[Spice-commits] 294 commits - .gitignore MAINTAINERS Makefile Makefile.objs Makefile.target QMP/qmp-events.txt arch_init.c block/Makefile.objs block/rbd.c block/sheepdog.c block/vhdx.c block/vhdx.h block/vmdk.c blockdev.c bsd-user/elfload.c bsd-user/main.c bsd-user/syscall.c configure cpus.c default-configs/i386-softmmu.mak default-configs/mips-softmmu.mak default-configs/mips64-softmmu.mak default-configs/mips64el-softmmu.mak default-configs/mipsel-softmmu.mak default-configs/pci.mak default-configs/ppc-softmmu.mak default-configs/ppc64-softmmu.mak default-configs/ppcemb-softmmu.mak default-configs/sound.mak default-configs/x86_64-softmmu.mak disas.c disas/arm.c docs/specs docs/tracing.txt docs/vnc-ledstate-Pseudo-encoding.txt dump-stub.c dump.c exec.c hmp-commands.hx hw/9pfs hw/acpi hw/arm hw/audio hw/block hw/char hw/core hw/cpu hw/display hw/dma hw/i386 hw/ide hw/input hw/intc hw/isa hw/mips hw/misc hw/moxie hw/net hw/nvram hw/pci-host hw/ppc hw/s390x hw/scsi hw/sparc64 hw/timer hw/unicore32 hw/usb hw/virtio hw/watchdog hw/xen include/block include/exec include/hw include/monitor include/qemu include/qemu-common.h include/qom include/sysemu include/ui kvm-all.c kvm-stub.c libcacard/cac.c libcacard/cac.h libcacard/vcard_emul_nss.c libcacard/vcardt.c libcacard/vcardt.h libcacard/vcardt_internal.h libcacard/vreader.c libcacard/vscclient.c linux-headers/asm-powerpc linux-headers/linux linux-user/elfload.c linux-user/main.c linux-user/syscall.c monitor.c nbd.c net/net.c net/tap.c pc-bios/README pc-bios/openbios-ppc pc-bios/openbios-sparc32 pc-bios/openbios-sparc64 pc-bios/s390-ccw pc-bios/s390-ccw.img qapi-schema.json qemu-char.c qemu-doc.texi qemu-options.hx qmp-commands.hx qmp.c qom/cpu.c qom/object.c roms/openbios rules.mak scripts/tracetool stubs/Makefile.objs stubs/cpus.c target-arm/kvm.c target-i386/arch_dump.c target-i386/cpu-qom.h target-i386/cpu.c target-i386/cpu.h target-i386/helper.c target-i386/kvm.c target-i386/misc_helper.c target-i386/tra nslate.c target-microblaze/cpu-qom.h target-microblaze/cpu.c target-microblaze/helper.c target-mips/dsp_helper.c target-ppc/cpu-qom.h target-ppc/cpu.h target-ppc/fpu_helper.c target-ppc/helper.h target-ppc/int_helper.c target-ppc/kvm.c target-ppc/kvm_ppc.h target-ppc/machine.c target-ppc/mem_helper.c target-ppc/translate.c target-ppc/translate_init.c target-s390x/cpu.h target-s390x/int_helper.c target-s390x/kvm.c target-s390x/translate.c tcg/arm tcg/tcg-op.h tcg/tcg.c tests/Makefile tests/libi2c-omap.c tests/libi2c.c tests/libi2c.h tests/libqos tests/libqtest.c tests/qemu-iotests tests/tcg tests/tmp105-test.c trace-events trace/Makefile.objs trace/ftrace.c trace/ftrace.h translate-all.c ui/cocoa.m ui/console.c ui/curses.c ui/gtk.c ui/input.c ui/sdl.c ui/spice-display.c ui/vnc-tls.c ui/vnc-ws.c ui/vnc-ws.h ui/vnc.c ui/vnc.h util/Makefile.objs util/crc32c.c util/cutils.c util/iov.c util/osdep.c util/qemu-config.c util/qemu-sockets.c vl.c

Gerd Hoffmann kraxel at kemper.freedesktop.org
Mon May 6 01:00:40 PDT 2013


 .gitignore                            |    2 
 MAINTAINERS                           |    6 
 Makefile                              |   25 
 Makefile.objs                         |    1 
 Makefile.target                       |   18 
 QMP/qmp-events.txt                    |   14 
 arch_init.c                           |  162 ---
 block/Makefile.objs                   |    1 
 block/rbd.c                           |    9 
 block/sheepdog.c                      |  308 ++++++-
 block/vhdx.c                          |  972 ++++++++++++++++++++++
 block/vhdx.h                          |  325 +++++++
 block/vmdk.c                          |  208 +++-
 blockdev.c                            |  124 ++
 bsd-user/elfload.c                    |    2 
 bsd-user/main.c                       |    4 
 bsd-user/syscall.c                    |    4 
 configure                             |   80 -
 cpus.c                                |   27 
 default-configs/i386-softmmu.mak      |    4 
 default-configs/mips-softmmu.mak      |    2 
 default-configs/mips64-softmmu.mak    |    2 
 default-configs/mips64el-softmmu.mak  |    2 
 default-configs/mipsel-softmmu.mak    |    2 
 default-configs/pci.mak               |    3 
 default-configs/ppc-softmmu.mak       |    2 
 default-configs/ppc64-softmmu.mak     |    2 
 default-configs/ppcemb-softmmu.mak    |    2 
 default-configs/sound.mak             |    4 
 default-configs/x86_64-softmmu.mak    |    4 
 disas.c                               |    1 
 disas/arm.c                           |    4 
 docs/specs/acpi_cpu_hotplug.txt       |   22 
 docs/specs/pvpanic.txt                |   39 
 docs/tracing.txt                      |   16 
 docs/vnc-ledstate-Pseudo-encoding.txt |   50 +
 dump-stub.c                           |   28 
 dump.c                                |    8 
 exec.c                                |   10 
 hmp-commands.hx                       |    4 
 hw/9pfs/virtio-9p-device.c            |    2 
 hw/acpi/ich9.c                        |    2 
 hw/acpi/piix4.c                       |   90 ++
 hw/arm/musicpal.c                     |    2 
 hw/audio/Makefile.objs                |   16 
 hw/audio/ac97.c                       |    3 
 hw/audio/adlib.c                      |   84 +
 hw/audio/cs4231a.c                    |    3 
 hw/audio/es1370.c                     |    3 
 hw/audio/gus.c                        |    3 
 hw/audio/intel-hda.c                  |   22 
 hw/audio/pcspk.c                      |   13 
 hw/audio/sb16.c                       |   17 
 hw/block/dataplane/virtio-blk.c       |   15 
 hw/block/fdc.c                        |   21 
 hw/block/pc_sysfw.c                   |   20 
 hw/block/virtio-blk.c                 |    9 
 hw/char/parallel.c                    |   11 
 hw/char/serial-isa.c                  |   11 
 hw/char/spapr_vty.c                   |   18 
 hw/char/virtio-serial-bus.c           |   11 
 hw/core/qdev.c                        |    3 
 hw/cpu/Makefile.objs                  |    1 
 hw/cpu/icc_bus.c                      |  119 ++
 hw/display/blizzard.c                 |    2 
 hw/display/cirrus_vga.c               |   19 
 hw/display/exynos4210_fimd.c          |    2 
 hw/display/g364fb.c                   |    2 
 hw/display/jazz_led.c                 |    2 
 hw/display/milkymist-vgafb.c          |    2 
 hw/display/omap_lcdc.c                |    2 
 hw/display/pl110.c                    |    2 
 hw/display/pxa2xx_lcd.c               |    2 
 hw/display/qxl.c                      |    8 
 hw/display/sm501.c                    |    2 
 hw/display/ssd0303.c                  |    2 
 hw/display/ssd0323.c                  |    2 
 hw/display/tc6393xb.c                 |    2 
 hw/display/tcx.c                      |    4 
 hw/display/vga-isa-mm.c               |    2 
 hw/display/vga-isa.c                  |   31 
 hw/display/vga-pci.c                  |    2 
 hw/display/vmware_vga.c               |    7 
 hw/display/xenfb.c                    |    2 
 hw/dma/i82374.c                       |   10 
 hw/i386/kvm/apic.c                    |    2 
 hw/i386/kvm/clock.c                   |    2 
 hw/i386/kvm/i8259.c                   |    2 
 hw/i386/kvmvapic.c                    |    1 
 hw/i386/pc.c                          |  102 ++
 hw/i386/pc_piix.c                     |   55 +
 hw/i386/pc_q35.c                      |   39 
 hw/ide/isa.c                          |   39 
 hw/input/hid.c                        |    4 
 hw/input/pckbd.c                      |   16 
 hw/input/vmmouse.c                    |   14 
 hw/intc/apic.c                        |    2 
 hw/intc/apic_common.c                 |   18 
 hw/intc/i8259.c                       |   16 
 hw/intc/i8259_common.c                |    8 
 hw/isa/lpc_ich9.c                     |    4 
 hw/mips/mips_jazz.c                   |    2 
 hw/mips/mips_malta.c                  |    3 
 hw/misc/Makefile.objs                 |    2 
 hw/misc/applesmc.c                    |   33 
 hw/misc/pvpanic.c                     |  144 +++
 hw/misc/sga.c                         |   10 
 hw/misc/vmport.c                      |   12 
 hw/moxie/moxiesim.c                   |    2 
 hw/net/ne2000-isa.c                   |   10 
 hw/net/spapr_llan.c                   |   24 
 hw/net/vhost_net.c                    |   17 
 hw/net/virtio-net.c                   |   27 
 hw/nvram/fw_cfg.c                     |    8 
 hw/nvram/spapr_nvram.c                |   10 
 hw/pci-host/apb.c                     |  118 ++
 hw/ppc/e500plat.c                     |    7 
 hw/ppc/mac_newworld.c                 |    2 
 hw/ppc/ppc_booke.c                    |   45 -
 hw/ppc/prep.c                         |    3 
 hw/ppc/spapr.c                        |   27 
 hw/ppc/spapr_vio.c                    |   41 
 hw/ppc/xics.c                         |    2 
 hw/s390x/ipl.c                        |   41 
 hw/s390x/s390-virtio-bus.c            |   96 +-
 hw/s390x/s390-virtio-bus.h            |   14 
 hw/s390x/s390-virtio-ccw.c            |    2 
 hw/s390x/s390-virtio.c                |    7 
 hw/s390x/s390-virtio.h                |    3 
 hw/s390x/virtio-ccw.c                 |  111 +-
 hw/s390x/virtio-ccw.h                 |   16 
 hw/scsi/esp-pci.c                     |    2 
 hw/scsi/esp.c                         |    2 
 hw/scsi/lsi53c895a.c                  |    2 
 hw/scsi/megasas.c                     |    2 
 hw/scsi/scsi-bus.c                    |    5 
 hw/scsi/spapr_vscsi.c                 |   17 
 hw/scsi/vhost-scsi.c                  |   18 
 hw/scsi/virtio-scsi.c                 |    9 
 hw/scsi/vmw_pvscsi.c                  |    2 
 hw/sparc64/sun4u.c                    |    2 
 hw/timer/m48t59.c                     |   35 
 hw/timer/mc146818rtc.c                |   43 -
 hw/unicore32/puv3.c                   |    2 
 hw/usb/ccid-card-emulated.c           |   19 
 hw/usb/ccid-card-passthru.c           |   63 +
 hw/usb/dev-audio.c                    |    1 
 hw/usb/dev-smartcard-reader.c         |  243 ++++-
 hw/usb/dev-storage.c                  |    4 
 hw/usb/dev-uas.c                      |    2 
 hw/virtio/vhost.c                     |   31 
 hw/virtio/virtio-balloon.c            |    8 
 hw/virtio/virtio-bus.c                |   40 
 hw/virtio/virtio-pci.c                |  297 ++----
 hw/virtio/virtio-pci.h                |   15 
 hw/virtio/virtio-rng.c                |  114 +-
 hw/virtio/virtio.c                    |  133 +--
 hw/watchdog/wdt_ib700.c               |   12 
 hw/xen/xen_apic.c                     |    2 
 include/block/nbd.h                   |    3 
 include/exec/exec-all.h               |   17 
 include/hw/acpi/ich9.h                |    2 
 include/hw/audio/audio.h              |   23 
 include/hw/audio/pcspk.h              |    6 
 include/hw/block/fdc.h                |    2 
 include/hw/boards.h                   |    3 
 include/hw/char/serial.h              |    1 
 include/hw/cpu/icc_bus.h              |   82 +
 include/hw/i386/apic_internal.h       |    8 
 include/hw/i386/ich9.h                |    2 
 include/hw/i386/pc.h                  |   11 
 include/hw/input/hid.h                |    1 
 include/hw/isa/i8259_internal.h       |    3 
 include/hw/nvram/fw_cfg.h             |    7 
 include/hw/scsi/scsi.h                |    3 
 include/hw/stream.h                   |    6 
 include/hw/timer/mc146818rtc.h        |    3 
 include/hw/virtio/virtio-bus.h        |    9 
 include/hw/virtio/virtio-rng.h        |   20 
 include/hw/virtio/virtio-scsi.h       |    1 
 include/hw/virtio/virtio.h            |   65 -
 include/monitor/monitor.h             |    1 
 include/qemu-common.h                 |   27 
 include/qemu/crc32c.h                 |   35 
 include/qemu/osdep.h                  |   17 
 include/qemu/timer.h                  |    4 
 include/qom/cpu.h                     |   77 +
 include/sysemu/arch_init.h            |    3 
 include/sysemu/dump.h                 |    9 
 include/sysemu/kvm.h                  |   24 
 include/sysemu/rng.h                  |    2 
 include/sysemu/sysemu.h               |    8 
 include/ui/console.h                  |   47 -
 kvm-all.c                             |    6 
 kvm-stub.c                            |    8 
 libcacard/cac.c                       |   80 +
 libcacard/cac.h                       |    8 
 libcacard/vcard_emul_nss.c            |   47 -
 libcacard/vcardt.c                    |   40 
 libcacard/vcardt.h                    |    5 
 libcacard/vcardt_internal.h           |    6 
 libcacard/vreader.c                   |   77 +
 libcacard/vscclient.c                 |  506 +++++++----
 linux-headers/asm-powerpc/kvm.h       |    5 
 linux-headers/linux/kvm.h             |    3 
 linux-user/elfload.c                  |    2 
 linux-user/main.c                     |    4 
 linux-user/syscall.c                  |    2 
 monitor.c                             |    3 
 nbd.c                                 |   36 
 net/net.c                             |    7 
 net/tap.c                             |    2 
 pc-bios/README                        |    4 
 pc-bios/openbios-ppc                  |binary
 pc-bios/openbios-sparc32              |binary
 pc-bios/openbios-sparc64              |binary
 pc-bios/s390-ccw.img                  |binary
 pc-bios/s390-ccw/Makefile             |   26 
 pc-bios/s390-ccw/bootmap.c            |  235 +++++
 pc-bios/s390-ccw/cio.h                |  322 +++++++
 pc-bios/s390-ccw/main.c               |   61 +
 pc-bios/s390-ccw/s390-ccw.h           |  134 +++
 pc-bios/s390-ccw/sclp-ascii.c         |   81 +
 pc-bios/s390-ccw/sclp.h               |  107 ++
 pc-bios/s390-ccw/start.S              |   31 
 pc-bios/s390-ccw/virtio.c             |  298 ++++++
 pc-bios/s390-ccw/virtio.h             |  163 +++
 qapi-schema.json                      |   84 +
 qemu-char.c                           |    2 
 qemu-doc.texi                         |    3 
 qemu-options.hx                       |    2 
 qmp-commands.hx                       |   72 +
 qmp.c                                 |   13 
 qom/cpu.c                             |  114 ++
 qom/object.c                          |   17 
 roms/openbios                         |    2 
 rules.mak                             |   13 
 scripts/tracetool/backend/ftrace.py   |   54 +
 stubs/Makefile.objs                   |    1 
 stubs/cpus.c                          |    5 
 target-arm/kvm.c                      |    4 
 target-i386/arch_dump.c               |   38 
 target-i386/cpu-qom.h                 |    9 
 target-i386/cpu.c                     |  520 +++++++-----
 target-i386/cpu.h                     |   19 
 target-i386/helper.c                  |    4 
 target-i386/kvm.c                     |    5 
 target-i386/misc_helper.c             |   14 
 target-i386/translate.c               |   10 
 target-microblaze/cpu-qom.h           |    1 
 target-microblaze/cpu.c               |    8 
 target-microblaze/helper.c            |    8 
 target-mips/dsp_helper.c              |   30 
 target-ppc/cpu-qom.h                  |    1 
 target-ppc/cpu.h                      |    6 
 target-ppc/fpu_helper.c               |   71 -
 target-ppc/helper.h                   |    4 
 target-ppc/int_helper.c               |   15 
 target-ppc/kvm.c                      |  237 +++++
 target-ppc/kvm_ppc.h                  |   30 
 target-ppc/machine.c                  |    2 
 target-ppc/mem_helper.c               |    2 
 target-ppc/translate.c                |  297 ++++++
 target-ppc/translate_init.c           |  117 +-
 target-s390x/cpu.h                    |   17 
 target-s390x/int_helper.c             |    3 
 target-s390x/kvm.c                    |   99 ++
 target-s390x/translate.c              |    2 
 tcg/arm/tcg-target.c                  | 1451 +++++++++++++++++++---------------
 tcg/arm/tcg-target.h                  |   14 
 tcg/tcg-op.h                          |    2 
 tcg/tcg.c                             |   10 
 tests/Makefile                        |    5 
 tests/libi2c-omap.c                   |  173 ----
 tests/libi2c.c                        |   22 
 tests/libi2c.h                        |   30 
 tests/libqos/fw_cfg.c                 |    7 
 tests/libqos/i2c-omap.c               |  173 ++++
 tests/libqos/i2c.c                    |   22 
 tests/libqos/i2c.h                    |   30 
 tests/libqtest.c                      |    2 
 tests/qemu-iotests/common.rc          |    3 
 tests/qemu-iotests/group              |    2 
 tests/tcg/mips/mips32-dsp/shll_ph.c   |   33 
 tests/tcg/mips/mips32-dsp/shll_qb.c   |   23 
 tests/tmp105-test.c                   |    2 
 trace-events                          |    9 
 trace/Makefile.objs                   |    1 
 trace/ftrace.c                        |  102 ++
 trace/ftrace.h                        |   10 
 translate-all.c                       |    1 
 ui/cocoa.m                            |    2 
 ui/console.c                          |   99 ++
 ui/curses.c                           |    2 
 ui/gtk.c                              |   95 +-
 ui/input.c                            |   55 +
 ui/sdl.c                              |    2 
 ui/spice-display.c                    |    2 
 ui/vnc-tls.c                          |   61 -
 ui/vnc-ws.c                           |   63 +
 ui/vnc-ws.h                           |    3 
 ui/vnc.c                              |  144 ++-
 ui/vnc.h                              |    8 
 util/Makefile.objs                    |    1 
 util/crc32c.c                         |  115 ++
 util/cutils.c                         |   23 
 util/iov.c                            |    2 
 util/osdep.c                          |   66 +
 util/qemu-config.c                    |   67 +
 util/qemu-sockets.c                   |   24 
 vl.c                                  |   43 -
 311 files changed, 10038 insertions(+), 3161 deletions(-)

New commits:
commit 467b34689d277fa56c09ad07ca0f08d7d7539f6d
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun May 5 09:53:22 2013 +0000

    Update OpenBIOS images
    
    Update OpenBIOS images to OpenBIOS 1.1 release (SVN r1136) built from
    submodule.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/pc-bios/README b/pc-bios/README
index eff3de7..7b4dfed 100644
--- a/pc-bios/README
+++ b/pc-bios/README
@@ -11,8 +11,8 @@
   firmware implementation. The goal is to implement a 100% IEEE
   1275-1994 (referred to as Open Firmware) compliant firmware.
   The included images for PowerPC (for 32 and 64 bit PPC CPUs),
-  Sparc32 and Sparc64 are built from OpenBIOS SVN revision
-  1063.
+  Sparc32 and Sparc64 are built from OpenBIOS 1.1 release (SVN
+  revision 1136).
 
 - SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware
   implementation for certain IBM POWER hardware.  The sources are at
diff --git a/pc-bios/openbios-ppc b/pc-bios/openbios-ppc
index 5311eca..77eb55d 100644
Binary files a/pc-bios/openbios-ppc and b/pc-bios/openbios-ppc differ
diff --git a/pc-bios/openbios-sparc32 b/pc-bios/openbios-sparc32
index 6bd8e45..c5ba6ae 100644
Binary files a/pc-bios/openbios-sparc32 and b/pc-bios/openbios-sparc32 differ
diff --git a/pc-bios/openbios-sparc64 b/pc-bios/openbios-sparc64
index 7c06fcc..c4aaa05 100644
Binary files a/pc-bios/openbios-sparc64 and b/pc-bios/openbios-sparc64 differ
diff --git a/roms/openbios b/roms/openbios
index f095c85..569e40c 160000
--- a/roms/openbios
+++ b/roms/openbios
@@ -1 +1 @@
-Subproject commit f095c858136896d236931357b8d597f407286f71
+Subproject commit 569e40c517e9623e672be38a21da7bcec046e3be
commit f7a87c42a05e5ecaa4ed9167178624f870106091
Merge: 120dc38 536f25e
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun May 5 09:05:34 2013 +0000

    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:
      target-arm: Fix incorrect check of kvm_vcpu_ioctl return value

commit 536f25e4c77592b936e50728c83894c23f4f61c8
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri May 3 18:47:22 2013 +0100

    target-arm: Fix incorrect check of kvm_vcpu_ioctl return value
    
    kvm_vcpu_ioctl() returns -ETHING on error, not ETHING -- correct
    an incorrect check in kvm_arch_init_vcpu(). This would not have
    had any significant ill-effects -- we would just have propagated
    the less useful ENOENT up to the caller rather than the more
    accurate EINVAL in the unlikely case that the kernel didn't
    have VFP-D32 support.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/kvm.c b/target-arm/kvm.c
index d8acace..b7bdc03 100644
--- a/target-arm/kvm.c
+++ b/target-arm/kvm.c
@@ -62,8 +62,8 @@ int kvm_arch_init_vcpu(CPUState *cs)
     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;
+    if (ret == -ENOENT) {
+        return -EINVAL;
     }
     return ret;
 }
commit 120dc38f6113b676ecef0a2c9e42fc08cace5bdb
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Fri May 3 15:25:36 2013 +0200

    qdev: skip bus check for bus-less devices in qdev_unplug()
    
    Since commit 2f7bd829db "qdev: Fix device_add bus assumptions"
    it's possible to device_add bus-less device, but if such device is
    unplugged it will dereference NULL parent_bus in qdev_unplug().
    
    Fix it by taking in account that parent_bus might be NULL and
    skipping bus check.
    
    Signed-off-by: Igor Mammedov <imammedo at redhat.com>
    Message-id: 1367587536-14964-1-git-send-email-imammedo at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index ab1d8f5..069ac90 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -208,7 +208,7 @@ void qdev_unplug(DeviceState *dev, Error **errp)
 {
     DeviceClass *dc = DEVICE_GET_CLASS(dev);
 
-    if (!dev->parent_bus->allow_hotplug) {
+    if (dev->parent_bus && !dev->parent_bus->allow_hotplug) {
         error_set(errp, QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
         return;
     }
commit 6f32a6b47ef4247ad14dad63c6ee231fdce4c5e9
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Tue Apr 30 16:08:51 2013 +0200

    virtio-scsi: fix the command line compatibility.
    
    The bus name is wrong since the refactoring.
    
    This keeps the behaviour of the command line.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1367330931-12994-6-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 83faf97..5a3d97c 100644
--- a/hw/s390x/s390-virtio-bus.c
+++ b/hw/s390x/s390-virtio-bus.c
@@ -235,6 +235,18 @@ static int s390_virtio_scsi_init(VirtIOS390Device *s390_dev)
 {
     VirtIOSCSIS390 *dev = VIRTIO_SCSI_S390(s390_dev);
     DeviceState *vdev = DEVICE(&dev->vdev);
+    DeviceState *qdev = DEVICE(s390_dev);
+    char *bus_name;
+
+    /*
+     * For command line compatibility, this sets the virtio-scsi-device bus
+     * name as before.
+     */
+    if (qdev->id) {
+        bus_name = g_strdup_printf("%s.0", qdev->id);
+        virtio_device_set_child_bus_name(VIRTIO_DEVICE(vdev), bus_name);
+        g_free(bus_name);
+    }
 
     qdev_set_parent_bus(vdev, BUS(&s390_dev->bus));
     if (qdev_init(vdev) < 0) {
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 4ebefd8..76e6d32 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -680,6 +680,18 @@ static int virtio_ccw_scsi_init(VirtioCcwDevice *ccw_dev)
 {
     VirtIOSCSICcw *dev = VIRTIO_SCSI_CCW(ccw_dev);
     DeviceState *vdev = DEVICE(&dev->vdev);
+    DeviceState *qdev = DEVICE(ccw_dev);
+    char *bus_name;
+
+    /*
+     * For command line compatibility, this sets the virtio-scsi-device bus
+     * name as before.
+     */
+    if (qdev->id) {
+        bus_name = g_strdup_printf("%s.0", qdev->id);
+        virtio_device_set_child_bus_name(VIRTIO_DEVICE(vdev), bus_name);
+        g_free(bus_name);
+    }
 
     qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
     if (qdev_init(vdev) < 0) {
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index f7ce743..08dd3f3 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -624,7 +624,8 @@ static int virtio_scsi_device_init(VirtIODevice *vdev)
         return ret;
     }
 
-    scsi_bus_new(&s->bus, qdev, &virtio_scsi_scsi_info, NULL);
+    scsi_bus_new(&s->bus, qdev, &virtio_scsi_scsi_info, vdev->bus_name);
+
     if (!qdev->hotplugged) {
         scsi_bus_legacy_handle_cmdline(&s->bus);
     }
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index abd2a3e..ec0066b 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -1106,11 +1106,23 @@ static int virtio_scsi_pci_init_pci(VirtIOPCIProxy *vpci_dev)
     VirtIOSCSIPCI *dev = VIRTIO_SCSI_PCI(vpci_dev);
     DeviceState *vdev = DEVICE(&dev->vdev);
     VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
+    DeviceState *proxy = DEVICE(vpci_dev);
+    char *bus_name;
 
     if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) {
         vpci_dev->nvectors = vs->conf.num_queues + 3;
     }
 
+    /*
+     * For command line compatibility, this sets the virtio-scsi-device bus
+     * name as before.
+     */
+    if (proxy->id) {
+        bus_name = g_strdup_printf("%s.0", proxy->id);
+        virtio_device_set_child_bus_name(VIRTIO_DEVICE(vdev), bus_name);
+        g_free(bus_name);
+    }
+
     qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
     if (qdev_init(vdev) < 0) {
         return -1;
diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h
index 4db346b..9a98540 100644
--- a/include/hw/virtio/virtio-scsi.h
+++ b/include/hw/virtio/virtio-scsi.h
@@ -189,5 +189,4 @@ typedef struct {
 int virtio_scsi_common_init(VirtIOSCSICommon *vs);
 int virtio_scsi_common_exit(VirtIOSCSICommon *vs);
 
-
 #endif /* _QEMU_VIRTIO_SCSI_H */
commit 80270a19685dd20eda017b0360c743b3e3ed6f57
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Tue Apr 30 16:08:50 2013 +0200

    virtio-serial: fix command line compatibility.
    
    The bus name is wrong since the refactoring.
    
    This keeps the behaviour of the command line.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1367330931-12994-5-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
index 3787ad2..cc3d1dd 100644
--- a/hw/char/virtio-serial-bus.c
+++ b/hw/char/virtio-serial-bus.c
@@ -911,7 +911,8 @@ static int virtio_serial_device_init(VirtIODevice *vdev)
                 sizeof(struct virtio_console_config));
 
     /* Spawn a new virtio-serial bus on which the ports will ride as devices */
-    qbus_create_inplace(&vser->bus.qbus, TYPE_VIRTIO_SERIAL_BUS, qdev, NULL);
+    qbus_create_inplace(&vser->bus.qbus, TYPE_VIRTIO_SERIAL_BUS, qdev,
+                        vdev->bus_name);
     vser->bus.qbus.allow_hotplug = 1;
     vser->bus.vser = vser;
     QTAILQ_INIT(&vser->ports);
diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c
index d52a547..83faf97 100644
--- a/hw/s390x/s390-virtio-bus.c
+++ b/hw/s390x/s390-virtio-bus.c
@@ -197,9 +197,20 @@ static int s390_virtio_serial_init(VirtIOS390Device *s390_dev)
     DeviceState *qdev = DEVICE(s390_dev);
     VirtIOS390Bus *bus;
     int r;
+    char *bus_name;
 
     bus = DO_UPCAST(VirtIOS390Bus, bus, qdev->parent_bus);
 
+    /*
+     * For command line compatibility, this sets the virtio-serial-device bus
+     * name as before.
+     */
+    if (qdev->id) {
+        bus_name = g_strdup_printf("%s.0", qdev->id);
+        virtio_device_set_child_bus_name(VIRTIO_DEVICE(vdev), bus_name);
+        g_free(bus_name);
+    }
+
     qdev_set_parent_bus(vdev, BUS(&s390_dev->bus));
     if (qdev_init(vdev) < 0) {
         return -1;
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index ef99080..4ebefd8 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -593,6 +593,18 @@ static int virtio_ccw_serial_init(VirtioCcwDevice *ccw_dev)
 {
     VirtioSerialCcw *dev = VIRTIO_SERIAL_CCW(ccw_dev);
     DeviceState *vdev = DEVICE(&dev->vdev);
+    DeviceState *proxy = DEVICE(ccw_dev);
+    char *bus_name;
+
+    /*
+     * For command line compatibility, this sets the virtio-serial-device bus
+     * name as before.
+     */
+    if (proxy->id) {
+        bus_name = g_strdup_printf("%s.0", proxy->id);
+        virtio_device_set_child_bus_name(VIRTIO_DEVICE(vdev), bus_name);
+        g_free(bus_name);
+    }
 
     qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
     if (qdev_init(vdev) < 0) {
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 070df44..abd2a3e 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -1297,6 +1297,8 @@ static int virtio_serial_pci_init(VirtIOPCIProxy *vpci_dev)
 {
     VirtIOSerialPCI *dev = VIRTIO_SERIAL_PCI(vpci_dev);
     DeviceState *vdev = DEVICE(&dev->vdev);
+    DeviceState *proxy = DEVICE(vpci_dev);
+    char *bus_name;
 
     if (vpci_dev->class_code != PCI_CLASS_COMMUNICATION_OTHER &&
         vpci_dev->class_code != PCI_CLASS_DISPLAY_OTHER && /* qemu 0.10 */
@@ -1310,6 +1312,16 @@ static int virtio_serial_pci_init(VirtIOPCIProxy *vpci_dev)
         vpci_dev->nvectors = dev->vdev.serial.max_virtserial_ports + 1;
     }
 
+    /*
+     * For command line compatibility, this sets the virtio-serial-device bus
+     * name as before.
+     */
+    if (proxy->id) {
+        bus_name = g_strdup_printf("%s.0", proxy->id);
+        virtio_device_set_child_bus_name(VIRTIO_DEVICE(vdev), bus_name);
+        g_free(bus_name);
+    }
+
     qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
     if (qdev_init(vdev) < 0) {
         return -1;
commit 11fc853c4cb5ab9db46d7859da191966199b588f
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Tue Apr 30 16:08:49 2013 +0200

    scsi: add bus_name parameter to scsi_bus_new.
    
    This adds the possibility to create a scsi-bus with a specified name.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Acked-by: Paolo Bonzini <pbonzini at redhat.com>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1367330931-12994-4-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/scsi/esp-pci.c b/hw/scsi/esp-pci.c
index 3ca5c8c..029789a 100644
--- a/hw/scsi/esp-pci.c
+++ b/hw/scsi/esp-pci.c
@@ -354,7 +354,7 @@ static int esp_pci_scsi_init(PCIDevice *dev)
     pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &pci->io);
     s->irq = pci->dev.irq[0];
 
-    scsi_bus_new(&s->bus, &dev->qdev, &esp_pci_scsi_info);
+    scsi_bus_new(&s->bus, &dev->qdev, &esp_pci_scsi_info, NULL);
     if (!dev->qdev.hotplugged) {
         return scsi_bus_legacy_handle_cmdline(&s->bus);
     }
diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 17adbec..0c81a50 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -681,7 +681,7 @@ static int sysbus_esp_init(SysBusDevice *dev)
 
     qdev_init_gpio_in(&dev->qdev, sysbus_esp_gpio_demux, 2);
 
-    scsi_bus_new(&s->bus, &dev->qdev, &esp_scsi_info);
+    scsi_bus_new(&s->bus, &dev->qdev, &esp_scsi_info, NULL);
     return scsi_bus_legacy_handle_cmdline(&s->bus);
 }
 
diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c
index c601b29..22b8e98 100644
--- a/hw/scsi/lsi53c895a.c
+++ b/hw/scsi/lsi53c895a.c
@@ -2099,7 +2099,7 @@ static int lsi_scsi_init(PCIDevice *dev)
     pci_register_bar(&s->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->ram_io);
     QTAILQ_INIT(&s->queue);
 
-    scsi_bus_new(&s->bus, &dev->qdev, &lsi_scsi_info);
+    scsi_bus_new(&s->bus, &dev->qdev, &lsi_scsi_info, NULL);
     if (!dev->qdev.hotplugged) {
         return scsi_bus_legacy_handle_cmdline(&s->bus);
     }
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index 14b0552..4934a81 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -2159,7 +2159,7 @@ static int megasas_scsi_init(PCIDevice *dev)
         s->frames[i].state = s;
     }
 
-    scsi_bus_new(&s->bus, &dev->qdev, &megasas_scsi_info);
+    scsi_bus_new(&s->bus, &dev->qdev, &megasas_scsi_info, NULL);
     scsi_bus_legacy_handle_cmdline(&s->bus);
     return 0;
 }
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index 6239ee1..53ea906 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -72,9 +72,10 @@ static void scsi_device_unit_attention_reported(SCSIDevice *s)
 }
 
 /* Create a scsi bus, and attach devices to it.  */
-void scsi_bus_new(SCSIBus *bus, DeviceState *host, const SCSIBusInfo *info)
+void scsi_bus_new(SCSIBus *bus, DeviceState *host, const SCSIBusInfo *info,
+                  const char *bus_name)
 {
-    qbus_create_inplace(&bus->qbus, TYPE_SCSI_BUS, host, NULL);
+    qbus_create_inplace(&bus->qbus, TYPE_SCSI_BUS, host, bus_name);
     bus->busnr = next_scsi_bus++;
     bus->info = info;
     bus->qbus.allow_hotplug = 1;
diff --git a/hw/scsi/spapr_vscsi.c b/hw/scsi/spapr_vscsi.c
index 3d322d5..e8978bf 100644
--- a/hw/scsi/spapr_vscsi.c
+++ b/hw/scsi/spapr_vscsi.c
@@ -915,7 +915,7 @@ static int spapr_vscsi_init(VIOsPAPRDevice *dev)
 
     dev->crq.SendFunc = vscsi_do_crq;
 
-    scsi_bus_new(&s->bus, &dev->qdev, &vscsi_scsi_info);
+    scsi_bus_new(&s->bus, &dev->qdev, &vscsi_scsi_info, NULL);
     if (!dev->qdev.hotplugged) {
         scsi_bus_legacy_handle_cmdline(&s->bus);
     }
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index 84b3ac7..f7ce743 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -624,7 +624,7 @@ static int virtio_scsi_device_init(VirtIODevice *vdev)
         return ret;
     }
 
-    scsi_bus_new(&s->bus, qdev, &virtio_scsi_scsi_info);
+    scsi_bus_new(&s->bus, qdev, &virtio_scsi_scsi_info, NULL);
     if (!qdev->hotplugged) {
         scsi_bus_legacy_handle_cmdline(&s->bus);
     }
diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
index 4b4a58f..48d12f4 100644
--- a/hw/scsi/vmw_pvscsi.c
+++ b/hw/scsi/vmw_pvscsi.c
@@ -1088,7 +1088,7 @@ pvscsi_init(PCIDevice *pci_dev)
         return -ENOMEM;
     }
 
-    scsi_bus_new(&s->bus, &pci_dev->qdev, &pvscsi_scsi_info);
+    scsi_bus_new(&s->bus, &pci_dev->qdev, &pvscsi_scsi_info, NULL);
     pvscsi_reset_state(s);
 
     return 0;
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index 06f0171..1073901 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -623,7 +623,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_bus_new(&s->bus, &s->dev.qdev, &usb_msd_scsi_info_storage, NULL);
     scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable,
                                             s->conf.bootindex, s->serial);
     if (!scsi_dev) {
@@ -650,7 +650,7 @@ static int usb_msd_initfn_bot(USBDevice *dev)
 
     usb_desc_create_serial(dev);
     usb_desc_init(dev);
-    scsi_bus_new(&s->bus, &s->dev.qdev, &usb_msd_scsi_info_bot);
+    scsi_bus_new(&s->bus, &s->dev.qdev, &usb_msd_scsi_info_bot, NULL);
     s->bus.qbus.allow_hotplug = 0;
     usb_msd_handle_reset(dev);
 
diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c
index c8c42ee..6efab62 100644
--- a/hw/usb/dev-uas.c
+++ b/hw/usb/dev-uas.c
@@ -888,7 +888,7 @@ static int usb_uas_init(USBDevice *dev)
     QTAILQ_INIT(&uas->requests);
     uas->status_bh = qemu_bh_new(usb_uas_send_status_bh, uas);
 
-    scsi_bus_new(&uas->bus, &uas->dev.qdev, &usb_uas_scsi_info);
+    scsi_bus_new(&uas->bus, &uas->dev.qdev, &usb_uas_scsi_info, NULL);
 
     return 0;
 }
diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h
index 3bda1c4..9786e00 100644
--- a/include/hw/scsi/scsi.h
+++ b/include/hw/scsi/scsi.h
@@ -152,7 +152,8 @@ struct SCSIBus {
     const SCSIBusInfo *info;
 };
 
-void scsi_bus_new(SCSIBus *bus, DeviceState *host, const SCSIBusInfo *info);
+void scsi_bus_new(SCSIBus *bus, DeviceState *host, const SCSIBusInfo *info,
+                  const char *bus_name);
 
 static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
 {
commit 1034e9cf4d0740c4c845d79998ac53a5b23e534d
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Tue Apr 30 16:08:48 2013 +0200

    virtio: add virtio_device_set_child_bus_name.
    
    Add virtio_device_set_child_bus_name function.
    
    It will be used with virtio-serial-x and virtio-scsi-x to set the
    child bus name before calling virtio-x-device's init.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1367330931-12994-3-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 0f88c25..53a0d90 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -1087,6 +1087,18 @@ EventNotifier *virtio_queue_get_host_notifier(VirtQueue *vq)
     return &vq->host_notifier;
 }
 
+void virtio_device_set_child_bus_name(VirtIODevice *vdev, char *bus_name)
+{
+    if (vdev->bus_name) {
+        g_free(vdev->bus_name);
+        vdev->bus_name = NULL;
+    }
+
+    if (bus_name) {
+        vdev->bus_name = g_strdup(bus_name);
+    }
+}
+
 static int virtio_device_init(DeviceState *qdev)
 {
     VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
@@ -1099,11 +1111,23 @@ static int virtio_device_init(DeviceState *qdev)
     return 0;
 }
 
+static int virtio_device_exit(DeviceState *qdev)
+{
+    VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
+
+    if (vdev->bus_name) {
+        g_free(vdev->bus_name);
+        vdev->bus_name = NULL;
+    }
+    return 0;
+}
+
 static void virtio_device_class_init(ObjectClass *klass, void *data)
 {
     /* Set the default value here. */
     DeviceClass *dc = DEVICE_CLASS(klass);
     dc->init = virtio_device_init;
+    dc->exit = virtio_device_exit;
     dc->bus_type = TYPE_VIRTIO_BUS;
 }
 
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index ae7a4c4..a6c5c53 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -118,6 +118,7 @@ struct VirtIODevice
     uint16_t device_id;
     bool vm_running;
     VMChangeStateEntry *vmstate;
+    char *bus_name;
 };
 
 typedef struct VirtioDeviceClass {
@@ -149,6 +150,9 @@ void virtio_init(VirtIODevice *vdev, const char *name,
                          uint16_t device_id, size_t config_size);
 void virtio_cleanup(VirtIODevice *vdev);
 
+/* Set the child bus name. */
+void virtio_device_set_child_bus_name(VirtIODevice *vdev, char *bus_name);
+
 VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size,
                             void (*handle_output)(VirtIODevice *,
                                                   VirtQueue *));
commit f4dd69aa4ce96196b3d84cd3d3e14a79ea029630
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Tue Apr 30 16:08:47 2013 +0200

    virtio-x-bus: force bus name to virtio-bus.
    
    When the proxy id is set, this bus takes the name "id.0" which is expected
    to be the virtio-device's first bus.
    
    So force this name to "virtio-bus" as it is an internal bus.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1367330931-12994-2-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 2cff6b7..d52a547 100644
--- a/hw/s390x/s390-virtio-bus.c
+++ b/hw/s390x/s390-virtio-bus.c
@@ -669,7 +669,10 @@ static void virtio_s390_bus_new(VirtioBusState *bus, VirtIOS390Device *dev)
 {
     DeviceState *qdev = DEVICE(dev);
     BusState *qbus;
-    qbus_create_inplace((BusState *)bus, TYPE_VIRTIO_S390_BUS, qdev, NULL);
+    char virtio_bus_name[] = "virtio-bus";
+
+    qbus_create_inplace((BusState *)bus, TYPE_VIRTIO_S390_BUS, qdev,
+                        virtio_bus_name);
     qbus = BUS(bus);
     qbus->allow_hotplug = 1;
 }
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index c0f2646..ef99080 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -1062,8 +1062,10 @@ static void virtio_ccw_bus_new(VirtioBusState *bus, VirtioCcwDevice *dev)
 {
     DeviceState *qdev = DEVICE(dev);
     BusState *qbus;
+    char virtio_bus_name[] = "virtio-bus";
 
-    qbus_create_inplace((BusState *)bus, TYPE_VIRTIO_CCW_BUS, qdev, NULL);
+    qbus_create_inplace((BusState *)bus, TYPE_VIRTIO_CCW_BUS, qdev,
+                        virtio_bus_name);
     qbus = BUS(bus);
     qbus->allow_hotplug = 1;
 }
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 41bb41e..070df44 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -1474,7 +1474,10 @@ static void virtio_pci_bus_new(VirtioBusState *bus, VirtIOPCIProxy *dev)
 {
     DeviceState *qdev = DEVICE(dev);
     BusState *qbus;
-    qbus_create_inplace((BusState *)bus, TYPE_VIRTIO_PCI_BUS, qdev, NULL);
+    char virtio_bus_name[] = "virtio-bus";
+
+    qbus_create_inplace((BusState *)bus, TYPE_VIRTIO_PCI_BUS, qdev,
+                        virtio_bus_name);
     qbus = BUS(bus);
     qbus->allow_hotplug = 1;
 }
commit 0057a0d59006d00c294de0b012d9a290eb1a5c80
Author: Tim Hardeck <thardeck at suse.de>
Date:   Tue Apr 23 16:33:01 2013 +0200

    TLS support for VNC Websockets
    
    Added TLS support to the VNC QEMU Websockets implementation.
    VNC-TLS needs to be enabled for this feature to be used.
    
    The required certificates are specified as in case of VNC-TLS
    with the VNC parameter "x509=<path>".
    
    If the server certificate isn't signed by a rooth authority it needs to
    be manually imported in the browser because at least in case of Firefox
    and Chrome there is no user dialog, the connection just gets canceled.
    
    As a side note VEncrypt over Websocket doesn't work atm because TLS can't
    be stacked in the current implementation. (It also didn't work before)
    Nevertheless to my knowledge there is no HTML 5 VNC client which supports
    it and the Websocket connection can be encrypted with regular TLS now so
    it should be fine for most use cases.
    
    Signed-off-by: Tim Hardeck <thardeck at suse.de>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1366727581-5772-1-git-send-email-thardeck at suse.de
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-options.hx b/qemu-options.hx
index e86cc24..fb62b75 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1127,6 +1127,8 @@ 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}.
+TLS encryption for the Websocket connection is supported if the required
+certificates are specified with the VNC option @option{x509}.
 
 @item password
 
diff --git a/ui/vnc-tls.c b/ui/vnc-tls.c
index 8d4cc8e..50275de 100644
--- a/ui/vnc-tls.c
+++ b/ui/vnc-tls.c
@@ -334,29 +334,38 @@ static int vnc_set_gnutls_priority(gnutls_session_t s, int x509)
 
 int vnc_tls_client_setup(struct VncState *vs,
                          int needX509Creds) {
+    VncStateTLS *tls;
 
     VNC_DEBUG("Do TLS setup\n");
+#ifdef CONFIG_VNC_WS
+    if (vs->websocket) {
+        tls = &vs->ws_tls;
+    } else
+#endif /* CONFIG_VNC_WS */
+    {
+        tls = &vs->tls;
+    }
     if (vnc_tls_initialize() < 0) {
         VNC_DEBUG("Failed to init TLS\n");
         vnc_client_error(vs);
         return -1;
     }
-    if (vs->tls.session == NULL) {
-        if (gnutls_init(&vs->tls.session, GNUTLS_SERVER) < 0) {
+    if (tls->session == NULL) {
+        if (gnutls_init(&tls->session, GNUTLS_SERVER) < 0) {
             vnc_client_error(vs);
             return -1;
         }
 
-        if (gnutls_set_default_priority(vs->tls.session) < 0) {
-            gnutls_deinit(vs->tls.session);
-            vs->tls.session = NULL;
+        if (gnutls_set_default_priority(tls->session) < 0) {
+            gnutls_deinit(tls->session);
+            tls->session = NULL;
             vnc_client_error(vs);
             return -1;
         }
 
-        if (vnc_set_gnutls_priority(vs->tls.session, needX509Creds) < 0) {
-            gnutls_deinit(vs->tls.session);
-            vs->tls.session = NULL;
+        if (vnc_set_gnutls_priority(tls->session, needX509Creds) < 0) {
+            gnutls_deinit(tls->session);
+            tls->session = NULL;
             vnc_client_error(vs);
             return -1;
         }
@@ -364,43 +373,43 @@ int vnc_tls_client_setup(struct VncState *vs,
         if (needX509Creds) {
             gnutls_certificate_server_credentials x509_cred = vnc_tls_initialize_x509_cred(vs->vd);
             if (!x509_cred) {
-                gnutls_deinit(vs->tls.session);
-                vs->tls.session = NULL;
+                gnutls_deinit(tls->session);
+                tls->session = NULL;
                 vnc_client_error(vs);
                 return -1;
             }
-            if (gnutls_credentials_set(vs->tls.session, GNUTLS_CRD_CERTIFICATE, x509_cred) < 0) {
-                gnutls_deinit(vs->tls.session);
-                vs->tls.session = NULL;
+            if (gnutls_credentials_set(tls->session, GNUTLS_CRD_CERTIFICATE, x509_cred) < 0) {
+                gnutls_deinit(tls->session);
+                tls->session = NULL;
                 gnutls_certificate_free_credentials(x509_cred);
                 vnc_client_error(vs);
                 return -1;
             }
             if (vs->vd->tls.x509verify) {
                 VNC_DEBUG("Requesting a client certificate\n");
-                gnutls_certificate_server_set_request (vs->tls.session, GNUTLS_CERT_REQUEST);
+                gnutls_certificate_server_set_request (tls->session, GNUTLS_CERT_REQUEST);
             }
 
         } else {
             gnutls_anon_server_credentials_t anon_cred = vnc_tls_initialize_anon_cred();
             if (!anon_cred) {
-                gnutls_deinit(vs->tls.session);
-                vs->tls.session = NULL;
+                gnutls_deinit(tls->session);
+                tls->session = NULL;
                 vnc_client_error(vs);
                 return -1;
             }
-            if (gnutls_credentials_set(vs->tls.session, GNUTLS_CRD_ANON, anon_cred) < 0) {
-                gnutls_deinit(vs->tls.session);
-                vs->tls.session = NULL;
+            if (gnutls_credentials_set(tls->session, GNUTLS_CRD_ANON, anon_cred) < 0) {
+                gnutls_deinit(tls->session);
+                tls->session = NULL;
                 gnutls_anon_free_server_credentials(anon_cred);
                 vnc_client_error(vs);
                 return -1;
             }
         }
 
-        gnutls_transport_set_ptr(vs->tls.session, (gnutls_transport_ptr_t)vs);
-        gnutls_transport_set_push_function(vs->tls.session, vnc_tls_push);
-        gnutls_transport_set_pull_function(vs->tls.session, vnc_tls_pull);
+        gnutls_transport_set_ptr(tls->session, (gnutls_transport_ptr_t)vs);
+        gnutls_transport_set_push_function(tls->session, vnc_tls_push);
+        gnutls_transport_set_pull_function(tls->session, vnc_tls_pull);
     }
     return 0;
 }
@@ -414,6 +423,14 @@ void vnc_tls_client_cleanup(struct VncState *vs)
     }
     vs->tls.wiremode = VNC_WIREMODE_CLEAR;
     g_free(vs->tls.dname);
+#ifdef CONFIG_VNC_WS
+    if (vs->ws_tls.session) {
+        gnutls_deinit(vs->ws_tls.session);
+        vs->ws_tls.session = NULL;
+    }
+    vs->ws_tls.wiremode = VNC_WIREMODE_CLEAR;
+    g_free(vs->ws_tls.dname);
+#endif /* CONFIG_VNC_WS */
 }
 
 
diff --git a/ui/vnc-ws.c b/ui/vnc-ws.c
index 3e30209..df89315 100644
--- a/ui/vnc-ws.c
+++ b/ui/vnc-ws.c
@@ -20,6 +20,69 @@
 
 #include "vnc.h"
 
+#ifdef CONFIG_VNC_TLS
+#include "qemu/sockets.h"
+
+static void vncws_tls_handshake_io(void *opaque);
+
+static int vncws_start_tls_handshake(struct VncState *vs)
+{
+    int ret = gnutls_handshake(vs->ws_tls.session);
+
+    if (ret < 0) {
+        if (!gnutls_error_is_fatal(ret)) {
+            VNC_DEBUG("Handshake interrupted (blocking)\n");
+            if (!gnutls_record_get_direction(vs->ws_tls.session)) {
+                qemu_set_fd_handler(vs->csock, vncws_tls_handshake_io,
+                                    NULL, vs);
+            } else {
+                qemu_set_fd_handler(vs->csock, NULL, vncws_tls_handshake_io,
+                                    vs);
+            }
+            return 0;
+        }
+        VNC_DEBUG("Handshake failed %s\n", gnutls_strerror(ret));
+        vnc_client_error(vs);
+        return -1;
+    }
+
+    VNC_DEBUG("Handshake done, switching to TLS data mode\n");
+    vs->ws_tls.wiremode = VNC_WIREMODE_TLS;
+    qemu_set_fd_handler2(vs->csock, NULL, vncws_handshake_read, NULL, vs);
+
+    return 0;
+}
+
+static void vncws_tls_handshake_io(void *opaque)
+{
+    struct VncState *vs = (struct VncState *)opaque;
+
+    VNC_DEBUG("Handshake IO continue\n");
+    vncws_start_tls_handshake(vs);
+}
+
+void vncws_tls_handshake_peek(void *opaque)
+{
+    VncState *vs = opaque;
+    long ret;
+
+    if (!vs->ws_tls.session) {
+        char peek[4];
+        ret = qemu_recv(vs->csock, peek, sizeof(peek), MSG_PEEK);
+        if (ret && (strncmp(peek, "\x16", 1) == 0
+                    || strncmp(peek, "\x80", 1) == 0)) {
+            VNC_DEBUG("TLS Websocket connection recognized");
+            vnc_tls_client_setup(vs, 1);
+            vncws_start_tls_handshake(vs);
+        } else {
+            vncws_handshake_read(vs);
+        }
+    } else {
+        qemu_set_fd_handler2(vs->csock, NULL, vncws_handshake_read, NULL, vs);
+    }
+}
+#endif /* CONFIG_VNC_TLS */
+
 void vncws_handshake_read(void *opaque)
 {
     VncState *vs = opaque;
diff --git a/ui/vnc-ws.h b/ui/vnc-ws.h
index 039a587..95c1b0a 100644
--- a/ui/vnc-ws.h
+++ b/ui/vnc-ws.h
@@ -74,6 +74,9 @@ enum {
     WS_OPCODE_PONG = 0xA
 };
 
+#ifdef CONFIG_VNC_TLS
+void vncws_tls_handshake_peek(void *opaque);
+#endif /* CONFIG_VNC_TLS */
 void vncws_handshake_read(void *opaque);
 long vnc_client_write_ws(VncState *vs);
 long vnc_client_read_ws(VncState *vs);
diff --git a/ui/vnc.c b/ui/vnc.c
index b90281b..89108de 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -1111,6 +1111,23 @@ void vnc_client_error(VncState *vs)
     vnc_disconnect_start(vs);
 }
 
+#ifdef CONFIG_VNC_TLS
+static long vnc_client_write_tls(gnutls_session_t *session,
+                                 const uint8_t *data,
+                                 size_t datalen)
+{
+    long ret = gnutls_write(*session, data, datalen);
+    if (ret < 0) {
+        if (ret == GNUTLS_E_AGAIN) {
+            errno = EAGAIN;
+        } else {
+            errno = EIO;
+        }
+        ret = -1;
+    }
+    return ret;
+}
+#endif /* CONFIG_VNC_TLS */
 
 /*
  * Called to write a chunk of data to the client socket. The data may
@@ -1132,17 +1149,20 @@ long vnc_client_write_buf(VncState *vs, const uint8_t *data, size_t datalen)
     long ret;
 #ifdef CONFIG_VNC_TLS
     if (vs->tls.session) {
-        ret = gnutls_write(vs->tls.session, data, datalen);
-        if (ret < 0) {
-            if (ret == GNUTLS_E_AGAIN)
-                errno = EAGAIN;
-            else
-                errno = EIO;
-            ret = -1;
+        ret = vnc_client_write_tls(&vs->tls.session, data, datalen);
+    } else {
+#ifdef CONFIG_VNC_WS
+        if (vs->ws_tls.session) {
+            ret = vnc_client_write_tls(&vs->ws_tls.session, data, datalen);
+        } else
+#endif /* CONFIG_VNC_WS */
+#endif /* CONFIG_VNC_TLS */
+        {
+            ret = send(vs->csock, (const void *)data, datalen, 0);
         }
-    } else
+#ifdef CONFIG_VNC_TLS
+    }
 #endif /* CONFIG_VNC_TLS */
-        ret = send(vs->csock, (const void *)data, datalen, 0);
     VNC_DEBUG("Wrote wire %p %zd -> %ld\n", data, datalen, ret);
     return vnc_client_io_error(vs, ret, socket_error());
 }
@@ -1240,6 +1260,22 @@ void vnc_read_when(VncState *vs, VncReadEvent *func, size_t expecting)
     vs->read_handler_expect = expecting;
 }
 
+#ifdef CONFIG_VNC_TLS
+static long vnc_client_read_tls(gnutls_session_t *session, uint8_t *data,
+                                size_t datalen)
+{
+    long ret = gnutls_read(*session, data, datalen);
+    if (ret < 0) {
+        if (ret == GNUTLS_E_AGAIN) {
+            errno = EAGAIN;
+        } else {
+            errno = EIO;
+        }
+        ret = -1;
+    }
+    return ret;
+}
+#endif /* CONFIG_VNC_TLS */
 
 /*
  * Called to read a chunk of data from the client socket. The data may
@@ -1261,17 +1297,20 @@ long vnc_client_read_buf(VncState *vs, uint8_t *data, size_t datalen)
     long ret;
 #ifdef CONFIG_VNC_TLS
     if (vs->tls.session) {
-        ret = gnutls_read(vs->tls.session, data, datalen);
-        if (ret < 0) {
-            if (ret == GNUTLS_E_AGAIN)
-                errno = EAGAIN;
-            else
-                errno = EIO;
-            ret = -1;
+        ret = vnc_client_read_tls(&vs->tls.session, data, datalen);
+    } else {
+#ifdef CONFIG_VNC_WS
+        if (vs->ws_tls.session) {
+            ret = vnc_client_read_tls(&vs->ws_tls.session, data, datalen);
+        } else
+#endif /* CONFIG_VNC_WS */
+#endif /* CONFIG_VNC_TLS */
+        {
+            ret = qemu_recv(vs->csock, data, datalen, 0);
         }
-    } else
+#ifdef CONFIG_VNC_TLS
+    }
 #endif /* CONFIG_VNC_TLS */
-        ret = qemu_recv(vs->csock, data, datalen, 0);
     VNC_DEBUG("Read wire %p %zd -> %ld\n", data, datalen, ret);
     return vnc_client_io_error(vs, ret, socket_error());
 }
@@ -2761,7 +2800,16 @@ static void vnc_connect(VncDisplay *vd, int csock, int skipauth, bool websocket)
 #ifdef CONFIG_VNC_WS
     if (websocket) {
         vs->websocket = 1;
-        qemu_set_fd_handler2(vs->csock, NULL, vncws_handshake_read, NULL, vs);
+#ifdef CONFIG_VNC_TLS
+        if (vd->tls.x509cert) {
+            qemu_set_fd_handler2(vs->csock, NULL, vncws_tls_handshake_peek,
+                                 NULL, vs);
+        } else
+#endif /* CONFIG_VNC_TLS */
+        {
+            qemu_set_fd_handler2(vs->csock, NULL, vncws_handshake_read,
+                                 NULL, vs);
+        }
     } else
 #endif /* CONFIG_VNC_WS */
     {
diff --git a/ui/vnc.h b/ui/vnc.h
index fea39ad..6e99213 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -276,9 +276,12 @@ struct VncState
     VncStateSASL sasl;
 #endif
 #ifdef CONFIG_VNC_WS
+#ifdef CONFIG_VNC_TLS
+    VncStateTLS ws_tls;
+#endif /* CONFIG_VNC_TLS */
     bool encode_ws;
     bool websocket;
-#endif
+#endif /* CONFIG_VNC_WS */
 
     QObject *info;
 
commit 8f3b664f6cc4153cc73941c941d54c4e499b7537
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed May 1 16:14:34 2013 +0200

    audio: Enable all cards
    
    ...or they will bitrot to death.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Message-id: 5181234A.6060504 at web.de
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/default-configs/sound.mak b/default-configs/sound.mak
index ff69c4d..4f22c34 100644
--- a/default-configs/sound.mak
+++ b/default-configs/sound.mak
@@ -1,4 +1,4 @@
 CONFIG_SB16=y
-#CONFIG_ADLIB=y
-#CONFIG_GUS=y
-#CONFIG_CS4231A=y
+CONFIG_ADLIB=y
+CONFIG_GUS=y
+CONFIG_CS4231A=y
commit fba90ac1d614c333c6a15c39cac555a12a04cee1
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed May 1 18:30:15 2013 +0200

    win32: fix compilation again
    
    While commit c02817e5bfbb27955cac970019e6670dc427bc41 fixed compilation
    without an installed libtool, moving the dependencies to rules.mak does
    not work because the version-*-y variables are not defined yet.  Building
    in a clean tree thus fails.
    
    Revert the commit and remove the dummy /bin/false assignment to LIBTOOL.
    This makes the build work, at the price of slightly worse errors when
    there are Makefile bugs.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Message-id: 1367425815-15083-1-git-send-email-pbonzini at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/Makefile b/Makefile
index f91f3b0..7dc0204 100644
--- a/Makefile
+++ b/Makefile
@@ -172,6 +172,7 @@ version.lo: $(SRC_PATH)/version.rc config-host.h
 version-obj-$(CONFIG_WIN32) += version.o
 version-lobj-$(CONFIG_WIN32) += version.lo
 
+Makefile: $(version-obj-y) $(version-lobj-y)
 
 ######################################################################
 # Build libraries
diff --git a/rules.mak b/rules.mak
index b21383b..4499745 100644
--- a/rules.mak
+++ b/rules.mak
@@ -22,15 +22,11 @@ QEMU_INCLUDES += -I$(<D) -I$(@D)
 %.o: %.rc
 	$(call quiet-command,$(WINDRES) -I. -o $@ $<,"  RC    $(TARGET_DIR)$@")
 
-Makefile: $(version-obj-y)
-
 ifeq ($(LIBTOOL),)
-LIBTOOL = /bin/false
 LINK = $(call quiet-command,$(CC) $(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ \
        $(sort $(filter %.o, $1)) $(filter-out %.o, $1) $(version-obj-y) \
        $(LIBS),"  LINK  $(TARGET_DIR)$@")
 else
-Makefile: $(version-lobj-y)
 LIBTOOL += $(if $(V),,--quiet)
 %.lo: %.c
 	$(call quiet-command,$(LIBTOOL) --mode=compile --tag=CC $(CC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<,"  lt CC $@")
@@ -74,7 +70,7 @@ quiet-command = $(if $(V),$1,$(if $(2), at echo $2 && $1, @$1))
 cc-option = $(if $(shell $(CC) $1 $2 -S -o /dev/null -xc /dev/null \
               >/dev/null 2>&1 && echo OK), $2, $3)
 
-VPATH_SUFFIXES = %.c %.h %.S %.m %.mak %.texi %.sh
+VPATH_SUFFIXES = %.c %.h %.S %.m %.mak %.texi %.sh %.rc
 set-vpath = $(if $1,$(foreach PATTERN,$(VPATH_SUFFIXES),$(eval vpath $(PATTERN) $1)))
 
 # find-in-path
commit cc9936a32f91c107a2a7655af4feeee3f4de5d12
Author: Andreas Färber <afaerber at suse.de>
Date:   Thu May 2 15:56:26 2013 +0200

    libqos: Relocate I2C files
    
    Commit c4efe1cada311b9dc0df5beb71c4227ff3414aa1 (qtest: add libqos
    including PCI support) created a libqos/ subdirectory but left the
    existing I2C libqos files libi2c*.[hc] in tests/. Clean this up.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Message-id: 1367502986-15104-1-git-send-email-afaerber at suse.de
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/tests/Makefile b/tests/Makefile
index 72bf2cd..bf41d10 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -119,14 +119,16 @@ tests/test-visitor-serialization$(EXESUF): tests/test-visitor-serialization.o $(
 tests/test-mul64$(EXESUF): tests/test-mul64.o libqemuutil.a
 
 libqos-obj-y = tests/libqos/pci.o tests/libqos/fw_cfg.o
+libqos-obj-y += tests/libqos/i2c.o
 libqos-pc-obj-y = $(libqos-obj-y) tests/libqos/pci-pc.o tests/libqos/fw_cfg-pc.o
 libqos-pc-obj-y += tests/libqos/malloc-pc.o
+libqos-omap-obj-y = $(libqos-obj-y) tests/libqos/i2c-omap.o
 
 tests/rtc-test$(EXESUF): tests/rtc-test.o
 tests/m48t59-test$(EXESUF): tests/m48t59-test.o
 tests/fdc-test$(EXESUF): tests/fdc-test.o
 tests/hd-geo-test$(EXESUF): tests/hd-geo-test.o
-tests/tmp105-test$(EXESUF): tests/tmp105-test.o
+tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y)
 tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y)
 tests/fw_cfg-test$(EXESUF): tests/fw_cfg-test.o $(libqos-pc-obj-y)
 
@@ -137,7 +139,6 @@ QTEST_TARGETS=$(foreach TARGET,$(TARGETS), $(if $(check-qtest-$(TARGET)-y), $(TA
 check-qtest-$(CONFIG_POSIX)=$(foreach TARGET,$(TARGETS), $(check-qtest-$(TARGET)-y))
 
 qtest-obj-y = tests/libqtest.o libqemuutil.a libqemustub.a
-qtest-obj-y += tests/libi2c.o tests/libi2c-omap.o
 $(check-qtest-y): $(qtest-obj-y)
 
 .PHONY: check-help
diff --git a/tests/libi2c-omap.c b/tests/libi2c-omap.c
deleted file mode 100644
index c52458c..0000000
--- a/tests/libi2c-omap.c
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * QTest I2C driver
- *
- * Copyright (c) 2012 Andreas Färber
- *
- * 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 "libi2c.h"
-
-#include <glib.h>
-#include <string.h>
-
-#include "qemu/osdep.h"
-#include "qemu/bswap.h"
-#include "libqtest.h"
-
-enum OMAPI2CRegisters {
-    OMAP_I2C_REV  = 0x00,
-    OMAP_I2C_STAT = 0x08,
-    OMAP_I2C_CNT  = 0x18,
-    OMAP_I2C_DATA = 0x1c,
-    OMAP_I2C_CON  = 0x24,
-    OMAP_I2C_SA   = 0x2c,
-};
-
-enum OMAPI2CSTATBits {
-    OMAP_I2C_STAT_NACK = 1 << 1,
-    OMAP_I2C_STAT_ARDY = 1 << 2,
-    OMAP_I2C_STAT_RRDY = 1 << 3,
-    OMAP_I2C_STAT_XRDY = 1 << 4,
-    OMAP_I2C_STAT_ROVR = 1 << 11,
-    OMAP_I2C_STAT_SBD  = 1 << 15,
-};
-
-enum OMAPI2CCONBits {
-    OMAP_I2C_CON_STT    = 1 << 0,
-    OMAP_I2C_CON_STP    = 1 << 1,
-    OMAP_I2C_CON_TRX    = 1 << 9,
-    OMAP_I2C_CON_MST    = 1 << 10,
-    OMAP_I2C_CON_BE     = 1 << 14,
-    OMAP_I2C_CON_I2C_EN = 1 << 15,
-};
-
-typedef struct OMAPI2C {
-    I2CAdapter parent;
-
-    uint64_t addr;
-} OMAPI2C;
-
-
-static void omap_i2c_set_slave_addr(OMAPI2C *s, uint8_t addr)
-{
-    uint16_t data = addr;
-
-    writew(s->addr + OMAP_I2C_SA, data);
-    data = readw(s->addr + OMAP_I2C_SA);
-    g_assert_cmphex(data, ==, addr);
-}
-
-static void omap_i2c_send(I2CAdapter *i2c, uint8_t addr,
-                          const uint8_t *buf, uint16_t len)
-{
-    OMAPI2C *s = (OMAPI2C *)i2c;
-    uint16_t data;
-
-    omap_i2c_set_slave_addr(s, addr);
-
-    data = len;
-    writew(s->addr + OMAP_I2C_CNT, data);
-
-    data = OMAP_I2C_CON_I2C_EN |
-           OMAP_I2C_CON_TRX |
-           OMAP_I2C_CON_MST |
-           OMAP_I2C_CON_STT |
-           OMAP_I2C_CON_STP;
-    writew(s->addr + OMAP_I2C_CON, data);
-    data = readw(s->addr + OMAP_I2C_CON);
-    g_assert((data & OMAP_I2C_CON_STP) != 0);
-
-    data = readw(s->addr + OMAP_I2C_STAT);
-    g_assert((data & OMAP_I2C_STAT_NACK) == 0);
-
-    while (len > 1) {
-        data = readw(s->addr + OMAP_I2C_STAT);
-        g_assert((data & OMAP_I2C_STAT_XRDY) != 0);
-
-        data = buf[0] | ((uint16_t)buf[1] << 8);
-        writew(s->addr + OMAP_I2C_DATA, data);
-        buf = (uint8_t *)buf + 2;
-        len -= 2;
-    }
-    if (len == 1) {
-        data = readw(s->addr + OMAP_I2C_STAT);
-        g_assert((data & OMAP_I2C_STAT_XRDY) != 0);
-
-        data = buf[0];
-        writew(s->addr + OMAP_I2C_DATA, data);
-    }
-
-    data = readw(s->addr + OMAP_I2C_CON);
-    g_assert((data & OMAP_I2C_CON_STP) == 0);
-}
-
-static void omap_i2c_recv(I2CAdapter *i2c, uint8_t addr,
-                          uint8_t *buf, uint16_t len)
-{
-    OMAPI2C *s = (OMAPI2C *)i2c;
-    uint16_t data, stat;
-
-    omap_i2c_set_slave_addr(s, addr);
-
-    data = len;
-    writew(s->addr + OMAP_I2C_CNT, data);
-
-    data = OMAP_I2C_CON_I2C_EN |
-           OMAP_I2C_CON_MST |
-           OMAP_I2C_CON_STT |
-           OMAP_I2C_CON_STP;
-    writew(s->addr + OMAP_I2C_CON, data);
-    data = readw(s->addr + OMAP_I2C_CON);
-    g_assert((data & OMAP_I2C_CON_STP) == 0);
-
-    data = readw(s->addr + OMAP_I2C_STAT);
-    g_assert((data & OMAP_I2C_STAT_NACK) == 0);
-
-    data = readw(s->addr + OMAP_I2C_CNT);
-    g_assert_cmpuint(data, ==, len);
-
-    while (len > 0) {
-        data = readw(s->addr + OMAP_I2C_STAT);
-        g_assert((data & OMAP_I2C_STAT_RRDY) != 0);
-        g_assert((data & OMAP_I2C_STAT_ROVR) == 0);
-
-        data = readw(s->addr + OMAP_I2C_DATA);
-
-        stat = readw(s->addr + OMAP_I2C_STAT);
-
-        if (unlikely(len == 1)) {
-            g_assert((stat & OMAP_I2C_STAT_SBD) != 0);
-
-            buf[0] = data & 0xff;
-            buf++;
-            len--;
-        } else {
-            buf[0] = data & 0xff;
-            buf[1] = data >> 8;
-            buf += 2;
-            len -= 2;
-        }
-    }
-
-    data = readw(s->addr + OMAP_I2C_CON);
-    g_assert((data & OMAP_I2C_CON_STP) == 0);
-}
-
-I2CAdapter *omap_i2c_create(uint64_t addr)
-{
-    OMAPI2C *s = g_malloc0(sizeof(*s));
-    I2CAdapter *i2c = (I2CAdapter *)s;
-    uint16_t data;
-
-    s->addr = addr;
-
-    i2c->send = omap_i2c_send;
-    i2c->recv = omap_i2c_recv;
-
-    /* verify the mmio address by looking for a known signature */
-    data = readw(addr + OMAP_I2C_REV);
-    g_assert_cmphex(data, ==, 0x34);
-
-    return i2c;
-}
diff --git a/tests/libi2c.c b/tests/libi2c.c
deleted file mode 100644
index 13ec85c..0000000
--- a/tests/libi2c.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * QTest I2C driver
- *
- * Copyright (c) 2012 Andreas Färber
- *
- * 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 "libi2c.h"
-#include "libqtest.h"
-
-void i2c_send(I2CAdapter *i2c, uint8_t addr,
-              const uint8_t *buf, uint16_t len)
-{
-    i2c->send(i2c, addr, buf, len);
-}
-
-void i2c_recv(I2CAdapter *i2c, uint8_t addr,
-              uint8_t *buf, uint16_t len)
-{
-    i2c->recv(i2c, addr, buf, len);
-}
diff --git a/tests/libi2c.h b/tests/libi2c.h
deleted file mode 100644
index 1ce9af4..0000000
--- a/tests/libi2c.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * I2C libqos
- *
- * Copyright (c) 2012 Andreas Färber
- *
- * 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 LIBQOS_I2C_H
-#define LIBQOS_I2C_H
-
-#include <stdint.h>
-
-typedef struct I2CAdapter I2CAdapter;
-struct I2CAdapter {
-    void (*send)(I2CAdapter *adapter, uint8_t addr,
-                 const uint8_t *buf, uint16_t len);
-    void (*recv)(I2CAdapter *adapter, uint8_t addr,
-                 uint8_t *buf, uint16_t len);
-};
-
-void i2c_send(I2CAdapter *i2c, uint8_t addr,
-              const uint8_t *buf, uint16_t len);
-void i2c_recv(I2CAdapter *i2c, uint8_t addr,
-              uint8_t *buf, uint16_t len);
-
-/* libi2c-omap.c */
-I2CAdapter *omap_i2c_create(uint64_t addr);
-
-#endif
diff --git a/tests/libqos/i2c-omap.c b/tests/libqos/i2c-omap.c
new file mode 100644
index 0000000..3d4d45d
--- /dev/null
+++ b/tests/libqos/i2c-omap.c
@@ -0,0 +1,173 @@
+/*
+ * QTest I2C driver
+ *
+ * Copyright (c) 2012 Andreas Färber
+ *
+ * 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 "libqos/i2c.h"
+
+#include <glib.h>
+#include <string.h>
+
+#include "qemu/osdep.h"
+#include "qemu/bswap.h"
+#include "libqtest.h"
+
+enum OMAPI2CRegisters {
+    OMAP_I2C_REV  = 0x00,
+    OMAP_I2C_STAT = 0x08,
+    OMAP_I2C_CNT  = 0x18,
+    OMAP_I2C_DATA = 0x1c,
+    OMAP_I2C_CON  = 0x24,
+    OMAP_I2C_SA   = 0x2c,
+};
+
+enum OMAPI2CSTATBits {
+    OMAP_I2C_STAT_NACK = 1 << 1,
+    OMAP_I2C_STAT_ARDY = 1 << 2,
+    OMAP_I2C_STAT_RRDY = 1 << 3,
+    OMAP_I2C_STAT_XRDY = 1 << 4,
+    OMAP_I2C_STAT_ROVR = 1 << 11,
+    OMAP_I2C_STAT_SBD  = 1 << 15,
+};
+
+enum OMAPI2CCONBits {
+    OMAP_I2C_CON_STT    = 1 << 0,
+    OMAP_I2C_CON_STP    = 1 << 1,
+    OMAP_I2C_CON_TRX    = 1 << 9,
+    OMAP_I2C_CON_MST    = 1 << 10,
+    OMAP_I2C_CON_BE     = 1 << 14,
+    OMAP_I2C_CON_I2C_EN = 1 << 15,
+};
+
+typedef struct OMAPI2C {
+    I2CAdapter parent;
+
+    uint64_t addr;
+} OMAPI2C;
+
+
+static void omap_i2c_set_slave_addr(OMAPI2C *s, uint8_t addr)
+{
+    uint16_t data = addr;
+
+    writew(s->addr + OMAP_I2C_SA, data);
+    data = readw(s->addr + OMAP_I2C_SA);
+    g_assert_cmphex(data, ==, addr);
+}
+
+static void omap_i2c_send(I2CAdapter *i2c, uint8_t addr,
+                          const uint8_t *buf, uint16_t len)
+{
+    OMAPI2C *s = (OMAPI2C *)i2c;
+    uint16_t data;
+
+    omap_i2c_set_slave_addr(s, addr);
+
+    data = len;
+    writew(s->addr + OMAP_I2C_CNT, data);
+
+    data = OMAP_I2C_CON_I2C_EN |
+           OMAP_I2C_CON_TRX |
+           OMAP_I2C_CON_MST |
+           OMAP_I2C_CON_STT |
+           OMAP_I2C_CON_STP;
+    writew(s->addr + OMAP_I2C_CON, data);
+    data = readw(s->addr + OMAP_I2C_CON);
+    g_assert((data & OMAP_I2C_CON_STP) != 0);
+
+    data = readw(s->addr + OMAP_I2C_STAT);
+    g_assert((data & OMAP_I2C_STAT_NACK) == 0);
+
+    while (len > 1) {
+        data = readw(s->addr + OMAP_I2C_STAT);
+        g_assert((data & OMAP_I2C_STAT_XRDY) != 0);
+
+        data = buf[0] | ((uint16_t)buf[1] << 8);
+        writew(s->addr + OMAP_I2C_DATA, data);
+        buf = (uint8_t *)buf + 2;
+        len -= 2;
+    }
+    if (len == 1) {
+        data = readw(s->addr + OMAP_I2C_STAT);
+        g_assert((data & OMAP_I2C_STAT_XRDY) != 0);
+
+        data = buf[0];
+        writew(s->addr + OMAP_I2C_DATA, data);
+    }
+
+    data = readw(s->addr + OMAP_I2C_CON);
+    g_assert((data & OMAP_I2C_CON_STP) == 0);
+}
+
+static void omap_i2c_recv(I2CAdapter *i2c, uint8_t addr,
+                          uint8_t *buf, uint16_t len)
+{
+    OMAPI2C *s = (OMAPI2C *)i2c;
+    uint16_t data, stat;
+
+    omap_i2c_set_slave_addr(s, addr);
+
+    data = len;
+    writew(s->addr + OMAP_I2C_CNT, data);
+
+    data = OMAP_I2C_CON_I2C_EN |
+           OMAP_I2C_CON_MST |
+           OMAP_I2C_CON_STT |
+           OMAP_I2C_CON_STP;
+    writew(s->addr + OMAP_I2C_CON, data);
+    data = readw(s->addr + OMAP_I2C_CON);
+    g_assert((data & OMAP_I2C_CON_STP) == 0);
+
+    data = readw(s->addr + OMAP_I2C_STAT);
+    g_assert((data & OMAP_I2C_STAT_NACK) == 0);
+
+    data = readw(s->addr + OMAP_I2C_CNT);
+    g_assert_cmpuint(data, ==, len);
+
+    while (len > 0) {
+        data = readw(s->addr + OMAP_I2C_STAT);
+        g_assert((data & OMAP_I2C_STAT_RRDY) != 0);
+        g_assert((data & OMAP_I2C_STAT_ROVR) == 0);
+
+        data = readw(s->addr + OMAP_I2C_DATA);
+
+        stat = readw(s->addr + OMAP_I2C_STAT);
+
+        if (unlikely(len == 1)) {
+            g_assert((stat & OMAP_I2C_STAT_SBD) != 0);
+
+            buf[0] = data & 0xff;
+            buf++;
+            len--;
+        } else {
+            buf[0] = data & 0xff;
+            buf[1] = data >> 8;
+            buf += 2;
+            len -= 2;
+        }
+    }
+
+    data = readw(s->addr + OMAP_I2C_CON);
+    g_assert((data & OMAP_I2C_CON_STP) == 0);
+}
+
+I2CAdapter *omap_i2c_create(uint64_t addr)
+{
+    OMAPI2C *s = g_malloc0(sizeof(*s));
+    I2CAdapter *i2c = (I2CAdapter *)s;
+    uint16_t data;
+
+    s->addr = addr;
+
+    i2c->send = omap_i2c_send;
+    i2c->recv = omap_i2c_recv;
+
+    /* verify the mmio address by looking for a known signature */
+    data = readw(addr + OMAP_I2C_REV);
+    g_assert_cmphex(data, ==, 0x34);
+
+    return i2c;
+}
diff --git a/tests/libqos/i2c.c b/tests/libqos/i2c.c
new file mode 100644
index 0000000..da7592f
--- /dev/null
+++ b/tests/libqos/i2c.c
@@ -0,0 +1,22 @@
+/*
+ * QTest I2C driver
+ *
+ * Copyright (c) 2012 Andreas Färber
+ *
+ * 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 "libqos/i2c.h"
+#include "libqtest.h"
+
+void i2c_send(I2CAdapter *i2c, uint8_t addr,
+              const uint8_t *buf, uint16_t len)
+{
+    i2c->send(i2c, addr, buf, len);
+}
+
+void i2c_recv(I2CAdapter *i2c, uint8_t addr,
+              uint8_t *buf, uint16_t len)
+{
+    i2c->recv(i2c, addr, buf, len);
+}
diff --git a/tests/libqos/i2c.h b/tests/libqos/i2c.h
new file mode 100644
index 0000000..1ce9af4
--- /dev/null
+++ b/tests/libqos/i2c.h
@@ -0,0 +1,30 @@
+/*
+ * I2C libqos
+ *
+ * Copyright (c) 2012 Andreas Färber
+ *
+ * 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 LIBQOS_I2C_H
+#define LIBQOS_I2C_H
+
+#include <stdint.h>
+
+typedef struct I2CAdapter I2CAdapter;
+struct I2CAdapter {
+    void (*send)(I2CAdapter *adapter, uint8_t addr,
+                 const uint8_t *buf, uint16_t len);
+    void (*recv)(I2CAdapter *adapter, uint8_t addr,
+                 uint8_t *buf, uint16_t len);
+};
+
+void i2c_send(I2CAdapter *i2c, uint8_t addr,
+              const uint8_t *buf, uint16_t len);
+void i2c_recv(I2CAdapter *i2c, uint8_t addr,
+              uint8_t *buf, uint16_t len);
+
+/* libi2c-omap.c */
+I2CAdapter *omap_i2c_create(uint64_t addr);
+
+#endif
diff --git a/tests/tmp105-test.c b/tests/tmp105-test.c
index 2869129..fecd6dc 100644
--- a/tests/tmp105-test.c
+++ b/tests/tmp105-test.c
@@ -7,7 +7,7 @@
  * See the COPYING file in the top-level directory.
  */
 #include "libqtest.h"
-#include "libi2c.h"
+#include "libqos/i2c.h"
 #include "hw/misc/tmp105_regs.h"
 
 #include <glib.h>
commit 743bddb4b35ceaaf6f95aea581a4130dcae6205a
Merge: a612925 e64dd5e
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri May 3 11:20:15 2013 -0500

    Merge remote-tracking branch 'stefanha/tracing' into staging
    
    # By Eiichi Tsukata (2) and Kazuya Saito (2)
    # Via Stefan Hajnoczi
    * stefanha/tracing:
      trace: document ftrace backend
      trace: Add ftrace tracing backend
      kvm-all: add kvm_run_exit tracepoint
      kvm-all: add kvm_ioctl, kvm_vm_ioctl, kvm_vcpu_ioctl tracepoints
    
    Message-id: 1367582485-15579-1-git-send-email-stefanha at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

commit a612925b4184fa7aa37092db4fef816030640922
Merge: 25565e8 7873df4
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri May 3 11:20:07 2013 -0500

    Merge remote-tracking branch 'stefanha/net' into staging
    
    # By Amos Kong (1) and Jason Wang (1)
    # Via Stefan Hajnoczi
    * stefanha/net:
      tap: properly initialize vhostfds
      net: make network client name unique
    
    Message-id: 1367582254-15060-1-git-send-email-stefanha at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

commit 25565e8595322b04902a09ebf877d80532f22fd1
Merge: c9e53a4 86abefd
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri May 3 11:20:02 2013 -0500

    Merge remote-tracking branch 'stefanha/block' into staging
    
    # By Fam Zheng (8) and others
    # Via Stefan Hajnoczi
    * stefanha/block:
      qemu-iotests: Filter out 'adapter_type'
      nbd: support large NBD requests
      nbd: use g_slice_new() instead of a freelist
      qemu-iotests: Filter out vmdk creation options
      vmdk: add bdrv_co_write_zeroes
      vmdk: store fields of VmdkMetaData in cpu endian
      vmdk: change magic number to macro
      vmdk: Add option to create zeroed-grain image
      vmdk: add support for “zeroed‐grain” GTE
      vmdk: named return code.
      blockdev: Replace "undefined error" in qmp_block_resize
      block: add read-only support to VHDX image format.
      block: initial VHDX driver support framework - supports open and probe
      block: vhdx header for the QEMU support of VHDX images
      qemu: add castagnoli crc32c checksum algorithm

commit e64dd5efb2c6d522a3bc9d096cd49a4e53f0ae10
Author: Eiichi Tsukata <eiichi.tsukata.xh at hitachi.com>
Date:   Thu Apr 11 20:25:16 2013 +0900

    trace: document ftrace backend
    
    Add documentation of ftrace backend.
    
    Signed-off-by: Eiichi Tsukata <eiichi.tsukata.xh at hitachi.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/docs/tracing.txt b/docs/tracing.txt
index cf53c17..60ff9c5 100644
--- a/docs/tracing.txt
+++ b/docs/tracing.txt
@@ -175,6 +175,22 @@ unless you have specific needs for more advanced backends.
 The "simple" backend currently does not capture string arguments, it simply
 records the char* pointer value instead of the string that is pointed to.
 
+=== Ftrace ===
+
+The "ftrace" backend writes trace data to ftrace marker. This effectively
+sends trace events to ftrace ring buffer, and you can compare qemu trace
+data and kernel(especially kvm.ko when using KVM) trace data.
+
+if you use KVM, enable kvm events in ftrace:
+
+   # echo 1 > /sys/kernel/debug/tracing/events/kvm/enable
+
+After running qemu by root user, you can get the trace:
+
+   # cat /sys/kernel/debug/tracing/trace
+
+Restriction: "ftrace" backend is restricted to Linux only.
+
 ==== Monitor commands ====
 
 * trace-file on|off|flush|set <path>
commit 781e9545dbe54d2f0a530edbf48fd0ac1e77244c
Author: Eiichi Tsukata <eiichi.tsukata.xh at hitachi.com>
Date:   Thu Apr 11 20:25:15 2013 +0900

    trace: Add ftrace tracing backend
    
    This patch adds a ftrace tracing backend which sends trace event to
    ftrace marker file. You can effectively compare qemu trace data and
    kernel(especially, kvm.ko when using KVM) trace data.
    The ftrace backend is restricted to Linux only.
    
    To try out the ftrace backend:
    
     $ ./configure --trace-backend=ftrace
     $ make
    
    if you use KVM, enable kvm events in ftrace:
    
     # sudo echo 1 > /sys/kernel/debug/tracing/events/kvm/enable
    
    After running qemu by root user, you can get the trace:
    
     # cat /sys/kernel/debug/tracing/trace
    
    Signed-off-by: Eiichi Tsukata <eiichi.tsukata.xh at hitachi.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/configure b/configure
index c4d85ba..e818e8b 100755
--- a/configure
+++ b/configure
@@ -4004,6 +4004,14 @@ if test "$trace_backend" = "dtrace"; then
     echo "CONFIG_TRACE_SYSTEMTAP=y" >> $config_host_mak
   fi
 fi
+if test "$trace_backend" = "ftrace"; then
+  if test "$linux" = "yes" ; then
+    echo "CONFIG_TRACE_FTRACE=y" >> $config_host_mak
+    trace_default=no
+  else
+    feature_not_found "ftrace(trace backend)"
+  fi
+fi
 echo "CONFIG_TRACE_FILE=$trace_file" >> $config_host_mak
 if test "$trace_default" = "yes"; then
   echo "CONFIG_TRACE_DEFAULT=y" >> $config_host_mak
diff --git a/scripts/tracetool/backend/ftrace.py b/scripts/tracetool/backend/ftrace.py
new file mode 100644
index 0000000..888c361
--- /dev/null
+++ b/scripts/tracetool/backend/ftrace.py
@@ -0,0 +1,54 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Ftrace built-in backend.
+"""
+
+__author__     = "Eiichi Tsukata <eiichi.tsukata.xh at hitachi.com>"
+__copyright__  = "Copyright (C) 2013 Hitachi, Ltd."
+__license__    = "GPL version 2 or (at your option) any later version"
+
+__maintainer__ = "Stefan Hajnoczi"
+__email__      = "stefanha at redhat.com"
+
+
+from tracetool import out
+
+
+PUBLIC = True
+
+
+def c(events):
+    pass
+
+def h(events):
+    out('#include "trace/ftrace.h"',
+        '#include "trace/control.h"',
+        '',
+        )
+
+    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)',
+            '{',
+            '    char ftrace_buf[MAX_TRACE_STRLEN];',
+            '    int unused __attribute__ ((unused));',
+            '    int trlen;',
+            '    bool _state = trace_event_get_state(%(event_id)s);',
+            '    if (_state) {',
+            '        trlen = snprintf(ftrace_buf, MAX_TRACE_STRLEN,',
+            '                         "%(name)s " %(fmt)s "\\n" %(argnames)s);',
+            '        trlen = MIN(trlen, MAX_TRACE_STRLEN - 1);',
+            '        unused = write(trace_marker_fd, ftrace_buf, trlen);',
+            '    }',
+            '}',
+            name = e.name,
+            args = e.args,
+            event_id = "TRACE_" + e.name.upper(),
+            fmt = e.fmt.rstrip("\n"),
+            argnames = argnames,
+            )
diff --git a/trace/Makefile.objs b/trace/Makefile.objs
index a043072..3b88e49 100644
--- a/trace/Makefile.objs
+++ b/trace/Makefile.objs
@@ -76,5 +76,6 @@ endif
 util-obj-$(CONFIG_TRACE_DEFAULT) += default.o
 util-obj-$(CONFIG_TRACE_SIMPLE) += simple.o
 util-obj-$(CONFIG_TRACE_STDERR) += stderr.o
+util-obj-$(CONFIG_TRACE_FTRACE) += ftrace.o
 util-obj-y += control.o
 util-obj-y += generated-tracers.o
diff --git a/trace/ftrace.c b/trace/ftrace.c
new file mode 100644
index 0000000..46b7fdb
--- /dev/null
+++ b/trace/ftrace.c
@@ -0,0 +1,102 @@
+/*
+ * Ftrace trace backend
+ *
+ * Copyright (C) 2013 Hitachi, Ltd.
+ * Created by Eiichi Tsukata <eiichi.tsukata.xh at hitachi.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <limits.h>
+#include "trace.h"
+#include "trace/control.h"
+
+int trace_marker_fd;
+
+static int find_debugfs(char *debugfs)
+{
+    char type[100];
+    FILE *fp;
+
+    fp = fopen("/proc/mounts", "r");
+    if (fp == NULL) {
+        return 0;
+    }
+
+    while (fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
+                  debugfs, type) == 2) {
+        if (strcmp(type, "debugfs") == 0) {
+            break;
+        }
+    }
+    fclose(fp);
+
+    if (strcmp(type, "debugfs") != 0) {
+        return 0;
+    }
+    return 1;
+}
+
+void trace_print_events(FILE *stream, fprintf_function stream_printf)
+{
+    TraceEventID 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_event_get_name(ev), i, trace_event_get_state_dynamic(ev));
+    }
+}
+
+void trace_event_set_state_dynamic_backend(TraceEvent *ev, bool state)
+{
+    ev->dstate = state;
+}
+
+bool trace_backend_init(const char *events, const char *file)
+{
+    char debugfs[PATH_MAX];
+    char path[PATH_MAX];
+    int debugfs_found;
+    int trace_fd = -1;
+
+    if (file) {
+        fprintf(stderr, "error: -trace file=...: "
+                "option not supported by the selected tracing backend\n");
+        return false;
+    }
+
+    debugfs_found = find_debugfs(debugfs);
+    if (debugfs_found) {
+        snprintf(path, PATH_MAX, "%s/tracing/tracing_on", debugfs);
+        trace_fd = open(path, O_WRONLY);
+        if (trace_fd < 0) {
+            perror("Could not open ftrace 'tracing_on' file");
+            return false;
+        } else {
+            if (write(trace_fd, "1", 1) < 0) {
+                perror("Could not write to 'tracing_on' file");
+                close(trace_fd);
+                return false;
+            }
+            close(trace_fd);
+        }
+        snprintf(path, PATH_MAX, "%s/tracing/trace_marker", debugfs);
+        trace_marker_fd = open(path, O_WRONLY);
+        if (trace_marker_fd < 0) {
+            perror("Could not open ftrace 'trace_marker' file");
+            return false;
+        }
+    } else {
+        fprintf(stderr, "debugfs is not mounted\n");
+        return false;
+    }
+
+    trace_backend_init_events(events);
+    return true;
+}
diff --git a/trace/ftrace.h b/trace/ftrace.h
new file mode 100644
index 0000000..94cb8d5
--- /dev/null
+++ b/trace/ftrace.h
@@ -0,0 +1,10 @@
+#ifndef TRACE_FTRACE_H
+#define TRACE_FTRACE_H
+
+#define MAX_TRACE_STRLEN 512
+#define _STR(x) #x
+#define STR(x) _STR(x)
+
+extern int trace_marker_fd;
+
+#endif /* ! TRACE_FTRACE_H */
commit b76ac80a5ca9f2e19405419172c0dcaf0370d4f5
Author: Kazuya Saito <saito.kazuya at jp.fujitsu.com>
Date:   Fri Mar 29 13:27:52 2013 +0900

    kvm-all: add kvm_run_exit tracepoint
    
    This patch enable us to know exit reason of KVM_RUN. It will help us
    know where the trouble is caused.
    
    Signed-off-by: Kazuya Saito <saito.kazuya at jp.fujitsu.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index 4f73b98..3a31602 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1627,6 +1627,7 @@ int kvm_cpu_exec(CPUArchState *env)
             abort();
         }
 
+        trace_kvm_run_exit(cpu->cpu_index, run->exit_reason);
         switch (run->exit_reason) {
         case KVM_EXIT_IO:
             DPRINTF("handle_io\n");
diff --git a/trace-events b/trace-events
index d5bc7a5..17d75ab 100644
--- a/trace-events
+++ b/trace-events
@@ -1158,3 +1158,5 @@ migrate_set_state(int new_state) "new state %d"
 kvm_ioctl(int type, void *arg) "type %d, arg %p"
 kvm_vm_ioctl(int type, void *arg) "type %d, arg %p"
 kvm_vcpu_ioctl(int cpu_index, int type, void *arg) "cpu_index %d, type %d, arg %p"
+kvm_run_exit(int cpu_index, uint32_t reason) "cpu_index %d, reason %d"
+
commit 9c7757290c6d80c2f5bde6fa71d2c9fe2b331c8c
Author: Kazuya Saito <saito.kazuya at jp.fujitsu.com>
Date:   Fri Mar 29 13:27:05 2013 +0900

    kvm-all: add kvm_ioctl, kvm_vm_ioctl, kvm_vcpu_ioctl tracepoints
    
    This patch adds tracepoints at ioctl to kvm. Tracing these ioctl is
    useful for clarification whether the cause of troubles is qemu or kvm.
    
    Signed-off-by: Kazuya Saito <saito.kazuya at jp.fujitsu.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index f6c0f4a..4f73b98 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -33,6 +33,7 @@
 #include "exec/memory.h"
 #include "exec/address-spaces.h"
 #include "qemu/event_notifier.h"
+#include "trace.h"
 
 /* This check must be after config-host.h is included */
 #ifdef CONFIG_EVENTFD
@@ -1687,6 +1688,7 @@ int kvm_ioctl(KVMState *s, int type, ...)
     arg = va_arg(ap, void *);
     va_end(ap);
 
+    trace_kvm_ioctl(type, arg);
     ret = ioctl(s->fd, type, arg);
     if (ret == -1) {
         ret = -errno;
@@ -1704,6 +1706,7 @@ int kvm_vm_ioctl(KVMState *s, int type, ...)
     arg = va_arg(ap, void *);
     va_end(ap);
 
+    trace_kvm_vm_ioctl(type, arg);
     ret = ioctl(s->vmfd, type, arg);
     if (ret == -1) {
         ret = -errno;
@@ -1721,6 +1724,7 @@ int kvm_vcpu_ioctl(CPUState *cpu, int type, ...)
     arg = va_arg(ap, void *);
     va_end(ap);
 
+    trace_kvm_vcpu_ioctl(cpu->cpu_index, type, arg);
     ret = ioctl(cpu->kvm_fd, type, arg);
     if (ret == -1) {
         ret = -errno;
diff --git a/trace-events b/trace-events
index 55e80be..d5bc7a5 100644
--- a/trace-events
+++ b/trace-events
@@ -1153,3 +1153,8 @@ virtio_ccw_new_device(int cssid, int ssid, int schid, int devno, const char *dev
 
 # migration.c
 migrate_set_state(int new_state) "new state %d"
+
+# kvm-all.c
+kvm_ioctl(int type, void *arg) "type %d, arg %p"
+kvm_vm_ioctl(int type, void *arg) "type %d, arg %p"
+kvm_vcpu_ioctl(int cpu_index, int type, void *arg) "cpu_index %d, type %d, arg %p"
commit 7873df408dd44eb92840b108211d5aa5db7db526
Author: Jason Wang <jasowang at redhat.com>
Date:   Fri Apr 19 15:11:15 2013 +0800

    tap: properly initialize vhostfds
    
    Only tap->vhostfd were checked net_init_tap_one(), but tap->vhostfds were
    forgot, this will lead qemu to ignore all fds passed by management through
    vhostfds, and tries to create vhost_net device itself. Fix by adding this check
    also.
    
    Reportyed-by: Michal Privoznik <mprivozn at redhat.com>
    Cc: Michal Privoznik <mprivozn at redhat.com>
    Cc: qemu-stable at nongnu.org
    Signed-off-by: Jason Wang <jasowang at redhat.com>
    Reviewed-by: Michal Privoznik <mprivozn at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/net/tap.c b/net/tap.c
index 17bdf01..e0b7a2a 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -623,7 +623,7 @@ static int net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
         vhostfdname || (tap->has_vhostforce && tap->vhostforce)) {
         int vhostfd;
 
-        if (tap->has_vhostfd) {
+        if (tap->has_vhostfd || tap->has_vhostfds) {
             vhostfd = monitor_handle_fd_param(cur_mon, vhostfdname);
             if (vhostfd == -1) {
                 return -1;
commit c963530a5b3e3e0f7304841adfe84416d82f59f6
Author: Amos Kong <akong at redhat.com>
Date:   Mon Apr 15 18:55:19 2013 +0800

    net: make network client name unique
    
    assign_name() creates a name MODEL.NUM, where MODEL is the client's model,
    and NUM is the number of MODELs that already exist.
    
    Markus added NIC naming for non-VLAN clients in commit 53e51d85.
    commit d33d93b2 incorrectly added a judgement of net-hub. It caused
    net clients created with -netdev get same names.
    
    eg:
     # qemu-upstream -device virtio-net-pci,netdev=h1 -netdev tap,id=h1 \
                        -device virtio-net-pci,netdev=h2 -netdev tap,id=h2 ..
     (qemu) info network
     virtio-net-pci.0: index=0,type=nic,model=virtio-net-pci,macaddr=52:54:00:12:34:56
      \ h1: index=0,type=tap,ifname=tap0,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown
     virtio-net-pci.0: index=0,type=nic,model=virtio-net-pci,macaddr=52:54:00:12:34:57
      \ h2: index=0,type=tap,ifname=tap1,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown
    
    This patch removed the check of nic-hub, and created unique names for
    all net clients that have same model.
    
    v2: update commitlog & comments
    
    Signed-off-by: Amos Kong <akong at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/net/net.c b/net/net.c
index 7869161..43a74e4 100644
--- a/net/net.c
+++ b/net/net.c
@@ -157,8 +157,7 @@ void qemu_macaddr_default_if_unset(MACAddr *macaddr)
 /**
  * Generate a name for net client
  *
- * Only net clients created with the legacy -net option need this.  Naming is
- * mandatory for net clients created with -netdev.
+ * Only net clients created with the legacy -net option and NICs need this.
  */
 static char *assign_name(NetClientState *nc1, const char *model)
 {
@@ -170,9 +169,7 @@ static char *assign_name(NetClientState *nc1, const char *model)
         if (nc == nc1) {
             continue;
         }
-        /* For compatibility only bump id for net clients on a vlan */
-        if (strcmp(nc->model, model) == 0 &&
-            net_hub_id_for_client(nc, NULL) == 0) {
+        if (strcmp(nc->model, model) == 0) {
             id++;
         }
     }
commit 86abefd61e23325162e59e5bfb8f0346eda62541
Author: Fam Zheng <famz at redhat.com>
Date:   Fri May 3 15:31:16 2013 +0800

    qemu-iotests: Filter out 'adapter_type'
    
    Filter out vmdk creation option 'adapter_type' for vmdk. So that tests
    with an explicit './check -o adapter_type=XXX' will not fail.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
index 442cf51..31eb62b 100644
--- a/tests/qemu-iotests/common.rc
+++ b/tests/qemu-iotests/common.rc
@@ -129,6 +129,7 @@ _make_test_img()
             -e "s# static=\\(on\\|off\\)##g" \
             -e "s# zeroed_grain=\\(on\\|off\\)##g" \
             -e "s# subformat='[^']*'##g" \
+            -e "s# adapter_type='[^']*'##g" \
             -e "s# lazy_refcounts=\\(on\\|off\\)##g"
 
     # Start an NBD server on the image file, which is what we'll be talking to
commit 2d8214885942becb8f4371a66d6f8c9a9580108a
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Thu May 2 14:23:08 2013 +0200

    nbd: support large NBD requests
    
    The Linux nbd driver recently increased the maximum supported request
    size up to 32 MB:
    
      commit 078be02b80359a541928c899c2631f39628f56df
      Author: Michal Belczyk <belczyk at bsd.krakow.pl>
      Date:   Tue Apr 30 15:28:28 2013 -0700
    
          nbd: increase default and max request sizes
    
          Raise the default max request size for nbd to 128KB (from 127KB) to get it
          4KB aligned.  This patch also allows the max request size to be increased
          (via /sys/block/nbd<x>/queue/max_sectors_kb) to 32MB.
    
    QEMU's 1 MB buffers are too small to handle these requests.
    
    This patch allocates data buffers dynamically and allows up to 32 MB per
    request.
    
    Reported-by: Nick Thomas <nick at bytemark.co.uk>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/include/block/nbd.h b/include/block/nbd.h
index 0903d7a..c90f5e4 100644
--- a/include/block/nbd.h
+++ b/include/block/nbd.h
@@ -58,7 +58,8 @@ enum {
 
 #define NBD_DEFAULT_PORT	10809
 
-#define NBD_BUFFER_SIZE (1024*1024)
+/* Maximum size of a single READ/WRITE data buffer */
+#define NBD_MAX_BUFFER_SIZE (32 * 1024 * 1024)
 
 ssize_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read);
 int tcp_socket_incoming(const char *address, uint16_t port);
diff --git a/nbd.c b/nbd.c
index 761f4ec..2606403 100644
--- a/nbd.c
+++ b/nbd.c
@@ -844,13 +844,11 @@ void nbd_client_close(NBDClient *client)
 static NBDRequest *nbd_request_get(NBDClient *client)
 {
     NBDRequest *req;
-    NBDExport *exp = client->exp;
 
     assert(client->nb_requests <= MAX_NBD_REQUESTS - 1);
     client->nb_requests++;
 
     req = g_slice_new0(NBDRequest);
-    req->data = qemu_blockalign(exp->bs, NBD_BUFFER_SIZE);
     nbd_client_get(client);
     req->client = client;
     return req;
@@ -860,7 +858,9 @@ static void nbd_request_put(NBDRequest *req)
 {
     NBDClient *client = req->client;
 
-    qemu_vfree(req->data);
+    if (req->data) {
+        qemu_vfree(req->data);
+    }
     g_slice_free(NBDRequest, req);
 
     if (client->nb_requests-- == MAX_NBD_REQUESTS) {
@@ -1007,6 +1007,7 @@ static ssize_t nbd_co_receive_request(NBDRequest *req, struct nbd_request *reque
 {
     NBDClient *client = req->client;
     int csock = client->sock;
+    uint32_t command;
     ssize_t rc;
 
     client->recv_coroutine = qemu_coroutine_self();
@@ -1018,9 +1019,9 @@ static ssize_t nbd_co_receive_request(NBDRequest *req, struct nbd_request *reque
         goto out;
     }
 
-    if (request->len > NBD_BUFFER_SIZE) {
+    if (request->len > NBD_MAX_BUFFER_SIZE) {
         LOG("len (%u) is larger than max len (%u)",
-            request->len, NBD_BUFFER_SIZE);
+            request->len, NBD_MAX_BUFFER_SIZE);
         rc = -EINVAL;
         goto out;
     }
@@ -1034,7 +1035,11 @@ static ssize_t nbd_co_receive_request(NBDRequest *req, struct nbd_request *reque
 
     TRACE("Decoding type");
 
-    if ((request->type & NBD_CMD_MASK_COMMAND) == NBD_CMD_WRITE) {
+    command = request->type & NBD_CMD_MASK_COMMAND;
+    if (command == NBD_CMD_READ || command == NBD_CMD_WRITE) {
+        req->data = qemu_blockalign(client->exp->bs, request->len);
+    }
+    if (command == NBD_CMD_WRITE) {
         TRACE("Reading %u byte(s)", request->len);
 
         if (qemu_co_recv(csock, req->data, request->len) != request->len) {
commit e1adb27a83f19799c454cead7bf930a0b3f2bb28
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Thu May 2 14:23:07 2013 +0200

    nbd: use g_slice_new() instead of a freelist
    
    Use GLib's efficient slice allocator instead of open-coding the request
    freelist.  This patch simplifies the NBDRequest code.
    
    Now we qemu_blockalign() the req->data buffer each time but the next
    patch switches from a fixed size buffer to a dynamic size anyway.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/nbd.c b/nbd.c
index 85187ff..761f4ec 100644
--- a/nbd.c
+++ b/nbd.c
@@ -98,7 +98,6 @@ struct NBDExport {
     off_t size;
     uint32_t nbdflags;
     QTAILQ_HEAD(, NBDClient) clients;
-    QSIMPLEQ_HEAD(, NBDRequest) requests;
     QTAILQ_ENTRY(NBDExport) next;
 };
 
@@ -850,13 +849,8 @@ static NBDRequest *nbd_request_get(NBDClient *client)
     assert(client->nb_requests <= MAX_NBD_REQUESTS - 1);
     client->nb_requests++;
 
-    if (QSIMPLEQ_EMPTY(&exp->requests)) {
-        req = g_malloc0(sizeof(NBDRequest));
-        req->data = qemu_blockalign(exp->bs, NBD_BUFFER_SIZE);
-    } else {
-        req = QSIMPLEQ_FIRST(&exp->requests);
-        QSIMPLEQ_REMOVE_HEAD(&exp->requests, entry);
-    }
+    req = g_slice_new0(NBDRequest);
+    req->data = qemu_blockalign(exp->bs, NBD_BUFFER_SIZE);
     nbd_client_get(client);
     req->client = client;
     return req;
@@ -865,7 +859,10 @@ static NBDRequest *nbd_request_get(NBDClient *client)
 static void nbd_request_put(NBDRequest *req)
 {
     NBDClient *client = req->client;
-    QSIMPLEQ_INSERT_HEAD(&client->exp->requests, req, entry);
+
+    qemu_vfree(req->data);
+    g_slice_free(NBDRequest, req);
+
     if (client->nb_requests-- == MAX_NBD_REQUESTS) {
         qemu_notify_event();
     }
@@ -877,7 +874,6 @@ NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset,
                           void (*close)(NBDExport *))
 {
     NBDExport *exp = g_malloc0(sizeof(NBDExport));
-    QSIMPLEQ_INIT(&exp->requests);
     exp->refcount = 1;
     QTAILQ_INIT(&exp->clients);
     exp->bs = bs;
@@ -953,13 +949,6 @@ void nbd_export_put(NBDExport *exp)
             exp->close(exp);
         }
 
-        while (!QSIMPLEQ_EMPTY(&exp->requests)) {
-            NBDRequest *first = QSIMPLEQ_FIRST(&exp->requests);
-            QSIMPLEQ_REMOVE_HEAD(&exp->requests, entry);
-            qemu_vfree(first->data);
-            g_free(first);
-        }
-
         g_free(exp);
     }
 }
commit c9e53a4cf116dae72d779c7748153cedd2e84228
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Apr 29 08:08:23 2013 -0700

    tcg-arm: Use movi32 in exit_tb
    
    Avoid the mini constant pool for armv7, and avoid replicating
    the test for pre-v7.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 12edad4..3d43412 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -1611,17 +1611,15 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
 
     switch (opc) {
     case INDEX_op_exit_tb:
-        {
+        if (use_armv7_instructions || check_fit_imm(args[0])) {
+            tcg_out_movi32(s, COND_AL, TCG_REG_R0, args[0]);
+            tcg_out_goto(s, COND_AL, (tcg_target_ulong) tb_ret_addr);
+        } else {
             uint8_t *ld_ptr = s->code_ptr;
-            if (args[0] >> 8)
-                tcg_out_ld32_12(s, COND_AL, TCG_REG_R0, TCG_REG_PC, 0);
-            else
-                tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R0, 0, args[0]);
+            tcg_out_ld32_12(s, COND_AL, TCG_REG_R0, TCG_REG_PC, 0);
             tcg_out_goto(s, COND_AL, (tcg_target_ulong) tb_ret_addr);
-            if (args[0] >> 8) {
-                *ld_ptr = (uint8_t) (s->code_ptr - ld_ptr) - 8;
-                tcg_out32(s, args[0]);
-            }
+            *ld_ptr = (uint8_t) (s->code_ptr - ld_ptr) - 8;
+            tcg_out32(s, args[0]);
         }
         break;
     case INDEX_op_goto_tb:
commit 8ddaeb1be66246225fe5aeeec33e4e7b82762694
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Apr 29 08:08:22 2013 -0700

    tcg-arm: Fix 64-bit tlb load for pre-v6
    
    Found by inspection, since the effect of the bug was simply to
    send all memory ops through the slow path.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 7216f7a..12edad4 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -1190,7 +1190,7 @@ static void tcg_out_tlb_read(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
         tcg_out_memop_12(s, COND_AL, INSN_LDR_IMM, TCG_REG_R0,
                          TCG_REG_R2, tlb_offset, 1, 1);
         if (TARGET_LONG_BITS == 64) {
-            tcg_out_memop_12(s, COND_AL, INSN_LDR_IMM, TCG_REG_R0,
+            tcg_out_memop_12(s, COND_AL, INSN_LDR_IMM, TCG_REG_R1,
                              TCG_REG_R2, 4, 1, 0);
         }
     }
commit 29851ee7c8bd3fb8542e21cd0270c73132590350
Author: Petar Jovanovic <petar.jovanovic at imgtec.com>
Date:   Sun Apr 28 03:18:36 2013 +0200

    target-mips: fix calculation of overflow for SHLL.PH and SHLL.QB
    
    This change corrects and simplifies how discard is calculated for shift
    left logical vector instructions. It is used to detect overflow and set bit
    22 in the DSPControl register.
    
    The existing tests (shll_ph.c, shll_qb.c) are extended with the corner cases
    that expose incorrectness in the previous implementation.
    
    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 f975da0..805247d 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -682,49 +682,31 @@ static inline uint8_t mipsdsp_sat8_reduce_precision(uint16_t a,
 
 static inline uint8_t mipsdsp_lshift8(uint8_t a, uint8_t s, CPUMIPSState *env)
 {
-    uint8_t sign;
     uint8_t discard;
 
-    if (s == 0) {
-        return a;
-    } else {
-        sign = (a >> 7) & 0x01;
-        if (sign != 0) {
-            discard = (((0x01 << (8 - s)) - 1) << s) |
-                      ((a >> (6 - (s - 1))) & ((0x01 << s) - 1));
-        } else {
-            discard = a >> (6 - (s - 1));
-        }
+    if (s != 0) {
+        discard = a >> (8 - s);
 
         if (discard != 0x00) {
             set_DSPControl_overflow_flag(1, 22, env);
         }
-        return a << s;
     }
+    return a << s;
 }
 
 static inline uint16_t mipsdsp_lshift16(uint16_t a, uint8_t s,
                                         CPUMIPSState *env)
 {
-    uint8_t  sign;
     uint16_t discard;
 
-    if (s == 0) {
-        return a;
-    } else {
-        sign = (a >> 15) & 0x01;
-        if (sign != 0) {
-            discard = (((0x01 << (16 - s)) - 1) << s) |
-                      ((a >> (14 - (s - 1))) & ((0x01 << s) - 1));
-        } else {
-            discard = a >> (14 - (s - 1));
-        }
+    if (s != 0) {
+        discard = (int16_t)a >> (15 - s);
 
         if ((discard != 0x0000) && (discard != 0xFFFF)) {
             set_DSPControl_overflow_flag(1, 22, env);
         }
-        return a << s;
     }
+    return a << s;
 }
 
 
diff --git a/tests/tcg/mips/mips32-dsp/shll_ph.c b/tests/tcg/mips/mips32-dsp/shll_ph.c
index b8f1ff5..5fa58cc 100644
--- a/tests/tcg/mips/mips32-dsp/shll_ph.c
+++ b/tests/tcg/mips/mips32-dsp/shll_ph.c
@@ -11,7 +11,38 @@ int main()
     resultdsp = 1;
 
     __asm
-        ("shll.ph %0, %2, 0x0B\n\t"
+        ("wrdsp $0\n\t"
+         "shll.ph %0, %2, 0x0B\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rt)
+        );
+    dsp = (dsp >> 22) & 0x01;
+    assert(dsp == resultdsp);
+    assert(rd  == result);
+
+    rt        = 0x7fff8000;
+    result    = 0xfffe0000;
+    resultdsp = 1;
+
+    __asm
+        ("wrdsp $0\n\t"
+         "shll.ph %0, %2, 0x01\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rt)
+        );
+    dsp = (dsp >> 22) & 0x01;
+    assert(dsp == resultdsp);
+    assert(rd  == result);
+
+    rt        = 0x00000001;
+    result    = 0x00008000;
+    resultdsp = 1;
+
+    __asm
+        ("wrdsp $0\n\t"
+         "shll.ph %0, %2, 0x0F\n\t"
          "rddsp %1\n\t"
          : "=r"(rd), "=r"(dsp)
          : "r"(rt)
diff --git a/tests/tcg/mips/mips32-dsp/shll_qb.c b/tests/tcg/mips/mips32-dsp/shll_qb.c
index 8c1b91c..729716d 100644
--- a/tests/tcg/mips/mips32-dsp/shll_qb.c
+++ b/tests/tcg/mips/mips32-dsp/shll_qb.c
@@ -11,12 +11,14 @@ int main()
     resultdsp = 0x00;
 
     __asm
-        ("shll.qb %0, %2, 0x00\n\t"
+        ("wrdsp $0\n\t"
+         "shll.qb %0, %2, 0x00\n\t"
          "rddsp   %1\n\t"
          : "=r"(rd), "=r"(dsp)
          : "r"(rt)
         );
     dsp = (dsp >> 22) & 0x01;
+    assert(dsp == resultdsp);
     assert(rd == result);
 
     rt     = 0x87654321;
@@ -24,12 +26,29 @@ int main()
     resultdsp = 0x01;
 
     __asm
-        ("shll.qb %0, %2, 0x03\n\t"
+        ("wrdsp $0\n\t"
+         "shll.qb %0, %2, 0x03\n\t"
          "rddsp   %1\n\t"
          : "=r"(rd), "=r"(dsp)
          : "r"(rt)
         );
     dsp = (dsp >> 22) & 0x01;
+    assert(dsp == resultdsp);
+    assert(rd == result);
+
+    rt     = 0x00000001;
+    result = 0x00000080;
+    resultdsp = 0x00;
+
+    __asm
+        ("wrdsp $0\n\t"
+         "shll.qb %0, %2, 0x07\n\t"
+         "rddsp   %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rt)
+        );
+    dsp = (dsp >> 22) & 0x01;
+    assert(dsp == resultdsp);
     assert(rd == result);
 
     return 0;
commit 50522d969be315457e3296d8a32990b58a203902
Author: Fam Zheng <famz at redhat.com>
Date:   Fri May 3 09:31:40 2013 +0800

    qemu-iotests: Filter out vmdk creation options
    
    Cover new image creation options for vmdk, so we can use '-o
    zeroed_grain=XXX' and '-o subformat=XXX' to run the tests successfully.
    
    Signed-off-by: Fam Zheng <famz at redhat.com>
    Reviewed-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
index a536bf7..442cf51 100644
--- a/tests/qemu-iotests/common.rc
+++ b/tests/qemu-iotests/common.rc
@@ -127,6 +127,8 @@ _make_test_img()
             -e "s# compat='[^']*'##g" \
             -e "s# compat6=\\(on\\|off\\)##g" \
             -e "s# static=\\(on\\|off\\)##g" \
+            -e "s# zeroed_grain=\\(on\\|off\\)##g" \
+            -e "s# subformat='[^']*'##g" \
             -e "s# lazy_refcounts=\\(on\\|off\\)##g"
 
     # Start an NBD server on the image file, which is what we'll be talking to
commit cdeaf1f15909e2e8af38f45aea7cfa467a729c52
Author: Fam Zheng <famz at redhat.com>
Date:   Thu May 2 10:25:27 2013 +0800

    vmdk: add bdrv_co_write_zeroes
    
    Use special offset to write zeroes efficiently, when zeroed-grain GTE is
    available. If zero-write an allocated cluster, cluster is leaked because
    its offset pointer is overwritten by "0x1".
    
    Signed-off-by: Fam Zheng <famz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/vmdk.c b/block/vmdk.c
index d98f304..608daaf 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -124,6 +124,7 @@ typedef struct VmdkMetaData {
     unsigned int l2_index;
     unsigned int l2_offset;
     int valid;
+    uint32_t *l2_cache_entry;
 } VmdkMetaData;
 
 typedef struct VmdkGrainMarker {
@@ -835,6 +836,9 @@ static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data)
             return VMDK_ERROR;
         }
     }
+    if (m_data->l2_cache_entry) {
+        *m_data->l2_cache_entry = offset;
+    }
 
     return VMDK_OK;
 }
@@ -905,6 +909,14 @@ static int get_cluster_offset(BlockDriverState *bs,
     l2_index = ((offset >> 9) / extent->cluster_sectors) % extent->l2_size;
     *cluster_offset = le32_to_cpu(l2_table[l2_index]);
 
+    if (m_data) {
+        m_data->valid = 1;
+        m_data->l1_index = l1_index;
+        m_data->l2_index = l2_index;
+        m_data->offset = *cluster_offset;
+        m_data->l2_offset = l2_offset;
+        m_data->l2_cache_entry = &l2_table[l2_index];
+    }
     if (extent->has_zero_grain && *cluster_offset == VMDK_GTE_ZEROED) {
         zeroed = true;
     }
@@ -938,10 +950,6 @@ static int get_cluster_offset(BlockDriverState *bs,
 
         if (m_data) {
             m_data->offset = *cluster_offset;
-            m_data->l1_index = l1_index;
-            m_data->l2_index = l2_index;
-            m_data->l2_offset = l2_offset;
-            m_data->valid = 1;
         }
     }
     *cluster_offset <<= 9;
@@ -1164,8 +1172,17 @@ static coroutine_fn int vmdk_co_read(BlockDriverState *bs, int64_t sector_num,
     return ret;
 }
 
+/**
+ * vmdk_write:
+ * @zeroed:       buf is ignored (data is zero), use zeroed_grain GTE feature
+ * if possible, otherwise return -ENOTSUP.
+ * @zero_dry_run: used for zeroed == true only, don't update L2 table, just
+ *
+ * Returns: error code with 0 for success.
+ */
 static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
-                     const uint8_t *buf, int nb_sectors)
+                      const uint8_t *buf, int nb_sectors,
+                      bool zeroed, bool zero_dry_run)
 {
     BDRVVmdkState *s = bs->opaque;
     VmdkExtent *extent = NULL;
@@ -1211,7 +1228,7 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
                                         &cluster_offset);
             }
         }
-        if (ret) {
+        if (ret == VMDK_ERROR) {
             return -EINVAL;
         }
         extent_begin_sector = extent->end_sector - extent->sectors;
@@ -1221,17 +1238,34 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
         if (n > nb_sectors) {
             n = nb_sectors;
         }
-
-        ret = vmdk_write_extent(extent,
-                        cluster_offset, index_in_cluster * 512,
-                        buf, n, sector_num);
-        if (ret) {
-            return ret;
-        }
-        if (m_data.valid) {
-            /* update L2 tables */
-            if (vmdk_L2update(extent, &m_data) == -1) {
-                return -EIO;
+        if (zeroed) {
+            /* Do zeroed write, buf is ignored */
+            if (extent->has_zero_grain &&
+                    index_in_cluster == 0 &&
+                    n >= extent->cluster_sectors) {
+                n = extent->cluster_sectors;
+                if (!zero_dry_run) {
+                    m_data.offset = VMDK_GTE_ZEROED;
+                    /* update L2 tables */
+                    if (vmdk_L2update(extent, &m_data) != VMDK_OK) {
+                        return -EIO;
+                    }
+                }
+            } else {
+                return -ENOTSUP;
+            }
+        } else {
+            ret = vmdk_write_extent(extent,
+                            cluster_offset, index_in_cluster * 512,
+                            buf, n, sector_num);
+            if (ret) {
+                return ret;
+            }
+            if (m_data.valid) {
+                /* update L2 tables */
+                if (vmdk_L2update(extent, &m_data) != VMDK_OK) {
+                    return -EIO;
+                }
             }
         }
         nb_sectors -= n;
@@ -1257,7 +1291,22 @@ static coroutine_fn int vmdk_co_write(BlockDriverState *bs, int64_t sector_num,
     int ret;
     BDRVVmdkState *s = bs->opaque;
     qemu_co_mutex_lock(&s->lock);
-    ret = vmdk_write(bs, sector_num, buf, nb_sectors);
+    ret = vmdk_write(bs, sector_num, buf, nb_sectors, false, false);
+    qemu_co_mutex_unlock(&s->lock);
+    return ret;
+}
+
+static int coroutine_fn vmdk_co_write_zeroes(BlockDriverState *bs,
+                                             int64_t sector_num,
+                                             int nb_sectors)
+{
+    int ret;
+    BDRVVmdkState *s = bs->opaque;
+    qemu_co_mutex_lock(&s->lock);
+    ret = vmdk_write(bs, sector_num, NULL, nb_sectors, true, true);
+    if (!ret) {
+        ret = vmdk_write(bs, sector_num, NULL, nb_sectors, true, false);
+    }
     qemu_co_mutex_unlock(&s->lock);
     return ret;
 }
@@ -1737,6 +1786,7 @@ static BlockDriver bdrv_vmdk = {
     .bdrv_reopen_prepare = vmdk_reopen_prepare,
     .bdrv_read      = vmdk_co_read,
     .bdrv_write     = vmdk_co_write,
+    .bdrv_co_write_zeroes = vmdk_co_write_zeroes,
     .bdrv_close     = vmdk_close,
     .bdrv_create    = vmdk_create,
     .bdrv_co_flush_to_disk  = vmdk_co_flush,
commit e304e8e5a05bc54c71c5f6fc76abd47410e59857
Author: Fam Zheng <famz at redhat.com>
Date:   Thu May 2 10:25:26 2013 +0800

    vmdk: store fields of VmdkMetaData in cpu endian
    
    Previously VmdkMetaData.offset is stored little endian while other
    fields are cpu endian. This changes offset to cpu endian and convert
    before writing to image.
    Signed-off-by: Fam Zheng <famz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/vmdk.c b/block/vmdk.c
index 0463d3b..d98f304 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -813,14 +813,15 @@ static int get_whole_cluster(BlockDriverState *bs,
 
 static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data)
 {
+    uint32_t offset;
+    QEMU_BUILD_BUG_ON(sizeof(offset) != sizeof(m_data->offset));
+    offset = cpu_to_le32(m_data->offset);
     /* update L2 table */
     if (bdrv_pwrite_sync(
                 extent->file,
                 ((int64_t)m_data->l2_offset * 512)
                     + (m_data->l2_index * sizeof(m_data->offset)),
-                &(m_data->offset),
-                sizeof(m_data->offset)
-            ) < 0) {
+                &offset, sizeof(offset)) < 0) {
         return VMDK_ERROR;
     }
     /* update backup L2 table */
@@ -830,8 +831,7 @@ static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data)
                     extent->file,
                     ((int64_t)m_data->l2_offset * 512)
                         + (m_data->l2_index * sizeof(m_data->offset)),
-                    &(m_data->offset), sizeof(m_data->offset)
-                ) < 0) {
+                    &offset, sizeof(offset)) < 0) {
             return VMDK_ERROR;
         }
     }
@@ -848,7 +848,7 @@ static int get_cluster_offset(BlockDriverState *bs,
 {
     unsigned int l1_index, l2_offset, l2_index;
     int min_index, i, j;
-    uint32_t min_count, *l2_table, tmp = 0;
+    uint32_t min_count, *l2_table;
     bool zeroed = false;
 
     if (m_data) {
@@ -924,8 +924,7 @@ static int get_cluster_offset(BlockDriverState *bs,
         }
 
         *cluster_offset >>= 9;
-        tmp = cpu_to_le32(*cluster_offset);
-        l2_table[l2_index] = tmp;
+        l2_table[l2_index] = cpu_to_le32(*cluster_offset);
 
         /* First of all we write grain itself, to avoid race condition
          * that may to corrupt the image.
@@ -938,7 +937,7 @@ static int get_cluster_offset(BlockDriverState *bs,
         }
 
         if (m_data) {
-            m_data->offset = tmp;
+            m_data->offset = *cluster_offset;
             m_data->l1_index = l1_index;
             m_data->l2_index = l2_index;
             m_data->l2_offset = l2_offset;
commit 95b0aa4231dfc827ddc189138d6502cbca66d2b6
Author: Fam Zheng <famz at redhat.com>
Date:   Thu May 2 10:25:25 2013 +0800

    vmdk: change magic number to macro
    
    Two hard coded flag bits are changed to macros.
    Signed-off-by: Fam Zheng <famz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/vmdk.c b/block/vmdk.c
index cc19e20..0463d3b 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -32,6 +32,7 @@
 #define VMDK3_MAGIC (('C' << 24) | ('O' << 16) | ('W' << 8) | 'D')
 #define VMDK4_MAGIC (('K' << 24) | ('D' << 16) | ('M' << 8) | 'V')
 #define VMDK4_COMPRESSION_DEFLATE 1
+#define VMDK4_FLAG_NL_DETECT (1 << 0)
 #define VMDK4_FLAG_RGD (1 << 1)
 /* Zeroed-grain enable bit */
 #define VMDK4_FLAG_ZERO_GRAIN   (1 << 2)
@@ -1287,7 +1288,7 @@ static int vmdk_create_extent(const char *filename, int64_t filesize,
     magic = cpu_to_be32(VMDK4_MAGIC);
     memset(&header, 0, sizeof(header));
     header.version = zeroed_grain ? 2 : 1;
-    header.flags = 3
+    header.flags = VMDK4_FLAG_RGD | VMDK4_FLAG_NL_DETECT
                    | (compress ? VMDK4_FLAG_COMPRESS | VMDK4_FLAG_MARKER : 0)
                    | (zeroed_grain ? VMDK4_FLAG_ZERO_GRAIN : 0);
     header.compressAlgorithm = compress ? VMDK4_COMPRESSION_DEFLATE : 0;
commit 69e0b6dfa455924842bfcbfa810fde34899f1350
Author: Fam Zheng <famz at redhat.com>
Date:   Thu May 2 10:25:24 2013 +0800

    vmdk: Add option to create zeroed-grain image
    
    Add image create option "zeroed-grain" to enable zeroed-grain GTE
    feature of vmdk sparse extents. When this option is on, header version
    of newly created extent will be 2 and VMDK4_FLAG_ZERO_GRAIN flag bit
    will be set.
    
    Signed-off-by: Fam Zheng <famz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/vmdk.c b/block/vmdk.c
index 7e07c0f..cc19e20 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -48,6 +48,8 @@
 #define VMDK_UNALLOC (-2)
 #define VMDK_ZEROED  (-3)
 
+#define BLOCK_OPT_ZEROED_GRAIN "zeroed_grain"
+
 typedef struct {
     uint32_t version;
     uint32_t flags;
@@ -1262,7 +1264,7 @@ static coroutine_fn int vmdk_co_write(BlockDriverState *bs, int64_t sector_num,
 
 
 static int vmdk_create_extent(const char *filename, int64_t filesize,
-                              bool flat, bool compress)
+                              bool flat, bool compress, bool zeroed_grain)
 {
     int ret, i;
     int fd = 0;
@@ -1284,9 +1286,10 @@ static int vmdk_create_extent(const char *filename, int64_t filesize,
     }
     magic = cpu_to_be32(VMDK4_MAGIC);
     memset(&header, 0, sizeof(header));
-    header.version = 1;
-    header.flags =
-        3 | (compress ? VMDK4_FLAG_COMPRESS | VMDK4_FLAG_MARKER : 0);
+    header.version = zeroed_grain ? 2 : 1;
+    header.flags = 3
+                   | (compress ? VMDK4_FLAG_COMPRESS | VMDK4_FLAG_MARKER : 0)
+                   | (zeroed_grain ? VMDK4_FLAG_ZERO_GRAIN : 0);
     header.compressAlgorithm = compress ? VMDK4_COMPRESSION_DEFLATE : 0;
     header.capacity = filesize / 512;
     header.granularity = 128;
@@ -1467,6 +1470,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options)
     char parent_desc_line[BUF_SIZE] = "";
     uint32_t parent_cid = 0xffffffff;
     uint32_t number_heads = 16;
+    bool zeroed_grain = false;
     const char desc_template[] =
         "# Disk DescriptorFile\n"
         "version=1\n"
@@ -1502,6 +1506,8 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options)
             flags |= options->value.n ? BLOCK_FLAG_COMPAT6 : 0;
         } else if (!strcmp(options->name, BLOCK_OPT_SUBFMT)) {
             fmt = options->value.s;
+        } else if (!strcmp(options->name, BLOCK_OPT_ZEROED_GRAIN)) {
+            zeroed_grain |= options->value.n;
         }
         options++;
     }
@@ -1588,7 +1594,8 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options)
         snprintf(ext_filename, sizeof(ext_filename), "%s%s",
                 path, desc_filename);
 
-        if (vmdk_create_extent(ext_filename, size, flat, compress)) {
+        if (vmdk_create_extent(ext_filename, size,
+                               flat, compress, zeroed_grain)) {
             return -EINVAL;
         }
         filesize -= size;
@@ -1714,6 +1721,11 @@ static QEMUOptionParameter vmdk_create_options[] = {
             "VMDK flat extent format, can be one of "
             "{monolithicSparse (default) | monolithicFlat | twoGbMaxExtentSparse | twoGbMaxExtentFlat | streamOptimized} "
     },
+    {
+        .name = BLOCK_OPT_ZEROED_GRAIN,
+        .type = OPT_FLAG,
+        .help = "Enable efficient zero writes using the zeroed-grain GTE feature"
+    },
     { NULL }
 };
 
commit 14ead646fe7d5163c342ebd1e0aeb556ecf343a1
Author: Fam Zheng <famz at redhat.com>
Date:   Thu May 2 10:25:23 2013 +0800

    vmdk: add support for “zeroed‐grain” GTE
    
    Introduced support for zeroed-grain GTE, as specified in Virtual Disk
    Format 5.0[1].
    
        Recent VMware hosted platform products support a new “zeroed‐grain”
        grain table entry (GTE). The zeroed‐grain GTE returns all zeros on
        read.  In other words, the zeroed‐grain GTE indicates that a grain
        in the child disk is zero‐filled but does not actually occupy space
        in storage.  A sparse extent with zeroed‐grain GTE has the following
        in its header:
    
         * SparseExtentHeader.version = 2
         * SparseExtentHeader.flags has bit 2 set
    
        Other than the new flag and the possibly zeroed‐grain GTE, version 2
        sparse extents are identical to version 1.  Also, a zeroed‐grain GTE
        has value 0x1 in the GT table.
    
    [1] Virtual Disk Format 5.0, http://www.vmware.com/support/developer/vddk/vmdk_50_technote.pdf?src=vmdk
    Signed-off-by: Fam Zheng <famz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/vmdk.c b/block/vmdk.c
index 16aa29c..7e07c0f 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -33,10 +33,13 @@
 #define VMDK4_MAGIC (('K' << 24) | ('D' << 16) | ('M' << 8) | 'V')
 #define VMDK4_COMPRESSION_DEFLATE 1
 #define VMDK4_FLAG_RGD (1 << 1)
+/* Zeroed-grain enable bit */
+#define VMDK4_FLAG_ZERO_GRAIN   (1 << 2)
 #define VMDK4_FLAG_COMPRESS (1 << 16)
 #define VMDK4_FLAG_MARKER (1 << 17)
 #define VMDK4_GD_AT_END 0xffffffffffffffffULL
 
+#define VMDK_GTE_ZEROED 0x1
 
 /* VMDK internal error codes */
 #define VMDK_OK      0
@@ -81,6 +84,8 @@ typedef struct VmdkExtent {
     bool flat;
     bool compressed;
     bool has_marker;
+    bool has_zero_grain;
+    int version;
     int64_t sectors;
     int64_t end_sector;
     int64_t flat_start_offset;
@@ -569,6 +574,8 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
     extent->compressed =
         le16_to_cpu(header.compressAlgorithm) == VMDK4_COMPRESSION_DEFLATE;
     extent->has_marker = le32_to_cpu(header.flags) & VMDK4_FLAG_MARKER;
+    extent->version = le32_to_cpu(header.version);
+    extent->has_zero_grain = le32_to_cpu(header.flags) & VMDK4_FLAG_ZERO_GRAIN;
     ret = vmdk_init_tables(bs, extent);
     if (ret) {
         /* free extent allocated by vmdk_add_extent */
@@ -839,6 +846,7 @@ static int get_cluster_offset(BlockDriverState *bs,
     unsigned int l1_index, l2_offset, l2_index;
     int min_index, i, j;
     uint32_t min_count, *l2_table, tmp = 0;
+    bool zeroed = false;
 
     if (m_data) {
         m_data->valid = 0;
@@ -894,9 +902,13 @@ static int get_cluster_offset(BlockDriverState *bs,
     l2_index = ((offset >> 9) / extent->cluster_sectors) % extent->l2_size;
     *cluster_offset = le32_to_cpu(l2_table[l2_index]);
 
-    if (!*cluster_offset) {
+    if (extent->has_zero_grain && *cluster_offset == VMDK_GTE_ZEROED) {
+        zeroed = true;
+    }
+
+    if (!*cluster_offset || zeroed) {
         if (!allocate) {
-            return VMDK_UNALLOC;
+            return zeroed ? VMDK_ZEROED : VMDK_UNALLOC;
         }
 
         /* Avoid the L2 tables update for the images that have snapshots. */
@@ -967,8 +979,8 @@ static int coroutine_fn vmdk_co_is_allocated(BlockDriverState *bs,
     ret = get_cluster_offset(bs, extent, NULL,
                             sector_num * 512, 0, &offset);
     qemu_co_mutex_unlock(&s->lock);
-    /* get_cluster_offset returning 0 means success */
-    ret = !ret;
+
+    ret = (ret == VMDK_OK || ret == VMDK_ZEROED);
 
     index_in_cluster = sector_num % extent->cluster_sectors;
     n = extent->cluster_sectors - index_in_cluster;
@@ -1111,9 +1123,9 @@ static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
         if (n > nb_sectors) {
             n = nb_sectors;
         }
-        if (ret) {
+        if (ret != VMDK_OK) {
             /* if not allocated, try to read from parent image, if exist */
-            if (bs->backing_hd) {
+            if (bs->backing_hd && ret != VMDK_ZEROED) {
                 if (!vmdk_is_cid_valid(bs)) {
                     return -EINVAL;
                 }
commit 65f7472577f9409d285b0216fae76c7c3f03fc41
Author: Fam Zheng <famz at redhat.com>
Date:   Thu May 2 10:25:22 2013 +0800

    vmdk: named return code.
    
    Internal routines in vmdk.c previously return -1 on error and 0 on
    success. More return values are useful for future changes such as
    zeroed-grain GTE. Change all the magic `return 0` and `return -1` to
    macro names:
    
     * VMDK_OK      0
     * VMDK_ERROR   (-1)
     * VMDK_UNALLOC (-2)
     * VMDK_ZEROED  (-3)
    
    Signed-off-by: Fam Zheng <famz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/vmdk.c b/block/vmdk.c
index 7bad757..16aa29c 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -37,6 +37,14 @@
 #define VMDK4_FLAG_MARKER (1 << 17)
 #define VMDK4_GD_AT_END 0xffffffffffffffffULL
 
+
+/* VMDK internal error codes */
+#define VMDK_OK      0
+#define VMDK_ERROR   (-1)
+/* Cluster not allocated */
+#define VMDK_UNALLOC (-2)
+#define VMDK_ZEROED  (-3)
+
 typedef struct {
     uint32_t version;
     uint32_t flags;
@@ -578,22 +586,22 @@ static int vmdk_parse_description(const char *desc, const char *opt_name,
 
     opt_pos = strstr(desc, opt_name);
     if (!opt_pos) {
-        return -1;
+        return VMDK_ERROR;
     }
     /* Skip "=\"" following opt_name */
     opt_pos += strlen(opt_name) + 2;
     if (opt_pos >= end) {
-        return -1;
+        return VMDK_ERROR;
     }
     opt_end = opt_pos;
     while (opt_end < end && *opt_end != '"') {
         opt_end++;
     }
     if (opt_end == end || buf_size < opt_end - opt_pos + 1) {
-        return -1;
+        return VMDK_ERROR;
     }
     pstrcpy(buf, opt_end - opt_pos + 1, opt_pos);
-    return 0;
+    return VMDK_OK;
 }
 
 /* Open an extent file and append to bs array */
@@ -772,7 +780,7 @@ static int get_whole_cluster(BlockDriverState *bs,
         int ret;
 
         if (!vmdk_is_cid_valid(bs)) {
-            return -1;
+            return VMDK_ERROR;
         }
 
         /* floor offset to cluster */
@@ -780,17 +788,17 @@ static int get_whole_cluster(BlockDriverState *bs,
         ret = bdrv_read(bs->backing_hd, offset >> 9, whole_grain,
                 extent->cluster_sectors);
         if (ret < 0) {
-            return -1;
+            return VMDK_ERROR;
         }
 
         /* Write grain only into the active image */
         ret = bdrv_write(extent->file, cluster_offset, whole_grain,
                 extent->cluster_sectors);
         if (ret < 0) {
-            return -1;
+            return VMDK_ERROR;
         }
     }
-    return 0;
+    return VMDK_OK;
 }
 
 static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data)
@@ -803,7 +811,7 @@ static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data)
                 &(m_data->offset),
                 sizeof(m_data->offset)
             ) < 0) {
-        return -1;
+        return VMDK_ERROR;
     }
     /* update backup L2 table */
     if (extent->l1_backup_table_offset != 0) {
@@ -814,11 +822,11 @@ static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data)
                         + (m_data->l2_index * sizeof(m_data->offset)),
                     &(m_data->offset), sizeof(m_data->offset)
                 ) < 0) {
-            return -1;
+            return VMDK_ERROR;
         }
     }
 
-    return 0;
+    return VMDK_OK;
 }
 
 static int get_cluster_offset(BlockDriverState *bs,
@@ -837,17 +845,17 @@ static int get_cluster_offset(BlockDriverState *bs,
     }
     if (extent->flat) {
         *cluster_offset = extent->flat_start_offset;
-        return 0;
+        return VMDK_OK;
     }
 
     offset -= (extent->end_sector - extent->sectors) * SECTOR_SIZE;
     l1_index = (offset >> 9) / extent->l1_entry_sectors;
     if (l1_index >= extent->l1_size) {
-        return -1;
+        return VMDK_ERROR;
     }
     l2_offset = extent->l1_table[l1_index];
     if (!l2_offset) {
-        return -1;
+        return VMDK_UNALLOC;
     }
     for (i = 0; i < L2_CACHE_SIZE; i++) {
         if (l2_offset == extent->l2_cache_offsets[i]) {
@@ -877,7 +885,7 @@ static int get_cluster_offset(BlockDriverState *bs,
                 l2_table,
                 extent->l2_size * sizeof(uint32_t)
             ) != extent->l2_size * sizeof(uint32_t)) {
-        return -1;
+        return VMDK_ERROR;
     }
 
     extent->l2_cache_offsets[min_index] = l2_offset;
@@ -888,7 +896,7 @@ static int get_cluster_offset(BlockDriverState *bs,
 
     if (!*cluster_offset) {
         if (!allocate) {
-            return -1;
+            return VMDK_UNALLOC;
         }
 
         /* Avoid the L2 tables update for the images that have snapshots. */
@@ -911,7 +919,7 @@ static int get_cluster_offset(BlockDriverState *bs,
          */
         if (get_whole_cluster(
                 bs, extent, *cluster_offset, offset, allocate) == -1) {
-            return -1;
+            return VMDK_ERROR;
         }
 
         if (m_data) {
@@ -923,7 +931,7 @@ static int get_cluster_offset(BlockDriverState *bs,
         }
     }
     *cluster_offset <<= 9;
-    return 0;
+    return VMDK_OK;
 }
 
 static VmdkExtent *find_extent(BDRVVmdkState *s,
@@ -1173,7 +1181,7 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
                                 sector_num << 9, !extent->compressed,
                                 &cluster_offset);
         if (extent->compressed) {
-            if (ret == 0) {
+            if (ret == VMDK_OK) {
                 /* Refuse write to allocated cluster for streamOptimized */
                 fprintf(stderr,
                         "VMDK: can't write to allocated cluster"
@@ -1357,7 +1365,7 @@ static int filename_decompose(const char *filename, char *path, char *prefix,
 
     if (filename == NULL || !strlen(filename)) {
         fprintf(stderr, "Vmdk: no filename provided.\n");
-        return -1;
+        return VMDK_ERROR;
     }
     p = strrchr(filename, '/');
     if (p == NULL) {
@@ -1369,7 +1377,7 @@ static int filename_decompose(const char *filename, char *path, char *prefix,
     if (p != NULL) {
         p++;
         if (p - filename >= buf_len) {
-            return -1;
+            return VMDK_ERROR;
         }
         pstrcpy(path, p - filename + 1, filename);
     } else {
@@ -1382,12 +1390,12 @@ static int filename_decompose(const char *filename, char *path, char *prefix,
         postfix[0] = '\0';
     } else {
         if (q - p >= buf_len) {
-            return -1;
+            return VMDK_ERROR;
         }
         pstrcpy(prefix, q - p + 1, p);
         pstrcpy(postfix, buf_len, q);
     }
-    return 0;
+    return VMDK_OK;
 }
 
 static int relative_path(char *dest, int dest_size,
@@ -1403,11 +1411,11 @@ static int relative_path(char *dest, int dest_size,
 #endif
 
     if (!(dest && base && target)) {
-        return -1;
+        return VMDK_ERROR;
     }
     if (path_is_absolute(target)) {
         pstrcpy(dest, dest_size, target);
-        return 0;
+        return VMDK_OK;
     }
     while (base[i] == target[i]) {
         i++;
@@ -1426,7 +1434,7 @@ static int relative_path(char *dest, int dest_size,
         pstrcat(dest, dest_size, sep);
     }
     pstrcat(dest, dest_size, q);
-    return 0;
+    return VMDK_OK;
 }
 
 static int vmdk_create(const char *filename, QEMUOptionParameter *options)
commit 8732901e1b8a5add02a2b747875202133413d565
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Thu May 2 15:32:55 2013 +0200

    blockdev: Replace "undefined error" in qmp_block_resize
    
    We have an errno value that can be displayed, so we should just do that.
    An easy way to reproduce this case is to resize a raw image to a size
    that is too large for the host file system.
    
    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/blockdev.c b/blockdev.c
index 6e293e9..7c9d8dd 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1118,6 +1118,7 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
 void qmp_block_resize(const char *device, int64_t size, Error **errp)
 {
     BlockDriverState *bs;
+    int ret;
 
     bs = bdrv_find(device);
     if (!bs) {
@@ -1133,7 +1134,8 @@ void qmp_block_resize(const char *device, int64_t size, Error **errp)
     /* complete all in-flight operations before resizing the device */
     bdrv_drain_all();
 
-    switch (bdrv_truncate(bs, size)) {
+    ret = bdrv_truncate(bs, size);
+    switch (ret) {
     case 0:
         break;
     case -ENOMEDIUM:
@@ -1149,7 +1151,7 @@ void qmp_block_resize(const char *device, int64_t size, Error **errp)
         error_set(errp, QERR_DEVICE_IN_USE, device);
         break;
     default:
-        error_set(errp, QERR_UNDEFINED_ERROR);
+        error_setg_errno(errp, -ret, "Could not resize");
         break;
     }
 }
commit 059e2fbbca484a68ac7fd99d1d76409294551586
Author: Jeff Cody <jcody at redhat.com>
Date:   Mon Apr 29 14:48:19 2013 -0400

    block: add read-only support to VHDX image format.
    
    This adds in read-only support to the VHDX image format.  This supports
    reads for fixed-size, and dynamic sized VHDX images.
    
    Differencing files are still unsupported.
    
    The image must be opened without BDRV_O_RDWR set, because we do not
    yet update the headers.  I.e., pass 'readonly=on' in the drive image
    options from the QEMU commandline.
    
    Signed-off-by: Jeff Cody <jcody at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/vhdx.c b/block/vhdx.c
index 0ee10a7..e9704b1 100644
--- a/block/vhdx.c
+++ b/block/vhdx.c
@@ -114,6 +114,17 @@ typedef struct VHDXMetadataEntries {
 } VHDXMetadataEntries;
 
 
+typedef struct VHDXSectorInfo {
+    uint32_t bat_idx;       /* BAT entry index */
+    uint32_t sectors_avail; /* sectors available in payload block */
+    uint32_t bytes_left;    /* bytes left in the block after data to r/w */
+    uint32_t bytes_avail;   /* bytes available in payload block */
+    uint64_t file_offset;   /* absolute offset in bytes, in file */
+    uint64_t block_offset;  /* block offset, in bytes */
+} VHDXSectorInfo;
+
+
+
 typedef struct BDRVVHDXState {
     CoMutex lock;
 
@@ -792,7 +803,7 @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags)
         goto fail;
     }
 
-    /* TODO: differencing files, read, write */
+    /* TODO: differencing files, write */
 
     return 0;
 fail:
@@ -810,10 +821,118 @@ static int vhdx_reopen_prepare(BDRVReopenState *state,
 }
 
 
+/*
+ * Perform sector to block offset translations, to get various
+ * sector and file offsets into the image.  See VHDXSectorInfo
+ */
+static void vhdx_block_translate(BDRVVHDXState *s, int64_t sector_num,
+                                 int nb_sectors, VHDXSectorInfo *sinfo)
+{
+    uint32_t block_offset;
+
+    sinfo->bat_idx = sector_num >> s->sectors_per_block_bits;
+    /* effectively a modulo - this gives us the offset into the block
+     * (in sector sizes) for our sector number */
+    block_offset = sector_num - (sinfo->bat_idx << s->sectors_per_block_bits);
+    /* the chunk ratio gives us the interleaving of the sector
+     * bitmaps, so we need to advance our page block index by the
+     * sector bitmaps entry number */
+    sinfo->bat_idx += sinfo->bat_idx >> s->chunk_ratio_bits;
+
+    /* the number of sectors we can read/write in this cycle */
+    sinfo->sectors_avail = s->sectors_per_block - block_offset;
+
+    sinfo->bytes_left = sinfo->sectors_avail << s->logical_sector_size_bits;
+
+    if (sinfo->sectors_avail > nb_sectors) {
+        sinfo->sectors_avail = nb_sectors;
+    }
+
+    sinfo->bytes_avail = sinfo->sectors_avail << s->logical_sector_size_bits;
+
+    sinfo->file_offset = s->bat[sinfo->bat_idx] >> VHDX_BAT_FILE_OFF_BITS;
+
+    sinfo->block_offset = block_offset << s->logical_sector_size_bits;
+
+    /* The file offset must be past the header section, so must be > 0 */
+    if (sinfo->file_offset == 0) {
+        return;
+    }
+
+    /* block offset is the offset in vhdx logical sectors, in
+     * the payload data block. Convert that to a byte offset
+     * in the block, and add in the payload data block offset
+     * in the file, in bytes, to get the final read address */
+
+    sinfo->file_offset <<= 20;  /* now in bytes, rather than 1MB units */
+    sinfo->file_offset += sinfo->block_offset;
+}
+
+
+
 static coroutine_fn int vhdx_co_readv(BlockDriverState *bs, int64_t sector_num,
                                       int nb_sectors, QEMUIOVector *qiov)
 {
-    return -ENOTSUP;
+    BDRVVHDXState *s = bs->opaque;
+    int ret = 0;
+    VHDXSectorInfo sinfo;
+    uint64_t bytes_done = 0;
+    QEMUIOVector hd_qiov;
+
+    qemu_iovec_init(&hd_qiov, qiov->niov);
+
+    qemu_co_mutex_lock(&s->lock);
+
+    while (nb_sectors > 0) {
+        /* We are a differencing file, so we need to inspect the sector bitmap
+         * to see if we have the data or not */
+        if (s->params.data_bits & VHDX_PARAMS_HAS_PARENT) {
+            /* not supported yet */
+            ret = -ENOTSUP;
+            goto exit;
+        } else {
+            vhdx_block_translate(s, sector_num, nb_sectors, &sinfo);
+
+            qemu_iovec_reset(&hd_qiov);
+            qemu_iovec_concat(&hd_qiov, qiov,  bytes_done, sinfo.bytes_avail);
+
+            /* check the payload block state */
+            switch (s->bat[sinfo.bat_idx] & VHDX_BAT_STATE_BIT_MASK) {
+            case PAYLOAD_BLOCK_NOT_PRESENT: /* fall through */
+            case PAYLOAD_BLOCK_UNDEFINED:   /* fall through */
+            case PAYLOAD_BLOCK_UNMAPPED:    /* fall through */
+            case PAYLOAD_BLOCK_ZERO:
+                /* return zero */
+                qemu_iovec_memset(&hd_qiov, 0, 0, sinfo.bytes_avail);
+                break;
+            case PAYLOAD_BLOCK_FULL_PRESENT:
+                qemu_co_mutex_unlock(&s->lock);
+                ret = bdrv_co_readv(bs->file,
+                                    sinfo.file_offset >> BDRV_SECTOR_BITS,
+                                    sinfo.sectors_avail, &hd_qiov);
+                qemu_co_mutex_lock(&s->lock);
+                if (ret < 0) {
+                    goto exit;
+                }
+                break;
+            case PAYLOAD_BLOCK_PARTIALLY_PRESENT:
+                /* we don't yet support difference files, fall through
+                 * to error */
+            default:
+                ret = -EIO;
+                goto exit;
+                break;
+            }
+            nb_sectors -= sinfo.sectors_avail;
+            sector_num += sinfo.sectors_avail;
+            bytes_done += sinfo.bytes_avail;
+        }
+    }
+    ret = 0;
+exit:
+    qemu_co_mutex_unlock(&s->lock);
+    qemu_iovec_destroy(&hd_qiov);
+    return ret;
 }
 
 
commit e8d4e5ffdb015959551726a5700c19b5d772ada4
Author: Jeff Cody <jcody at redhat.com>
Date:   Mon Apr 29 14:48:18 2013 -0400

    block: initial VHDX driver support framework - supports open and probe
    
    This is the initial block driver framework for VHDX image support
    (i.e. Hyper-V image file formats), that supports opening VHDX files, and
    parsing the headers.
    
    This commit does not yet enable:
        - reading
        - writing
        - updating the header
        - differencing files (images with parents)
        - log replay / dirty logs (only clean images)
    
    This is based on Microsoft's VHDX specification:
        "VHDX Format Specification v0.95", published 4/12/2012
        https://www.microsoft.com/en-us/download/details.aspx?id=29681
    
    Signed-off-by: Jeff Cody <jcody at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/Makefile.objs b/block/Makefile.objs
index 6c4b5bc..5f0358a 100644
--- a/block/Makefile.objs
+++ b/block/Makefile.objs
@@ -2,6 +2,7 @@ block-obj-y += raw.o cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o vpc.o vvfat
 block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o
 block-obj-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o
 block-obj-y += qed-check.o
+block-obj-y += vhdx.o
 block-obj-y += parallels.o blkdebug.o blkverify.o
 block-obj-$(CONFIG_WIN32) += raw-win32.o win32-aio.o
 block-obj-$(CONFIG_POSIX) += raw-posix.o
diff --git a/block/vhdx.c b/block/vhdx.c
new file mode 100644
index 0000000..0ee10a7
--- /dev/null
+++ b/block/vhdx.c
@@ -0,0 +1,853 @@
+/*
+ * Block driver for Hyper-V VHDX Images
+ *
+ * Copyright (c) 2013 Red Hat, Inc.,
+ *
+ * Authors:
+ *  Jeff Cody <jcody at redhat.com>
+ *
+ *  This is based on the "VHDX Format Specification v0.95", published 4/12/2012
+ *  by Microsoft:
+ *      https://www.microsoft.com/en-us/download/details.aspx?id=29681
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qemu-common.h"
+#include "block/block_int.h"
+#include "qemu/module.h"
+#include "qemu/crc32c.h"
+#include "block/vhdx.h"
+
+
+/* Several metadata and region table data entries are identified by
+ * guids in  a MS-specific GUID format. */
+
+
+/* ------- Known Region Table GUIDs ---------------------- */
+static const MSGUID bat_guid =      { .data1 = 0x2dc27766,
+                                      .data2 = 0xf623,
+                                      .data3 = 0x4200,
+                                      .data4 = { 0x9d, 0x64, 0x11, 0x5e,
+                                                 0x9b, 0xfd, 0x4a, 0x08} };
+
+static const MSGUID metadata_guid = { .data1 = 0x8b7ca206,
+                                      .data2 = 0x4790,
+                                      .data3 = 0x4b9a,
+                                      .data4 = { 0xb8, 0xfe, 0x57, 0x5f,
+                                                 0x05, 0x0f, 0x88, 0x6e} };
+
+
+
+/* ------- Known Metadata Entry GUIDs ---------------------- */
+static const MSGUID file_param_guid =   { .data1 = 0xcaa16737,
+                                          .data2 = 0xfa36,
+                                          .data3 = 0x4d43,
+                                          .data4 = { 0xb3, 0xb6, 0x33, 0xf0,
+                                                     0xaa, 0x44, 0xe7, 0x6b} };
+
+static const MSGUID virtual_size_guid = { .data1 = 0x2FA54224,
+                                          .data2 = 0xcd1b,
+                                          .data3 = 0x4876,
+                                          .data4 = { 0xb2, 0x11, 0x5d, 0xbe,
+                                                     0xd8, 0x3b, 0xf4, 0xb8} };
+
+static const MSGUID page83_guid =       { .data1 = 0xbeca12ab,
+                                          .data2 = 0xb2e6,
+                                          .data3 = 0x4523,
+                                          .data4 = { 0x93, 0xef, 0xc3, 0x09,
+                                                     0xe0, 0x00, 0xc7, 0x46} };
+
+
+static const MSGUID phys_sector_guid =  { .data1 = 0xcda348c7,
+                                          .data2 = 0x445d,
+                                          .data3 = 0x4471,
+                                          .data4 = { 0x9c, 0xc9, 0xe9, 0x88,
+                                                     0x52, 0x51, 0xc5, 0x56} };
+
+static const MSGUID parent_locator_guid = { .data1 = 0xa8d35f2d,
+                                            .data2 = 0xb30b,
+                                            .data3 = 0x454d,
+                                            .data4 = { 0xab, 0xf7, 0xd3,
+                                                       0xd8, 0x48, 0x34,
+                                                       0xab, 0x0c} };
+
+static const MSGUID logical_sector_guid = { .data1 = 0x8141bf1d,
+                                            .data2 = 0xa96f,
+                                            .data3 = 0x4709,
+                                            .data4 = { 0xba, 0x47, 0xf2,
+                                                       0x33, 0xa8, 0xfa,
+                                                       0xab, 0x5f} };
+
+/* Each parent type must have a valid GUID; this is for parent images
+ * of type 'VHDX'.  If we were to allow e.g. a QCOW2 parent, we would
+ * need to make up our own QCOW2 GUID type */
+static const MSGUID parent_vhdx_guid = { .data1 = 0xb04aefb7,
+                                         .data2 = 0xd19e,
+                                         .data3 = 0x4a81,
+                                         .data4 = { 0xb7, 0x89, 0x25, 0xb8,
+                                                    0xe9, 0x44, 0x59, 0x13} };
+
+
+#define META_FILE_PARAMETER_PRESENT      0x01
+#define META_VIRTUAL_DISK_SIZE_PRESENT   0x02
+#define META_PAGE_83_PRESENT             0x04
+#define META_LOGICAL_SECTOR_SIZE_PRESENT 0x08
+#define META_PHYS_SECTOR_SIZE_PRESENT    0x10
+#define META_PARENT_LOCATOR_PRESENT      0x20
+
+#define META_ALL_PRESENT    \
+    (META_FILE_PARAMETER_PRESENT | META_VIRTUAL_DISK_SIZE_PRESENT | \
+     META_PAGE_83_PRESENT | META_LOGICAL_SECTOR_SIZE_PRESENT | \
+     META_PHYS_SECTOR_SIZE_PRESENT)
+
+typedef struct VHDXMetadataEntries {
+    VHDXMetadataTableEntry file_parameters_entry;
+    VHDXMetadataTableEntry virtual_disk_size_entry;
+    VHDXMetadataTableEntry page83_data_entry;
+    VHDXMetadataTableEntry logical_sector_size_entry;
+    VHDXMetadataTableEntry phys_sector_size_entry;
+    VHDXMetadataTableEntry parent_locator_entry;
+    uint16_t present;
+} VHDXMetadataEntries;
+
+
+typedef struct BDRVVHDXState {
+    CoMutex lock;
+
+    int curr_header;
+    VHDXHeader *headers[2];
+
+    VHDXRegionTableHeader rt;
+    VHDXRegionTableEntry bat_rt;         /* region table for the BAT */
+    VHDXRegionTableEntry metadata_rt;    /* region table for the metadata */
+
+    VHDXMetadataTableHeader metadata_hdr;
+    VHDXMetadataEntries metadata_entries;
+
+    VHDXFileParameters params;
+    uint32_t block_size;
+    uint32_t block_size_bits;
+    uint32_t sectors_per_block;
+    uint32_t sectors_per_block_bits;
+
+    uint64_t virtual_disk_size;
+    uint32_t logical_sector_size;
+    uint32_t physical_sector_size;
+
+    uint64_t chunk_ratio;
+    uint32_t chunk_ratio_bits;
+    uint32_t logical_sector_size_bits;
+
+    uint32_t bat_entries;
+    VHDXBatEntry *bat;
+    uint64_t bat_offset;
+
+    VHDXParentLocatorHeader parent_header;
+    VHDXParentLocatorEntry *parent_entries;
+
+} BDRVVHDXState;
+
+uint32_t vhdx_checksum_calc(uint32_t crc, uint8_t *buf, size_t size,
+                            int crc_offset)
+{
+    uint32_t crc_new;
+    uint32_t crc_orig;
+    assert(buf != NULL);
+
+    if (crc_offset > 0) {
+        memcpy(&crc_orig, buf + crc_offset, sizeof(crc_orig));
+        memset(buf + crc_offset, 0, sizeof(crc_orig));
+    }
+
+    crc_new = crc32c(crc, buf, size);
+    if (crc_offset > 0) {
+        memcpy(buf + crc_offset, &crc_orig, sizeof(crc_orig));
+    }
+
+    return crc_new;
+}
+
+/* Validates the checksum of the buffer, with an in-place CRC.
+ *
+ * Zero is substituted during crc calculation for the original crc field,
+ * and the crc field is restored afterwards.  But the buffer will be modifed
+ * during the calculation, so this may not be not suitable for multi-threaded
+ * use.
+ *
+ * crc_offset: byte offset in buf of the buffer crc
+ * buf: buffer pointer
+ * size: size of buffer (must be > crc_offset+4)
+ *
+ * returns true if checksum is valid, false otherwise
+ */
+bool vhdx_checksum_is_valid(uint8_t *buf, size_t size, int crc_offset)
+{
+    uint32_t crc_orig;
+    uint32_t crc;
+
+    assert(buf != NULL);
+    assert(size > (crc_offset + 4));
+
+    memcpy(&crc_orig, buf + crc_offset, sizeof(crc_orig));
+    crc_orig = le32_to_cpu(crc_orig);
+
+    crc = vhdx_checksum_calc(0xffffffff, buf, size, crc_offset);
+
+    return crc == crc_orig;
+}
+
+
+/*
+ * Per the MS VHDX Specification, for every VHDX file:
+ *      - The header section is fixed size - 1 MB
+ *      - The header section is always the first "object"
+ *      - The first 64KB of the header is the File Identifier
+ *      - The first uint64 (8 bytes) is the VHDX Signature ("vhdxfile")
+ *      - The following 512 bytes constitute a UTF-16 string identifiying the
+ *        software that created the file, and is optional and diagnostic only.
+ *
+ *  Therefore, we probe by looking for the vhdxfile signature "vhdxfile"
+ */
+static int vhdx_probe(const uint8_t *buf, int buf_size, const char *filename)
+{
+    if (buf_size >= 8 && !memcmp(buf, "vhdxfile", 8)) {
+        return 100;
+    }
+    return 0;
+}
+
+/* All VHDX structures on disk are little endian */
+static void vhdx_header_le_import(VHDXHeader *h)
+{
+    assert(h != NULL);
+
+    le32_to_cpus(&h->signature);
+    le32_to_cpus(&h->checksum);
+    le64_to_cpus(&h->sequence_number);
+
+    leguid_to_cpus(&h->file_write_guid);
+    leguid_to_cpus(&h->data_write_guid);
+    leguid_to_cpus(&h->log_guid);
+
+    le16_to_cpus(&h->log_version);
+    le16_to_cpus(&h->version);
+    le32_to_cpus(&h->log_length);
+    le64_to_cpus(&h->log_offset);
+}
+
+
+/* opens the specified header block from the VHDX file header section */
+static int vhdx_parse_header(BlockDriverState *bs, BDRVVHDXState *s)
+{
+    int ret = 0;
+    VHDXHeader *header1;
+    VHDXHeader *header2;
+    bool h1_valid = false;
+    bool h2_valid = false;
+    uint64_t h1_seq = 0;
+    uint64_t h2_seq = 0;
+    uint8_t *buffer;
+
+    header1 = qemu_blockalign(bs, sizeof(VHDXHeader));
+    header2 = qemu_blockalign(bs, sizeof(VHDXHeader));
+
+    buffer = qemu_blockalign(bs, VHDX_HEADER_SIZE);
+
+    s->headers[0] = header1;
+    s->headers[1] = header2;
+
+    /* We have to read the whole VHDX_HEADER_SIZE instead of
+     * sizeof(VHDXHeader), because the checksum is over the whole
+     * region */
+    ret = bdrv_pread(bs->file, VHDX_HEADER1_OFFSET, buffer, VHDX_HEADER_SIZE);
+    if (ret < 0) {
+        goto fail;
+    }
+    /* copy over just the relevant portion that we need */
+    memcpy(header1, buffer, sizeof(VHDXHeader));
+    vhdx_header_le_import(header1);
+
+    if (vhdx_checksum_is_valid(buffer, VHDX_HEADER_SIZE, 4) &&
+        !memcmp(&header1->signature, "head", 4)             &&
+        header1->version == 1) {
+        h1_seq = header1->sequence_number;
+        h1_valid = true;
+    }
+
+    ret = bdrv_pread(bs->file, VHDX_HEADER2_OFFSET, buffer, VHDX_HEADER_SIZE);
+    if (ret < 0) {
+        goto fail;
+    }
+    /* copy over just the relevant portion that we need */
+    memcpy(header2, buffer, sizeof(VHDXHeader));
+    vhdx_header_le_import(header2);
+
+    if (vhdx_checksum_is_valid(buffer, VHDX_HEADER_SIZE, 4) &&
+        !memcmp(&header2->signature, "head", 4)             &&
+        header2->version == 1) {
+        h2_seq = header2->sequence_number;
+        h2_valid = true;
+    }
+
+    /* If there is only 1 valid header (or no valid headers), we
+     * don't care what the sequence numbers are */
+    if (h1_valid && !h2_valid) {
+        s->curr_header = 0;
+    } else if (!h1_valid && h2_valid) {
+        s->curr_header = 1;
+    } else if (!h1_valid && !h2_valid) {
+        ret = -EINVAL;
+        goto fail;
+    } else {
+        /* If both headers are valid, then we choose the active one by the
+         * highest sequence number.  If the sequence numbers are equal, that is
+         * invalid */
+        if (h1_seq > h2_seq) {
+            s->curr_header = 0;
+        } else if (h2_seq > h1_seq) {
+            s->curr_header = 1;
+        } else {
+            ret = -EINVAL;
+            goto fail;
+        }
+    }
+
+    ret = 0;
+
+    goto exit;
+
+fail:
+    qerror_report(ERROR_CLASS_GENERIC_ERROR, "No valid VHDX header found");
+    qemu_vfree(header1);
+    qemu_vfree(header2);
+    s->headers[0] = NULL;
+    s->headers[1] = NULL;
+exit:
+    qemu_vfree(buffer);
+    return ret;
+}
+
+
+static int vhdx_open_region_tables(BlockDriverState *bs, BDRVVHDXState *s)
+{
+    int ret = 0;
+    uint8_t *buffer;
+    int offset = 0;
+    VHDXRegionTableEntry rt_entry;
+    uint32_t i;
+    bool bat_rt_found = false;
+    bool metadata_rt_found = false;
+
+    /* We have to read the whole 64KB block, because the crc32 is over the
+     * whole block */
+    buffer = qemu_blockalign(bs, VHDX_HEADER_BLOCK_SIZE);
+
+    ret = bdrv_pread(bs->file, VHDX_REGION_TABLE_OFFSET, buffer,
+                     VHDX_HEADER_BLOCK_SIZE);
+    if (ret < 0) {
+        goto fail;
+    }
+    memcpy(&s->rt, buffer, sizeof(s->rt));
+    le32_to_cpus(&s->rt.signature);
+    le32_to_cpus(&s->rt.checksum);
+    le32_to_cpus(&s->rt.entry_count);
+    le32_to_cpus(&s->rt.reserved);
+    offset += sizeof(s->rt);
+
+    if (!vhdx_checksum_is_valid(buffer, VHDX_HEADER_BLOCK_SIZE, 4) ||
+        memcmp(&s->rt.signature, "regi", 4)) {
+        ret = -EINVAL;
+        goto fail;
+    }
+
+    /* Per spec, maximum region table entry count is 2047 */
+    if (s->rt.entry_count > 2047) {
+        ret = -EINVAL;
+        goto fail;
+    }
+
+    for (i = 0; i < s->rt.entry_count; i++) {
+        memcpy(&rt_entry, buffer + offset, sizeof(rt_entry));
+        offset += sizeof(rt_entry);
+
+        leguid_to_cpus(&rt_entry.guid);
+        le64_to_cpus(&rt_entry.file_offset);
+        le32_to_cpus(&rt_entry.length);
+        le32_to_cpus(&rt_entry.data_bits);
+
+        /* see if we recognize the entry */
+        if (guid_eq(rt_entry.guid, bat_guid)) {
+            /* must be unique; if we have already found it this is invalid */
+            if (bat_rt_found) {
+                ret = -EINVAL;
+                goto fail;
+            }
+            bat_rt_found = true;
+            s->bat_rt = rt_entry;
+            continue;
+        }
+
+        if (guid_eq(rt_entry.guid, metadata_guid)) {
+            /* must be unique; if we have already found it this is invalid */
+            if (metadata_rt_found) {
+                ret = -EINVAL;
+                goto fail;
+            }
+            metadata_rt_found = true;
+            s->metadata_rt = rt_entry;
+            continue;
+        }
+
+        if (rt_entry.data_bits & VHDX_REGION_ENTRY_REQUIRED) {
+            /* cannot read vhdx file - required region table entry that
+             * we do not understand.  per spec, we must fail to open */
+            ret = -ENOTSUP;
+            goto fail;
+        }
+    }
+    ret = 0;
+
+fail:
+    qemu_vfree(buffer);
+    return ret;
+}
+
+
+
+/* Metadata initial parser
+ *
+ * This loads all the metadata entry fields.  This may cause additional
+ * fields to be processed (e.g. parent locator, etc..).
+ *
+ * There are 5 Metadata items that are always required:
+ *      - File Parameters (block size, has a parent)
+ *      - Virtual Disk Size (size, in bytes, of the virtual drive)
+ *      - Page 83 Data (scsi page 83 guid)
+ *      - Logical Sector Size (logical sector size in bytes, either 512 or
+ *                             4096.  We only support 512 currently)
+ *      - Physical Sector Size (512 or 4096)
+ *
+ * Also, if the File Parameters indicate this is a differencing file,
+ * we must also look for the Parent Locator metadata item.
+ */
+static int vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s)
+{
+    int ret = 0;
+    uint8_t *buffer;
+    int offset = 0;
+    uint32_t i = 0;
+    VHDXMetadataTableEntry md_entry;
+
+    buffer = qemu_blockalign(bs, VHDX_METADATA_TABLE_MAX_SIZE);
+
+    ret = bdrv_pread(bs->file, s->metadata_rt.file_offset, buffer,
+                     VHDX_METADATA_TABLE_MAX_SIZE);
+    if (ret < 0) {
+        goto exit;
+    }
+    memcpy(&s->metadata_hdr, buffer, sizeof(s->metadata_hdr));
+    offset += sizeof(s->metadata_hdr);
+
+    le64_to_cpus(&s->metadata_hdr.signature);
+    le16_to_cpus(&s->metadata_hdr.reserved);
+    le16_to_cpus(&s->metadata_hdr.entry_count);
+
+    if (memcmp(&s->metadata_hdr.signature, "metadata", 8)) {
+        ret = -EINVAL;
+        goto exit;
+    }
+
+    s->metadata_entries.present = 0;
+
+    if ((s->metadata_hdr.entry_count * sizeof(md_entry)) >
+        (VHDX_METADATA_TABLE_MAX_SIZE - offset)) {
+        ret = -EINVAL;
+        goto exit;
+    }
+
+    for (i = 0; i < s->metadata_hdr.entry_count; i++) {
+        memcpy(&md_entry, buffer + offset, sizeof(md_entry));
+        offset += sizeof(md_entry);
+
+        leguid_to_cpus(&md_entry.item_id);
+        le32_to_cpus(&md_entry.offset);
+        le32_to_cpus(&md_entry.length);
+        le32_to_cpus(&md_entry.data_bits);
+        le32_to_cpus(&md_entry.reserved2);
+
+        if (guid_eq(md_entry.item_id, file_param_guid)) {
+            if (s->metadata_entries.present & META_FILE_PARAMETER_PRESENT) {
+                ret = -EINVAL;
+                goto exit;
+            }
+            s->metadata_entries.file_parameters_entry = md_entry;
+            s->metadata_entries.present |= META_FILE_PARAMETER_PRESENT;
+            continue;
+        }
+
+        if (guid_eq(md_entry.item_id, virtual_size_guid)) {
+            if (s->metadata_entries.present & META_VIRTUAL_DISK_SIZE_PRESENT) {
+                ret = -EINVAL;
+                goto exit;
+            }
+            s->metadata_entries.virtual_disk_size_entry = md_entry;
+            s->metadata_entries.present |= META_VIRTUAL_DISK_SIZE_PRESENT;
+            continue;
+        }
+
+        if (guid_eq(md_entry.item_id, page83_guid)) {
+            if (s->metadata_entries.present & META_PAGE_83_PRESENT) {
+                ret = -EINVAL;
+                goto exit;
+            }
+            s->metadata_entries.page83_data_entry = md_entry;
+            s->metadata_entries.present |= META_PAGE_83_PRESENT;
+            continue;
+        }
+
+        if (guid_eq(md_entry.item_id, logical_sector_guid)) {
+            if (s->metadata_entries.present &
+                META_LOGICAL_SECTOR_SIZE_PRESENT) {
+                ret = -EINVAL;
+                goto exit;
+            }
+            s->metadata_entries.logical_sector_size_entry = md_entry;
+            s->metadata_entries.present |= META_LOGICAL_SECTOR_SIZE_PRESENT;
+            continue;
+        }
+
+        if (guid_eq(md_entry.item_id, phys_sector_guid)) {
+            if (s->metadata_entries.present & META_PHYS_SECTOR_SIZE_PRESENT) {
+                ret = -EINVAL;
+                goto exit;
+            }
+            s->metadata_entries.phys_sector_size_entry = md_entry;
+            s->metadata_entries.present |= META_PHYS_SECTOR_SIZE_PRESENT;
+            continue;
+        }
+
+        if (guid_eq(md_entry.item_id, parent_locator_guid)) {
+            if (s->metadata_entries.present & META_PARENT_LOCATOR_PRESENT) {
+                ret = -EINVAL;
+                goto exit;
+            }
+            s->metadata_entries.parent_locator_entry = md_entry;
+            s->metadata_entries.present |= META_PARENT_LOCATOR_PRESENT;
+            continue;
+        }
+
+        if (md_entry.data_bits & VHDX_META_FLAGS_IS_REQUIRED) {
+            /* cannot read vhdx file - required region table entry that
+             * we do not understand.  per spec, we must fail to open */
+            ret = -ENOTSUP;
+            goto exit;
+        }
+    }
+
+    if (s->metadata_entries.present != META_ALL_PRESENT) {
+        ret = -ENOTSUP;
+        goto exit;
+    }
+
+    ret = bdrv_pread(bs->file,
+                     s->metadata_entries.file_parameters_entry.offset
+                                         + s->metadata_rt.file_offset,
+                     &s->params,
+                     sizeof(s->params));
+
+    if (ret < 0) {
+        goto exit;
+    }
+
+    le32_to_cpus(&s->params.block_size);
+    le32_to_cpus(&s->params.data_bits);
+
+
+    /* We now have the file parameters, so we can tell if this is a
+     * differencing file (i.e.. has_parent), is dynamic or fixed
+     * sized (leave_blocks_allocated), and the block size */
+
+    /* The parent locator required iff the file parameters has_parent set */
+    if (s->params.data_bits & VHDX_PARAMS_HAS_PARENT) {
+        if (s->metadata_entries.present & META_PARENT_LOCATOR_PRESENT) {
+            /* TODO: parse  parent locator fields */
+            ret = -ENOTSUP; /* temp, until differencing files are supported */
+            goto exit;
+        } else {
+            /* if has_parent is set, but there is not parent locator present,
+             * then that is an invalid combination */
+            ret = -EINVAL;
+            goto exit;
+        }
+    }
+
+    /* determine virtual disk size, logical sector size,
+     * and phys sector size */
+
+    ret = bdrv_pread(bs->file,
+                     s->metadata_entries.virtual_disk_size_entry.offset
+                                           + s->metadata_rt.file_offset,
+                     &s->virtual_disk_size,
+                     sizeof(uint64_t));
+    if (ret < 0) {
+        goto exit;
+    }
+    ret = bdrv_pread(bs->file,
+                     s->metadata_entries.logical_sector_size_entry.offset
+                                             + s->metadata_rt.file_offset,
+                     &s->logical_sector_size,
+                     sizeof(uint32_t));
+    if (ret < 0) {
+        goto exit;
+    }
+    ret = bdrv_pread(bs->file,
+                     s->metadata_entries.phys_sector_size_entry.offset
+                                          + s->metadata_rt.file_offset,
+                     &s->physical_sector_size,
+                     sizeof(uint32_t));
+    if (ret < 0) {
+        goto exit;
+    }
+
+    le64_to_cpus(&s->virtual_disk_size);
+    le32_to_cpus(&s->logical_sector_size);
+    le32_to_cpus(&s->physical_sector_size);
+
+    if (s->logical_sector_size == 0 || s->params.block_size == 0) {
+        ret = -EINVAL;
+        goto exit;
+    }
+
+    /* both block_size and sector_size are guaranteed powers of 2 */
+    s->sectors_per_block = s->params.block_size / s->logical_sector_size;
+    s->chunk_ratio = (VHDX_MAX_SECTORS_PER_BLOCK) *
+                     (uint64_t)s->logical_sector_size /
+                     (uint64_t)s->params.block_size;
+
+    /* These values are ones we will want to use for division / multiplication
+     * later on, and they are all guaranteed (per the spec) to be powers of 2,
+     * so we can take advantage of that for shift operations during
+     * reads/writes */
+    if (s->logical_sector_size & (s->logical_sector_size - 1)) {
+        ret = -EINVAL;
+        goto exit;
+    }
+    if (s->sectors_per_block & (s->sectors_per_block - 1)) {
+        ret = -EINVAL;
+        goto exit;
+    }
+    if (s->chunk_ratio & (s->chunk_ratio - 1)) {
+        ret = -EINVAL;
+        goto exit;
+    }
+    s->block_size = s->params.block_size;
+    if (s->block_size & (s->block_size - 1)) {
+        ret = -EINVAL;
+        goto exit;
+    }
+
+    s->logical_sector_size_bits = 31 - clz32(s->logical_sector_size);
+    s->sectors_per_block_bits =   31 - clz32(s->sectors_per_block);
+    s->chunk_ratio_bits =         63 - clz64(s->chunk_ratio);
+    s->block_size_bits =          31 - clz32(s->block_size);
+
+    ret = 0;
+
+exit:
+    qemu_vfree(buffer);
+    return ret;
+}
+
+/* Parse the replay log.  Per the VHDX spec, if the log is present
+ * it must be replayed prior to opening the file, even read-only.
+ *
+ * If read-only, we must replay the log in RAM (or refuse to open
+ * a dirty VHDX file read-only */
+static int vhdx_parse_log(BlockDriverState *bs, BDRVVHDXState *s)
+{
+    int ret = 0;
+    int i;
+    VHDXHeader *hdr;
+
+    hdr = s->headers[s->curr_header];
+
+    /* either the log guid, or log length is zero,
+     * then a replay log is present */
+    for (i = 0; i < sizeof(hdr->log_guid.data4); i++) {
+        ret |= hdr->log_guid.data4[i];
+    }
+    if (hdr->log_guid.data1 == 0 &&
+        hdr->log_guid.data2 == 0 &&
+        hdr->log_guid.data3 == 0 &&
+        ret == 0) {
+        goto exit;
+    }
+
+    /* per spec, only log version of 0 is supported */
+    if (hdr->log_version != 0) {
+        ret = -EINVAL;
+        goto exit;
+    }
+
+    if (hdr->log_length == 0) {
+        goto exit;
+    }
+
+    /* We currently do not support images with logs to replay */
+    ret = -ENOTSUP;
+
+exit:
+    return ret;
+}
+
+
+static int vhdx_open(BlockDriverState *bs, QDict *options, int flags)
+{
+    BDRVVHDXState *s = bs->opaque;
+    int ret = 0;
+    uint32_t i;
+    uint64_t signature;
+    uint32_t data_blocks_cnt, bitmap_blocks_cnt;
+
+
+    s->bat = NULL;
+
+    qemu_co_mutex_init(&s->lock);
+
+    /* validate the file signature */
+    ret = bdrv_pread(bs->file, 0, &signature, sizeof(uint64_t));
+    if (ret < 0) {
+        goto fail;
+    }
+    if (memcmp(&signature, "vhdxfile", 8)) {
+        ret = -EINVAL;
+        goto fail;
+    }
+
+    ret = vhdx_parse_header(bs, s);
+    if (ret) {
+        goto fail;
+    }
+
+    ret = vhdx_parse_log(bs, s);
+    if (ret) {
+        goto fail;
+    }
+
+    ret = vhdx_open_region_tables(bs, s);
+    if (ret) {
+        goto fail;
+    }
+
+    ret = vhdx_parse_metadata(bs, s);
+    if (ret) {
+        goto fail;
+    }
+    s->block_size = s->params.block_size;
+
+    /* the VHDX spec dictates that virtual_disk_size is always a multiple of
+     * logical_sector_size */
+    bs->total_sectors = s->virtual_disk_size >> s->logical_sector_size_bits;
+
+    data_blocks_cnt = s->virtual_disk_size >> s->block_size_bits;
+    if (s->virtual_disk_size - (data_blocks_cnt << s->block_size_bits)) {
+        data_blocks_cnt++;
+    }
+    bitmap_blocks_cnt = data_blocks_cnt >> s->chunk_ratio_bits;
+    if (data_blocks_cnt - (bitmap_blocks_cnt << s->chunk_ratio_bits)) {
+        bitmap_blocks_cnt++;
+    }
+
+    if (s->parent_entries) {
+        s->bat_entries = bitmap_blocks_cnt * (s->chunk_ratio + 1);
+    } else {
+        s->bat_entries = data_blocks_cnt +
+                         ((data_blocks_cnt - 1) >> s->chunk_ratio_bits);
+    }
+
+    s->bat_offset = s->bat_rt.file_offset;
+
+    if (s->bat_entries > s->bat_rt.length / sizeof(VHDXBatEntry)) {
+        /* BAT allocation is not large enough for all entries */
+        ret = -EINVAL;
+        goto fail;
+    }
+
+    s->bat = qemu_blockalign(bs, s->bat_rt.length);
+
+    ret = bdrv_pread(bs->file, s->bat_offset, s->bat, s->bat_rt.length);
+    if (ret < 0) {
+        goto fail;
+    }
+
+    for (i = 0; i < s->bat_entries; i++) {
+        le64_to_cpus(&s->bat[i]);
+    }
+
+    if (flags & BDRV_O_RDWR) {
+        ret = -ENOTSUP;
+        goto fail;
+    }
+
+    /* TODO: differencing files, read, write */
+
+    return 0;
+fail:
+    qemu_vfree(s->headers[0]);
+    qemu_vfree(s->headers[1]);
+    qemu_vfree(s->bat);
+    qemu_vfree(s->parent_entries);
+    return ret;
+}
+
+static int vhdx_reopen_prepare(BDRVReopenState *state,
+                               BlockReopenQueue *queue, Error **errp)
+{
+    return 0;
+}
+
+
+static coroutine_fn int vhdx_co_readv(BlockDriverState *bs, int64_t sector_num,
+                                      int nb_sectors, QEMUIOVector *qiov)
+{
+    return -ENOTSUP;
+}
+
+
+
+static coroutine_fn int vhdx_co_writev(BlockDriverState *bs, int64_t sector_num,
+                                      int nb_sectors, QEMUIOVector *qiov)
+{
+    return -ENOTSUP;
+}
+
+
+static void vhdx_close(BlockDriverState *bs)
+{
+    BDRVVHDXState *s = bs->opaque;
+    qemu_vfree(s->headers[0]);
+    qemu_vfree(s->headers[1]);
+    qemu_vfree(s->bat);
+    qemu_vfree(s->parent_entries);
+}
+
+static BlockDriver bdrv_vhdx = {
+    .format_name            = "vhdx",
+    .instance_size          = sizeof(BDRVVHDXState),
+    .bdrv_probe             = vhdx_probe,
+    .bdrv_open              = vhdx_open,
+    .bdrv_close             = vhdx_close,
+    .bdrv_reopen_prepare    = vhdx_reopen_prepare,
+    .bdrv_co_readv          = vhdx_co_readv,
+    .bdrv_co_writev         = vhdx_co_writev,
+};
+
+static void bdrv_vhdx_init(void)
+{
+    bdrv_register(&bdrv_vhdx);
+}
+
+block_init(bdrv_vhdx_init);
diff --git a/block/vhdx.h b/block/vhdx.h
index fcddd37..c3b64c6 100644
--- a/block/vhdx.h
+++ b/block/vhdx.h
@@ -308,4 +308,18 @@ typedef struct QEMU_PACKED VHDXParentLocatorEntry {
 
 /* ----- END VHDX SPECIFICATION STRUCTURES ---- */
 
+
+uint32_t vhdx_checksum_calc(uint32_t crc, uint8_t *buf, size_t size,
+                            int crc_offset);
+
+bool vhdx_checksum_is_valid(uint8_t *buf, size_t size, int crc_offset);
+
+
+static void leguid_to_cpus(MSGUID *guid)
+{
+    le32_to_cpus(&guid->data1);
+    le16_to_cpus(&guid->data2);
+    le16_to_cpus(&guid->data3);
+}
+
 #endif
commit 203cdba3bc6fb6022dbece90483fe03ed33bcffb
Author: Jeff Cody <jcody at redhat.com>
Date:   Mon Apr 29 14:48:17 2013 -0400

    block: vhdx header for the QEMU support of VHDX images
    
    This is based on Microsoft's VHDX specification:
        "VHDX Format Specification v0.95", published 4/12/2012
        https://www.microsoft.com/en-us/download/details.aspx?id=29681
    
    These structures define the various header, metadata, and other
    block structures defined in the VHDX specification.
    
    Signed-off-by: Jeff Cody <jcody at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/vhdx.h b/block/vhdx.h
new file mode 100644
index 0000000..fcddd37
--- /dev/null
+++ b/block/vhdx.h
@@ -0,0 +1,311 @@
+/*
+ * Block driver for Hyper-V VHDX Images
+ *
+ * Copyright (c) 2013 Red Hat, Inc.,
+ *
+ * Authors:
+ *  Jeff Cody <jcody at redhat.com>
+ *
+ *  This is based on the "VHDX Format Specification v0.95", published 4/12/2012
+ *  by Microsoft:
+ *      https://www.microsoft.com/en-us/download/details.aspx?id=29681
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#ifndef BLOCK_VHDX_H
+#define BLOCK_VHDX_H
+
+/* Structures and fields present in the VHDX file */
+
+/* The header section has the following blocks,
+ * each block is 64KB:
+ *
+ * _____________________________________________________________________________
+ * | File Id. |   Header 1    | Header 2   | Region Table |  Reserved (768KB)  |
+ * |----------|---------------|------------|--------------|--------------------|
+ * |          |               |            |              |                    |
+ * 0.........64KB...........128KB........192KB..........256KB................1MB
+ */
+
+#define VHDX_HEADER_BLOCK_SIZE      (64*1024)
+
+#define VHDX_FILE_ID_OFFSET         0
+#define VHDX_HEADER1_OFFSET         (VHDX_HEADER_BLOCK_SIZE*1)
+#define VHDX_HEADER2_OFFSET         (VHDX_HEADER_BLOCK_SIZE*2)
+#define VHDX_REGION_TABLE_OFFSET    (VHDX_HEADER_BLOCK_SIZE*3)
+
+
+/*
+ * A note on the use of MS-GUID fields.  For more details on the GUID,
+ * please see: https://en.wikipedia.org/wiki/Globally_unique_identifier.
+ *
+ * The VHDX specification only states that these are MS GUIDs, and which
+ * bytes are data1-data4. It makes no mention of what algorithm should be used
+ * to generate the GUID, nor what standard.  However, looking at the specified
+ * known GUID fields, it appears the GUIDs are:
+ *  Standard/DCE GUID type  (noted by 10b in the MSB of byte 0 of .data4)
+ *  Random algorithm        (noted by 0x4XXX for .data3)
+ */
+
+/* ---- HEADER SECTION STRUCTURES ---- */
+
+/* These structures are ones that are defined in the VHDX specification
+ * document */
+
+typedef struct VHDXFileIdentifier {
+    uint64_t    signature;              /* "vhdxfile" in ASCII */
+    uint16_t    creator[256];           /* optional; utf-16 string to identify
+                                           the vhdx file creator.  Diagnotistic
+                                           only */
+} VHDXFileIdentifier;
+
+
+/* the guid is a 16 byte unique ID - the definition for this used by
+ * Microsoft is not just 16 bytes though - it is a structure that is defined,
+ * so we need to follow it here so that endianness does not trip us up */
+
+typedef struct MSGUID {
+    uint32_t  data1;
+    uint16_t  data2;
+    uint16_t  data3;
+    uint8_t   data4[8];
+} MSGUID;
+
+#define guid_eq(a, b) \
+    (memcmp(&(a), &(b), sizeof(MSGUID)) == 0)
+
+#define VHDX_HEADER_SIZE (4*1024)   /* although the vhdx_header struct in disk
+                                       is only 582 bytes, for purposes of crc
+                                       the header is the first 4KB of the 64KB
+                                       block */
+
+/* The full header is 4KB, although the actual header data is much smaller.
+ * But for the checksum calculation, it is over the entire 4KB structure,
+ * not just the defined portion of it */
+typedef struct QEMU_PACKED VHDXHeader {
+    uint32_t    signature;              /* "head" in ASCII */
+    uint32_t    checksum;               /* CRC-32C hash of the whole header */
+    uint64_t    sequence_number;        /* Seq number of this header.  Each
+                                           VHDX file has 2 of these headers,
+                                           and only the header with the highest
+                                           sequence number is valid */
+    MSGUID      file_write_guid;       /* 128 bit unique identifier. Must be
+                                           updated to new, unique value before
+                                           the first modification is made to
+                                           file */
+    MSGUID      data_write_guid;        /* 128 bit unique identifier. Must be
+                                           updated to new, unique value before
+                                           the first modification is made to
+                                           visible data.   Visbile data is
+                                           defined as:
+                                                    - system & user metadata
+                                                    - raw block data
+                                                    - disk size
+                                                    - any change that will
+                                                      cause the virtual disk
+                                                      sector read to differ
+
+                                           This does not need to change if
+                                           blocks are re-arranged */
+    MSGUID      log_guid;               /* 128 bit unique identifier. If zero,
+                                           there is no valid log. If non-zero,
+                                           log entries with this guid are
+                                           valid. */
+    uint16_t    log_version;            /* version of the log format. Mustn't be
+                                           zero, unless log_guid is also zero */
+    uint16_t    version;                /* version of th evhdx file.  Currently,
+                                           only supported version is "1" */
+    uint32_t    log_length;             /* length of the log.  Must be multiple
+                                           of 1MB */
+    uint64_t    log_offset;             /* byte offset in the file of the log.
+                                           Must also be a multiple of 1MB */
+} VHDXHeader;
+
+/* Header for the region table block */
+typedef struct QEMU_PACKED VHDXRegionTableHeader {
+    uint32_t    signature;              /* "regi" in ASCII */
+    uint32_t    checksum;               /* CRC-32C hash of the 64KB table */
+    uint32_t    entry_count;            /* number of valid entries */
+    uint32_t    reserved;
+} VHDXRegionTableHeader;
+
+/* Individual region table entry.  There may be a maximum of 2047 of these
+ *
+ *  There are two known region table properties.  Both are required.
+ *  BAT (block allocation table):  2DC27766F62342009D64115E9BFD4A08
+ *  Metadata:                      8B7CA20647904B9AB8FE575F050F886E
+ */
+#define VHDX_REGION_ENTRY_REQUIRED  0x01    /* if set, parser must understand
+                                               this entry in order to open
+                                               file */
+typedef struct QEMU_PACKED VHDXRegionTableEntry {
+    MSGUID      guid;                   /* 128-bit unique identifier */
+    uint64_t    file_offset;            /* offset of the object in the file.
+                                           Must be multiple of 1MB */
+    uint32_t    length;                 /* length, in bytes, of the object */
+    uint32_t    data_bits;
+} VHDXRegionTableEntry;
+
+
+/* ---- LOG ENTRY STRUCTURES ---- */
+#define VHDX_LOG_HDR_SIZE 64
+typedef struct QEMU_PACKED VHDXLogEntryHeader {
+    uint32_t    signature;              /* "loge" in ASCII */
+    uint32_t    checksum;               /* CRC-32C hash of the 64KB table */
+    uint32_t    entry_length;           /* length in bytes, multiple of 1MB */
+    uint32_t    tail;                   /* byte offset of first log entry of a
+                                           seq, where this entry is the last
+                                           entry */
+    uint64_t    sequence_number;        /* incremented with each log entry.
+                                           May not be zero. */
+    uint32_t    descriptor_count;       /* number of descriptors in this log
+                                           entry, must be >= 0 */
+    uint32_t    reserved;
+    MSGUID      log_guid;               /* value of the log_guid from
+                                           vhdx_header.  If not found in
+                                           vhdx_header, it is invalid */
+    uint64_t    flushed_file_offset;    /* see spec for full details - this
+                                           sould be vhdx file size in bytes */
+    uint64_t    last_file_offset;       /* size in bytes that all allocated
+                                           file structures fit into */
+} VHDXLogEntryHeader;
+
+#define VHDX_LOG_DESC_SIZE 32
+
+typedef struct QEMU_PACKED VHDXLogDescriptor {
+    uint32_t    signature;              /* "zero" or "desc" in ASCII */
+    union  {
+        uint32_t    reserved;           /* zero desc */
+        uint32_t    trailing_bytes;     /* data desc: bytes 4092-4096 of the
+                                           data sector */
+    };
+    union {
+        uint64_t    zero_length;        /* zero desc: length of the section to
+                                           zero */
+        uint64_t    leading_bytes;      /* data desc: bytes 0-7 of the data
+                                           sector */
+    };
+    uint64_t    file_offset;            /* file offset to write zeros - multiple
+                                           of 4kB */
+    uint64_t    sequence_number;        /* must match same field in
+                                           vhdx_log_entry_header */
+} VHDXLogDescriptor;
+
+typedef struct QEMU_PACKED VHDXLogDataSector {
+    uint32_t    data_signature;         /* "data" in ASCII */
+    uint32_t    sequence_high;          /* 4 MSB of 8 byte sequence_number */
+    uint8_t     data[4084];             /* raw data, bytes 8-4091 (inclusive).
+                                           see the data descriptor field for the
+                                           other mising bytes */
+    uint32_t    sequence_low;           /* 4 LSB of 8 byte sequence_number */
+} VHDXLogDataSector;
+
+
+
+/* block states - different state values depending on whether it is a
+ * payload block, or a sector block. */
+
+#define PAYLOAD_BLOCK_NOT_PRESENT       0
+#define PAYLOAD_BLOCK_UNDEFINED         1
+#define PAYLOAD_BLOCK_ZERO              2
+#define PAYLOAD_BLOCK_UNMAPPED          5
+#define PAYLOAD_BLOCK_FULL_PRESENT      6
+#define PAYLOAD_BLOCK_PARTIALLY_PRESENT 7
+
+#define SB_BLOCK_NOT_PRESENT    0
+#define SB_BLOCK_PRESENT        6
+
+/* per the spec */
+#define VHDX_MAX_SECTORS_PER_BLOCK  (1<<23)
+
+/* upper 44 bits are the file offset in 1MB units lower 3 bits are the state
+   other bits are reserved */
+#define VHDX_BAT_STATE_BIT_MASK 0x07
+#define VHDX_BAT_FILE_OFF_BITS (64-44)
+typedef uint64_t VHDXBatEntry;
+
+/* ---- METADATA REGION STRUCTURES ---- */
+
+#define VHDX_METADATA_ENTRY_SIZE 32
+#define VHDX_METADATA_MAX_ENTRIES 2047  /* not including the header */
+#define VHDX_METADATA_TABLE_MAX_SIZE \
+    (VHDX_METADATA_ENTRY_SIZE * (VHDX_METADATA_MAX_ENTRIES+1))
+typedef struct QEMU_PACKED VHDXMetadataTableHeader {
+    uint64_t    signature;              /* "metadata" in ASCII */
+    uint16_t    reserved;
+    uint16_t    entry_count;            /* number table entries. <= 2047 */
+    uint32_t    reserved2[5];
+} VHDXMetadataTableHeader;
+
+#define VHDX_META_FLAGS_IS_USER         0x01    /* max 1024 entries */
+#define VHDX_META_FLAGS_IS_VIRTUAL_DISK 0x02    /* virtual disk metadata if set,
+                                                   otherwise file metdata */
+#define VHDX_META_FLAGS_IS_REQUIRED     0x04    /* parse must understand this
+                                                   entry to open the file */
+typedef struct QEMU_PACKED VHDXMetadataTableEntry {
+    MSGUID      item_id;                /* 128-bit identifier for metadata */
+    uint32_t    offset;                 /* byte offset of the metadata.  At
+                                           least 64kB.  Relative to start of
+                                           metadata region */
+                                        /* note: if length = 0, so is offset */
+    uint32_t    length;                 /* length of metadata. <= 1MB. */
+    uint32_t    data_bits;      /* least-significant 3 bits are flags, the
+                                   rest are reserved (see above) */
+    uint32_t    reserved2;
+} VHDXMetadataTableEntry;
+
+#define VHDX_PARAMS_LEAVE_BLOCKS_ALLOCED 0x01   /* Do not change any blocks to
+                                                   be BLOCK_NOT_PRESENT.
+                                                   If set indicates a fixed
+                                                   size VHDX file */
+#define VHDX_PARAMS_HAS_PARENT           0x02    /* has parent / backing file */
+typedef struct QEMU_PACKED VHDXFileParameters {
+    uint32_t    block_size;             /* size of each payload block, always
+                                           power of 2, <= 256MB and >= 1MB. */
+    uint32_t data_bits;     /* least-significant 2 bits are flags, the rest
+                               are reserved (see above) */
+} VHDXFileParameters;
+
+typedef struct QEMU_PACKED VHDXVirtualDiskSize {
+    uint64_t    virtual_disk_size;      /* Size of the virtual disk, in bytes.
+                                           Must be multiple of the sector size,
+                                           max of 64TB */
+} VHDXVirtualDiskSize;
+
+typedef struct QEMU_PACKED VHDXPage83Data {
+    MSGUID      page_83_data[16];       /* unique id for scsi devices that
+                                           support page 0x83 */
+} VHDXPage83Data;
+
+typedef struct QEMU_PACKED VHDXVirtualDiskLogicalSectorSize {
+    uint32_t    logical_sector_size;    /* virtual disk sector size (in bytes).
+                                           Can only be 512 or 4096 bytes */
+} VHDXVirtualDiskLogicalSectorSize;
+
+typedef struct QEMU_PACKED VHDXVirtualDiskPhysicalSectorSize {
+    uint32_t    physical_sector_size;   /* physical sector size (in bytes).
+                                           Can only be 512 or 4096 bytes */
+} VHDXVirtualDiskPhysicalSectorSize;
+
+typedef struct QEMU_PACKED VHDXParentLocatorHeader {
+    MSGUID      locator_type[16];       /* type of the parent virtual disk. */
+    uint16_t    reserved;
+    uint16_t    key_value_count;        /* number of key/value pairs for this
+                                           locator */
+} VHDXParentLocatorHeader;
+
+/* key and value strings are UNICODE strings, UTF-16 LE encoding, no NULs */
+typedef struct QEMU_PACKED VHDXParentLocatorEntry {
+    uint32_t    key_offset;             /* offset in metadata for key, > 0 */
+    uint32_t    value_offset;           /* offset in metadata for value, >0 */
+    uint16_t    key_length;             /* length of entry key, > 0 */
+    uint16_t    value_length;           /* length of entry value, > 0 */
+} VHDXParentLocatorEntry;
+
+
+/* ----- END VHDX SPECIFICATION STRUCTURES ---- */
+
+#endif
commit 8e1b02b8ef2eefcb2ff3855531d7bc2ea71e1fb4
Author: Jeff Cody <jcody at redhat.com>
Date:   Mon Apr 29 14:48:16 2013 -0400

    qemu: add castagnoli crc32c checksum algorithm
    
    This adds the Castagnoli CRC32C algorithm, using the 0x11EDC6F41
    polynomial.
    
    This is extracted from the linux kernel cryptographic crc32.c module.
    
    The algorithm is based on:
    
    Castagnoli93: Guy Castagnoli and Stefan Braeuer and Martin Herrman
                 "Optimization of Cyclic Redundancy-Check Codes with 24
                  and 32 Parity Bits", IEEE Transactions on Communication,
                  Volume 41, Number 6, June 1993
    
    Signed-off-by: Jeff Cody <jcody at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/include/qemu/crc32c.h b/include/qemu/crc32c.h
new file mode 100644
index 0000000..56d1c3b
--- /dev/null
+++ b/include/qemu/crc32c.h
@@ -0,0 +1,35 @@
+/*
+ *  Castagnoli CRC32C Checksum Algorithm
+ *
+ *  Polynomial: 0x11EDC6F41
+ *
+ *  Castagnoli93: Guy Castagnoli and Stefan Braeuer and Martin Herrman
+ *               "Optimization of Cyclic Redundancy-Check Codes with 24
+ *                 and 32 Parity Bits",IEEE Transactions on Communication,
+ *                Volume 41, Number 6, June 1993
+ *
+ *  Copyright (c) 2013 Red Hat, Inc.,
+ *
+ *  Authors:
+ *   Jeff Cody <jcody at redhat.com>
+ *
+ *  Based on the Linux kernel cryptographic crc32c module,
+ *
+ *  Copyright (c) 2004 Cisco Systems, Inc.
+ *  Copyright (c) 2008 Herbert Xu <herbert at gondor.apana.org.au>
+ *
+ * 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.
+ *
+ */
+
+#ifndef QEMU_CRC32_H
+#define QEMU_CRC32_H
+
+#include "qemu-common.h"
+
+uint32_t crc32c(uint32_t crc, const uint8_t *data, unsigned int length);
+
+#endif
diff --git a/util/Makefile.objs b/util/Makefile.objs
index c5652f5..4a1bd4e 100644
--- a/util/Makefile.objs
+++ b/util/Makefile.objs
@@ -10,3 +10,4 @@ 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
+util-obj-y += crc32c.o
diff --git a/util/crc32c.c b/util/crc32c.c
new file mode 100644
index 0000000..8866327
--- /dev/null
+++ b/util/crc32c.c
@@ -0,0 +1,115 @@
+/*
+ *  Castagnoli CRC32C Checksum Algorithm
+ *
+ *  Polynomial: 0x11EDC6F41
+ *
+ *  Castagnoli93: Guy Castagnoli and Stefan Braeuer and Martin Herrman
+ *               "Optimization of Cyclic Redundancy-Check Codes with 24
+ *                 and 32 Parity Bits",IEEE Transactions on Communication,
+ *                Volume 41, Number 6, June 1993
+ *
+ *  Copyright (c) 2013 Red Hat, Inc.,
+ *
+ *  Authors:
+ *   Jeff Cody <jcody at redhat.com>
+ *
+ *  Based on the Linux kernel cryptographic crc32c module,
+ *
+ *  Copyright (c) 2004 Cisco Systems, Inc.
+ *  Copyright (c) 2008 Herbert Xu <herbert at gondor.apana.org.au>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+#include "qemu-common.h"
+#include "qemu/crc32c.h"
+
+/*
+ * This is the CRC-32C table
+ * Generated with:
+ * width = 32 bits
+ * poly = 0x1EDC6F41
+ * reflect input bytes = true
+ * reflect output bytes = true
+ */
+
+static const uint32_t crc32c_table[256] = {
+    0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
+    0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
+    0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
+    0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
+    0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
+    0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
+    0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
+    0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
+    0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
+    0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
+    0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
+    0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
+    0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
+    0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
+    0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
+    0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
+    0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
+    0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
+    0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
+    0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
+    0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
+    0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
+    0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
+    0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
+    0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
+    0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
+    0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
+    0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
+    0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
+    0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
+    0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
+    0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
+    0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
+    0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
+    0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
+    0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
+    0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
+    0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
+    0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
+    0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
+    0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
+    0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
+    0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
+    0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
+    0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
+    0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
+    0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
+    0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
+    0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
+    0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
+    0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
+    0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
+    0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
+    0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
+    0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
+    0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
+    0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
+    0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
+    0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
+    0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
+    0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
+    0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
+    0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
+    0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
+};
+
+
+uint32_t crc32c(uint32_t crc, const uint8_t *data, unsigned int length)
+{
+    while (length--) {
+        crc = crc32c_table[(crc ^ *data++) & 0xFFL] ^ (crc >> 8);
+    }
+    return crc^0xffffffff;
+}
+
commit 8ca27ce2e1150486ea2db4116a03706b28294f16
Merge: 0db4c32 e7bdf65
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu May 2 10:57:01 2013 -0500

    Merge remote-tracking branch 'afaerber/qom-cpu' into staging
    
    # By Igor Mammedov (21) and others
    # Via Andreas Färber
    * afaerber/qom-cpu: (29 commits)
      Drop redundant resume_all_vcpus() from main()
      cpus: Fix pausing TCG CPUs while in vCPU thread
      target-i386: Replace cpuid_*features fields with a feature word array
      target-i386: Break CPUID feature definition lines
      target-i386/kvm.c: Code formatting changes
      target-i386: Group together level, xlevel, xlevel2 fields
      pc: Implement QEMUMachine::hot_add_cpu hook
      QMP: Add cpu-add command
      Add hot_add_cpu hook to QEMUMachine
      target-i386: Move APIC to ICC bus
      target-i386: Attach ICC bus to CPU on its creation
      target-i386: Introduce ICC bus/device/bridge
      cpu: Move cpu_write_elfXX_note() functions to CPUState
      kvmvapic: Make dependency on sysbus.h explicit
      target-i386: Replace MSI_SPACE_SIZE with APIC_SPACE_SIZE
      target-i386: Do not allow to set apic-id once CPU is realized
      target-i386: Introduce apic-id CPU property
      target-i386: Introduce feat2prop() for CPU properties
      acpi_piix4: Add infrastructure to send CPU hot-plug GPE to guest
      cpu: Add helper cpu_exists(), to check if CPU with specified id exists
      ...

commit 0db4c324a8c6f2b1b8a118146f9b0fc8c4210719
Merge: e9016ee 6e860b5
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu May 2 10:56:07 2013 -0500

    Merge remote-tracking branch 'mjt/trivial-patches' into staging
    
    # By Andreas Färber (1) and others
    # Via Michael Tokarev
    * mjt/trivial-patches:
      pvscsi: fix compilation on 32 bit hosts
      Trivial grammar and spelling fixes
      configure: Pick up libseccomp include path

commit e7bdf659c16e1cefd61f53648503d8c060668d6b
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Aug 20 20:11:36 2012 +0200

    Drop redundant resume_all_vcpus() from main()
    
    VCPUs are either resumed directly via vm_start(), after the incoming
    migration is done, or when a continue command is issued. We don't need
    the explicit resume before entering main_loop().
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/vl.c b/vl.c
index 41c367d..6e6225f 100644
--- a/vl.c
+++ b/vl.c
@@ -4415,7 +4415,6 @@ int main(int argc, char **argv, char **envp)
 
     os_setup_post();
 
-    resume_all_vcpus();
     main_loop();
     bdrv_close_all();
     pause_all_vcpus();
commit 1085819368e8693f08307e72f0082d759f67ef03
Author: Andreas Färber <afaerber at suse.de>
Date:   Thu May 2 11:22:05 2013 +0200

    cpus: Fix pausing TCG CPUs while in vCPU thread
    
    Due to a preceding while loop, no CPU would've been put into stopped
    state. Reinitialize the variable.
    This fixes commit d798e97456658ea7605303b7c69b04ec7df95c10 (Allow to use
    pause_all_vcpus from VCPU context) for non-KVM case.
    
    While at it, change a 0 to false, amending commit
    4fdeee7cd4c8f90ef765537b9346a195d9483ab5 (cpu: Move stop field to
    CPUState).
    
    Reviewed-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/cpus.c b/cpus.c
index a2d92c7..c232265 100644
--- a/cpus.c
+++ b/cpus.c
@@ -974,9 +974,10 @@ void pause_all_vcpus(void)
     if (qemu_in_vcpu_thread()) {
         cpu_stop_current();
         if (!kvm_enabled()) {
+            penv = first_cpu;
             while (penv) {
                 CPUState *pcpu = ENV_GET_CPU(penv);
-                pcpu->stop = 0;
+                pcpu->stop = false;
                 pcpu->stopped = true;
                 penv = penv->next_cpu;
             }
commit 0514ef2fbb3882afe410ba7800c79fd0ef5dbf00
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Mon Apr 22 16:00:15 2013 -0300

    target-i386: Replace cpuid_*features fields with a feature word array
    
    This replaces the feature-bit fields on both X86CPU and x86_def_t
    structs with an array.
    
    With this, we will be able to simplify code that simply does the same
    operation on all feature words (e.g. kvm_check_features_against_host(),
    filter_features_for_kvm(), add_flagname_to_bitmaps(), CPU feature-bit
    property lookup/registration, and the proposed "feature-words" property)
    
    The following field replacements were made on X86CPU and x86_def_t:
    
      (cpuid_)features         -> features[FEAT_1_EDX]
      (cpuid_)ext_features     -> features[FEAT_1_ECX]
      (cpuid_)ext2_features    -> features[FEAT_8000_0001_EDX]
      (cpuid_)ext3_features    -> features[FEAT_8000_0001_ECX]
      (cpuid_)ext4_features    -> features[FEAT_C000_0001_EDX]
      (cpuid_)kvm_features     -> features[FEAT_KVM]
      (cpuid_)svm_features     -> features[FEAT_SVM]
      (cpuid_)7_0_ebx_features -> features[FEAT_7_0_EBX]
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Reviewed-by: Igor Mammedov <imammedo at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c
index a6cd3ab..5e20510 100644
--- a/bsd-user/elfload.c
+++ b/bsd-user/elfload.c
@@ -110,7 +110,7 @@ static const char *get_elf_platform(void)
 
 static uint32_t get_elf_hwcap(void)
 {
-  return thread_env->cpuid_features;
+    return thread_env->features[FEAT_1_EDX];
 }
 
 #ifdef TARGET_X86_64
diff --git a/bsd-user/main.c b/bsd-user/main.c
index cc84981..0da3ab9 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -1004,13 +1004,13 @@ int main(int argc, char **argv)
 
     env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
     env->hflags |= HF_PE_MASK;
-    if (env->cpuid_features & CPUID_SSE) {
+    if (env->features[FEAT_1_EDX] & CPUID_SSE) {
         env->cr[4] |= CR4_OSFXSR_MASK;
         env->hflags |= HF_OSFXSR_MASK;
     }
 #ifndef TARGET_ABI32
     /* enable 64 bit mode if possible */
-    if (!(env->cpuid_ext2_features & CPUID_EXT2_LM)) {
+    if (!(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM)) {
         fprintf(stderr, "The selected x86 CPU does not support 64 bit mode\n");
         exit(1);
     }
diff --git a/hw/i386/kvm/clock.c b/hw/i386/kvm/clock.c
index fa40e28..87d4d0f 100644
--- a/hw/i386/kvm/clock.c
+++ b/hw/i386/kvm/clock.c
@@ -129,7 +129,7 @@ static const TypeInfo kvmclock_info = {
 void kvmclock_create(void)
 {
     if (kvm_enabled() &&
-        first_cpu->cpuid_kvm_features & ((1ULL << KVM_FEATURE_CLOCKSOURCE) |
+        first_cpu->features[FEAT_KVM] & ((1ULL << KVM_FEATURE_CLOCKSOURCE) |
                                          (1ULL << KVM_FEATURE_CLOCKSOURCE2))) {
         sysbus_create_simple("kvmclock", -1, NULL);
     }
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 979b57c..ddef23e 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -137,7 +137,7 @@ static const char *get_elf_platform(void)
 
 static uint32_t get_elf_hwcap(void)
 {
-    return thread_env->cpuid_features;
+    return thread_env->features[FEAT_1_EDX];
 }
 
 #ifdef TARGET_X86_64
diff --git a/linux-user/main.c b/linux-user/main.c
index 4e92a0b..b97b8cf 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3764,13 +3764,13 @@ int main(int argc, char **argv, char **envp)
 
     env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
     env->hflags |= HF_PE_MASK;
-    if (env->cpuid_features & CPUID_SSE) {
+    if (env->features[FEAT_1_EDX] & CPUID_SSE) {
         env->cr[4] |= CR4_OSFXSR_MASK;
         env->hflags |= HF_OSFXSR_MASK;
     }
 #ifndef TARGET_ABI32
     /* enable 64 bit mode if possible */
-    if (!(env->cpuid_ext2_features & CPUID_EXT2_LM)) {
+    if (!(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM)) {
         fprintf(stderr, "The selected x86 CPU does not support 64 bit mode\n");
         exit(1);
     }
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 424e7c2..9f2adad 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -357,13 +357,8 @@ typedef struct x86_def_t {
     int family;
     int model;
     int stepping;
-    uint32_t features, ext_features, ext2_features, ext3_features;
-    uint32_t kvm_features, svm_features;
+    FeatureWordArray features;
     char model_id[48];
-    /* Store the results of Centaur's CPUID instructions */
-    uint32_t ext4_features;
-    /* The feature bits on CPUID[EAX=7,ECX=0].EBX */
-    uint32_t cpuid_7_0_ebx_features;
 } x86_def_t;
 
 #define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
@@ -424,16 +419,16 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 6,
         .model = 2,
         .stepping = 3,
-        .features =
+        .features[FEAT_1_EDX] =
             PPRO_FEATURES |
             CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
             CPUID_PSE36,
-        .ext_features =
+        .features[FEAT_1_ECX] =
             CPUID_EXT_SSE3 | CPUID_EXT_CX16 | CPUID_EXT_POPCNT,
-        .ext2_features =
+        .features[FEAT_8000_0001_EDX] =
             (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
             CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
-        .ext3_features =
+        .features[FEAT_8000_0001_ECX] =
             CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
             CPUID_EXT3_ABM | CPUID_EXT3_SSE4A,
         .xlevel = 0x8000000A,
@@ -445,14 +440,14 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 16,
         .model = 2,
         .stepping = 3,
-        .features =
+        .features[FEAT_1_EDX] =
             PPRO_FEATURES |
             CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
             CPUID_PSE36 | CPUID_VME | CPUID_HT,
-        .ext_features =
+        .features[FEAT_1_ECX] =
             CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_CX16 |
             CPUID_EXT_POPCNT,
-        .ext2_features =
+        .features[FEAT_8000_0001_EDX] =
             (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
             CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX |
             CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_MMXEXT |
@@ -461,10 +456,10 @@ static x86_def_t builtin_x86_defs[] = {
                     CPUID_EXT3_CR8LEG,
                     CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH,
                     CPUID_EXT3_OSVW, CPUID_EXT3_IBS */
-        .ext3_features =
+        .features[FEAT_8000_0001_ECX] =
             CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
             CPUID_EXT3_ABM | CPUID_EXT3_SSE4A,
-        .svm_features =
+        .features[FEAT_SVM] =
             CPUID_SVM_NPT | CPUID_SVM_LBRV,
         .xlevel = 0x8000001A,
         .model_id = "AMD Phenom(tm) 9550 Quad-Core Processor"
@@ -476,18 +471,18 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 6,
         .model = 15,
         .stepping = 11,
-        .features =
+        .features[FEAT_1_EDX] =
             PPRO_FEATURES |
             CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
             CPUID_PSE36 | CPUID_VME | CPUID_DTS | CPUID_ACPI | CPUID_SS |
             CPUID_HT | CPUID_TM | CPUID_PBE,
-        .ext_features =
+        .features[FEAT_1_ECX] =
             CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 |
             CPUID_EXT_DTES64 | CPUID_EXT_DSCPL | CPUID_EXT_VMX | CPUID_EXT_EST |
             CPUID_EXT_TM2 | CPUID_EXT_CX16 | CPUID_EXT_XTPR | CPUID_EXT_PDCM,
-        .ext2_features =
+        .features[FEAT_8000_0001_EDX] =
             CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
-        .ext3_features =
+        .features[FEAT_8000_0001_ECX] =
             CPUID_EXT3_LAHF_LM,
         .xlevel = 0x80000008,
         .model_id = "Intel(R) Core(TM)2 Duo CPU     T7700  @ 2.40GHz",
@@ -500,22 +495,22 @@ static x86_def_t builtin_x86_defs[] = {
         .model = 6,
         .stepping = 1,
         /* Missing: CPUID_VME, CPUID_HT */
-        .features =
+        .features[FEAT_1_EDX] =
             PPRO_FEATURES |
             CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
             CPUID_PSE36,
         /* Missing: CPUID_EXT_POPCNT, CPUID_EXT_MONITOR */
-        .ext_features =
+        .features[FEAT_1_ECX] =
             CPUID_EXT_SSE3 | CPUID_EXT_CX16,
         /* Missing: CPUID_EXT2_PDPE1GB, CPUID_EXT2_RDTSCP */
-        .ext2_features =
+        .features[FEAT_8000_0001_EDX] =
             (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
             CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
         /* Missing: CPUID_EXT3_LAHF_LM, CPUID_EXT3_CMP_LEG, CPUID_EXT3_EXTAPIC,
                     CPUID_EXT3_CR8LEG, CPUID_EXT3_ABM, CPUID_EXT3_SSE4A,
                     CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH,
                     CPUID_EXT3_OSVW, CPUID_EXT3_IBS, CPUID_EXT3_SVM */
-        .ext3_features =
+        .features[FEAT_8000_0001_ECX] =
             0,
         .xlevel = 0x80000008,
         .model_id = "Common KVM processor"
@@ -527,9 +522,9 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 6,
         .model = 3,
         .stepping = 3,
-        .features =
+        .features[FEAT_1_EDX] =
             PPRO_FEATURES,
-        .ext_features =
+        .features[FEAT_1_ECX] =
             CPUID_EXT_SSE3 | CPUID_EXT_POPCNT,
         .xlevel = 0x80000004,
     },
@@ -540,14 +535,14 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 15,
         .model = 6,
         .stepping = 1,
-        .features =
+        .features[FEAT_1_EDX] =
             PPRO_FEATURES |
             CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_PSE36,
-        .ext_features =
+        .features[FEAT_1_ECX] =
             CPUID_EXT_SSE3,
-        .ext2_features =
+        .features[FEAT_8000_0001_EDX] =
             PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES,
-        .ext3_features =
+        .features[FEAT_8000_0001_ECX] =
             0,
         .xlevel = 0x80000008,
         .model_id = "Common 32-bit KVM processor"
@@ -559,14 +554,14 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 6,
         .model = 14,
         .stepping = 8,
-        .features =
+        .features[FEAT_1_EDX] =
             PPRO_FEATURES | CPUID_VME |
             CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_DTS | CPUID_ACPI |
             CPUID_SS | CPUID_HT | CPUID_TM | CPUID_PBE,
-        .ext_features =
+        .features[FEAT_1_ECX] =
             CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_VMX |
             CPUID_EXT_EST | CPUID_EXT_TM2 | CPUID_EXT_XTPR | CPUID_EXT_PDCM,
-        .ext2_features =
+        .features[FEAT_8000_0001_EDX] =
             CPUID_EXT2_NX,
         .xlevel = 0x80000008,
         .model_id = "Genuine Intel(R) CPU           T2600  @ 2.16GHz",
@@ -578,7 +573,7 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 4,
         .model = 0,
         .stepping = 0,
-        .features =
+        .features[FEAT_1_EDX] =
             I486_FEATURES,
         .xlevel = 0,
     },
@@ -589,7 +584,7 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 5,
         .model = 4,
         .stepping = 3,
-        .features =
+        .features[FEAT_1_EDX] =
             PENTIUM_FEATURES,
         .xlevel = 0,
     },
@@ -600,7 +595,7 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 6,
         .model = 5,
         .stepping = 2,
-        .features =
+        .features[FEAT_1_EDX] =
             PENTIUM2_FEATURES,
         .xlevel = 0,
     },
@@ -611,7 +606,7 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 6,
         .model = 7,
         .stepping = 3,
-        .features =
+        .features[FEAT_1_EDX] =
             PENTIUM3_FEATURES,
         .xlevel = 0,
     },
@@ -622,10 +617,10 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 6,
         .model = 2,
         .stepping = 3,
-        .features =
+        .features[FEAT_1_EDX] =
             PPRO_FEATURES | CPUID_PSE36 | CPUID_VME | CPUID_MTRR |
             CPUID_MCA,
-        .ext2_features =
+        .features[FEAT_8000_0001_EDX] =
             (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
             CPUID_EXT2_MMXEXT | CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT,
         .xlevel = 0x80000008,
@@ -638,18 +633,18 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 6,
         .model = 28,
         .stepping = 2,
-        .features =
+        .features[FEAT_1_EDX] =
             PPRO_FEATURES |
             CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_VME | CPUID_DTS |
             CPUID_ACPI | CPUID_SS | CPUID_HT | CPUID_TM | CPUID_PBE,
             /* Some CPUs got no CPUID_SEP */
-        .ext_features =
+        .features[FEAT_1_ECX] =
             CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 |
             CPUID_EXT_DSCPL | CPUID_EXT_EST | CPUID_EXT_TM2 | CPUID_EXT_XTPR,
-        .ext2_features =
+        .features[FEAT_8000_0001_EDX] =
             (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
             CPUID_EXT2_NX,
-        .ext3_features =
+        .features[FEAT_8000_0001_ECX] =
             CPUID_EXT3_LAHF_LM,
         .xlevel = 0x8000000A,
         .model_id = "Intel(R) Atom(TM) CPU N270   @ 1.60GHz",
@@ -661,17 +656,17 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 6,
         .model = 2,
         .stepping = 3,
-        .features =
+        .features[FEAT_1_EDX] =
             CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
              CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
              CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
              CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
              CPUID_DE | CPUID_FP87,
-        .ext_features =
+        .features[FEAT_1_ECX] =
             CPUID_EXT_SSSE3 | CPUID_EXT_SSE3,
-        .ext2_features =
+        .features[FEAT_8000_0001_EDX] =
             CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL,
-        .ext3_features =
+        .features[FEAT_8000_0001_ECX] =
             CPUID_EXT3_LAHF_LM,
         .xlevel = 0x8000000A,
         .model_id = "Intel Celeron_4x0 (Conroe/Merom Class Core 2)",
@@ -683,18 +678,18 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 6,
         .model = 2,
         .stepping = 3,
-        .features =
+        .features[FEAT_1_EDX] =
             CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
              CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
              CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
              CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
              CPUID_DE | CPUID_FP87,
-        .ext_features =
+        .features[FEAT_1_ECX] =
             CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 |
              CPUID_EXT_SSE3,
-        .ext2_features =
+        .features[FEAT_8000_0001_EDX] =
             CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL,
-        .ext3_features =
+        .features[FEAT_8000_0001_ECX] =
             CPUID_EXT3_LAHF_LM,
         .xlevel = 0x8000000A,
         .model_id = "Intel Core 2 Duo P9xxx (Penryn Class Core 2)",
@@ -706,18 +701,18 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 6,
         .model = 2,
         .stepping = 3,
-        .features =
+        .features[FEAT_1_EDX] =
             CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
              CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
              CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
              CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
              CPUID_DE | CPUID_FP87,
-        .ext_features =
+        .features[FEAT_1_ECX] =
             CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 |
              CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_SSE3,
-        .ext2_features =
+        .features[FEAT_8000_0001_EDX] =
             CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
-        .ext3_features =
+        .features[FEAT_8000_0001_ECX] =
             CPUID_EXT3_LAHF_LM,
         .xlevel = 0x8000000A,
         .model_id = "Intel Core i7 9xx (Nehalem Class Core i7)",
@@ -729,19 +724,19 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 6,
         .model = 44,
         .stepping = 1,
-        .features =
+        .features[FEAT_1_EDX] =
             CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
              CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
              CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
              CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
              CPUID_DE | CPUID_FP87,
-        .ext_features =
+        .features[FEAT_1_ECX] =
             CPUID_EXT_AES | CPUID_EXT_POPCNT | CPUID_EXT_SSE42 |
              CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 |
              CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3,
-        .ext2_features =
+        .features[FEAT_8000_0001_EDX] =
             CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
-        .ext3_features =
+        .features[FEAT_8000_0001_ECX] =
             CPUID_EXT3_LAHF_LM,
         .xlevel = 0x8000000A,
         .model_id = "Westmere E56xx/L56xx/X56xx (Nehalem-C)",
@@ -753,22 +748,22 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 6,
         .model = 42,
         .stepping = 1,
-        .features =
+        .features[FEAT_1_EDX] =
             CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
              CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
              CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
              CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
              CPUID_DE | CPUID_FP87,
-        .ext_features =
+        .features[FEAT_1_ECX] =
             CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
              CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_POPCNT |
              CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 |
              CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ |
              CPUID_EXT_SSE3,
-        .ext2_features =
+        .features[FEAT_8000_0001_EDX] =
             CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
              CPUID_EXT2_SYSCALL,
-        .ext3_features =
+        .features[FEAT_8000_0001_ECX] =
             CPUID_EXT3_LAHF_LM,
         .xlevel = 0x8000000A,
         .model_id = "Intel Xeon E312xx (Sandy Bridge)",
@@ -780,25 +775,25 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 6,
         .model = 60,
         .stepping = 1,
-        .features =
+        .features[FEAT_1_EDX] =
             CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
              CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
              CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
              CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
              CPUID_DE | CPUID_FP87,
-        .ext_features =
+        .features[FEAT_1_ECX] =
             CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
              CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 |
              CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 |
              CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 |
              CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE |
              CPUID_EXT_PCID,
-        .ext2_features =
+        .features[FEAT_8000_0001_EDX] =
             CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
              CPUID_EXT2_SYSCALL,
-        .ext3_features =
+        .features[FEAT_8000_0001_ECX] =
             CPUID_EXT3_LAHF_LM,
-        .cpuid_7_0_ebx_features =
+        .features[FEAT_7_0_EBX] =
             CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 |
             CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP |
             CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID |
@@ -813,15 +808,15 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 15,
         .model = 6,
         .stepping = 1,
-        .features =
+        .features[FEAT_1_EDX] =
             CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
              CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
              CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
              CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
              CPUID_DE | CPUID_FP87,
-        .ext_features =
+        .features[FEAT_1_ECX] =
             CPUID_EXT_SSE3,
-        .ext2_features =
+        .features[FEAT_8000_0001_EDX] =
             CPUID_EXT2_LM | CPUID_EXT2_FXSR | CPUID_EXT2_MMX |
              CPUID_EXT2_NX | CPUID_EXT2_PSE36 | CPUID_EXT2_PAT |
              CPUID_EXT2_CMOV | CPUID_EXT2_MCA | CPUID_EXT2_PGE |
@@ -838,15 +833,15 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 15,
         .model = 6,
         .stepping = 1,
-        .features =
+        .features[FEAT_1_EDX] =
             CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
              CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
              CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
              CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
              CPUID_DE | CPUID_FP87,
-        .ext_features =
+        .features[FEAT_1_ECX] =
             CPUID_EXT_CX16 | CPUID_EXT_SSE3,
-        .ext2_features =
+        .features[FEAT_8000_0001_EDX] =
             CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_FXSR |
              CPUID_EXT2_MMX | CPUID_EXT2_NX | CPUID_EXT2_PSE36 |
              CPUID_EXT2_PAT | CPUID_EXT2_CMOV | CPUID_EXT2_MCA |
@@ -854,7 +849,7 @@ static x86_def_t builtin_x86_defs[] = {
              CPUID_EXT2_APIC | CPUID_EXT2_CX8 | CPUID_EXT2_MCE |
              CPUID_EXT2_PAE | CPUID_EXT2_MSR | CPUID_EXT2_TSC | CPUID_EXT2_PSE |
              CPUID_EXT2_DE | CPUID_EXT2_FPU,
-        .ext3_features =
+        .features[FEAT_8000_0001_ECX] =
             CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM,
         .xlevel = 0x80000008,
         .model_id = "AMD Opteron 22xx (Gen 2 Class Opteron)",
@@ -866,16 +861,16 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 15,
         .model = 6,
         .stepping = 1,
-        .features =
+        .features[FEAT_1_EDX] =
             CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
              CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
              CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
              CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
              CPUID_DE | CPUID_FP87,
-        .ext_features =
+        .features[FEAT_1_ECX] =
             CPUID_EXT_POPCNT | CPUID_EXT_CX16 | CPUID_EXT_MONITOR |
              CPUID_EXT_SSE3,
-        .ext2_features =
+        .features[FEAT_8000_0001_EDX] =
             CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_FXSR |
              CPUID_EXT2_MMX | CPUID_EXT2_NX | CPUID_EXT2_PSE36 |
              CPUID_EXT2_PAT | CPUID_EXT2_CMOV | CPUID_EXT2_MCA |
@@ -883,7 +878,7 @@ static x86_def_t builtin_x86_defs[] = {
              CPUID_EXT2_APIC | CPUID_EXT2_CX8 | CPUID_EXT2_MCE |
              CPUID_EXT2_PAE | CPUID_EXT2_MSR | CPUID_EXT2_TSC | CPUID_EXT2_PSE |
              CPUID_EXT2_DE | CPUID_EXT2_FPU,
-        .ext3_features =
+        .features[FEAT_8000_0001_ECX] =
             CPUID_EXT3_MISALIGNSSE | CPUID_EXT3_SSE4A |
              CPUID_EXT3_ABM | CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM,
         .xlevel = 0x80000008,
@@ -896,18 +891,18 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 21,
         .model = 1,
         .stepping = 2,
-        .features =
+        .features[FEAT_1_EDX] =
             CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
              CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
              CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
              CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
              CPUID_DE | CPUID_FP87,
-        .ext_features =
+        .features[FEAT_1_ECX] =
             CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
              CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 |
              CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ |
              CPUID_EXT_SSE3,
-        .ext2_features =
+        .features[FEAT_8000_0001_EDX] =
             CPUID_EXT2_LM | CPUID_EXT2_RDTSCP |
              CPUID_EXT2_PDPE1GB | CPUID_EXT2_FXSR | CPUID_EXT2_MMX |
              CPUID_EXT2_NX | CPUID_EXT2_PSE36 | CPUID_EXT2_PAT |
@@ -915,7 +910,7 @@ static x86_def_t builtin_x86_defs[] = {
              CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL | CPUID_EXT2_APIC |
              CPUID_EXT2_CX8 | CPUID_EXT2_MCE | CPUID_EXT2_PAE | CPUID_EXT2_MSR |
              CPUID_EXT2_TSC | CPUID_EXT2_PSE | CPUID_EXT2_DE | CPUID_EXT2_FPU,
-        .ext3_features =
+        .features[FEAT_8000_0001_ECX] =
             CPUID_EXT3_FMA4 | CPUID_EXT3_XOP |
              CPUID_EXT3_3DNOWPREFETCH | CPUID_EXT3_MISALIGNSSE |
              CPUID_EXT3_SSE4A | CPUID_EXT3_ABM | CPUID_EXT3_SVM |
@@ -930,18 +925,18 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 21,
         .model = 2,
         .stepping = 0,
-        .features =
+        .features[FEAT_1_EDX] =
             CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
              CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
              CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
              CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
              CPUID_DE | CPUID_FP87,
-        .ext_features =
+        .features[FEAT_1_ECX] =
             CPUID_EXT_F16C | CPUID_EXT_AVX | CPUID_EXT_XSAVE |
              CPUID_EXT_AES | CPUID_EXT_POPCNT | CPUID_EXT_SSE42 |
              CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_FMA |
              CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3,
-        .ext2_features =
+        .features[FEAT_8000_0001_EDX] =
             CPUID_EXT2_LM | CPUID_EXT2_RDTSCP |
              CPUID_EXT2_PDPE1GB | CPUID_EXT2_FXSR | CPUID_EXT2_MMX |
              CPUID_EXT2_NX | CPUID_EXT2_PSE36 | CPUID_EXT2_PAT |
@@ -949,7 +944,7 @@ static x86_def_t builtin_x86_defs[] = {
              CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL | CPUID_EXT2_APIC |
              CPUID_EXT2_CX8 | CPUID_EXT2_MCE | CPUID_EXT2_PAE | CPUID_EXT2_MSR |
              CPUID_EXT2_TSC | CPUID_EXT2_PSE | CPUID_EXT2_DE | CPUID_EXT2_FPU,
-        .ext3_features =
+        .features[FEAT_8000_0001_ECX] =
             CPUID_EXT3_TBM | CPUID_EXT3_FMA4 | CPUID_EXT3_XOP |
              CPUID_EXT3_3DNOWPREFETCH | CPUID_EXT3_MISALIGNSSE |
              CPUID_EXT3_SSE4A | CPUID_EXT3_ABM | CPUID_EXT3_SVM |
@@ -999,22 +994,22 @@ static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def)
     x86_cpu_def->stepping = eax & 0x0F;
 
     x86_cpu_def->level = kvm_arch_get_supported_cpuid(s, 0x0, 0, R_EAX);
-    x86_cpu_def->features =
+    x86_cpu_def->features[FEAT_1_EDX] =
         kvm_arch_get_supported_cpuid(s, 0x1, 0, R_EDX);
-    x86_cpu_def->ext_features =
+    x86_cpu_def->features[FEAT_1_ECX] =
         kvm_arch_get_supported_cpuid(s, 0x1, 0, R_ECX);
 
     if (x86_cpu_def->level >= 7) {
-        x86_cpu_def->cpuid_7_0_ebx_features =
+        x86_cpu_def->features[FEAT_7_0_EBX] =
                     kvm_arch_get_supported_cpuid(s, 0x7, 0, R_EBX);
     } else {
-        x86_cpu_def->cpuid_7_0_ebx_features = 0;
+        x86_cpu_def->features[FEAT_7_0_EBX] = 0;
     }
 
     x86_cpu_def->xlevel = kvm_arch_get_supported_cpuid(s, 0x80000000, 0, R_EAX);
-    x86_cpu_def->ext2_features =
+    x86_cpu_def->features[FEAT_8000_0001_EDX] =
                 kvm_arch_get_supported_cpuid(s, 0x80000001, 0, R_EDX);
-    x86_cpu_def->ext3_features =
+    x86_cpu_def->features[FEAT_8000_0001_ECX] =
                 kvm_arch_get_supported_cpuid(s, 0x80000001, 0, R_ECX);
 
     cpu_x86_fill_model_id(x86_cpu_def->model_id);
@@ -1027,15 +1022,15 @@ static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def)
             /* Support VIA max extended level */
             x86_cpu_def->xlevel2 = eax;
             host_cpuid(0xC0000001, 0, &eax, &ebx, &ecx, &edx);
-            x86_cpu_def->ext4_features =
+            x86_cpu_def->features[FEAT_C000_0001_EDX] =
                     kvm_arch_get_supported_cpuid(s, 0xC0000001, 0, R_EDX);
         }
     }
 
     /* Other KVM-specific feature fields: */
-    x86_cpu_def->svm_features =
+    x86_cpu_def->features[FEAT_SVM] =
         kvm_arch_get_supported_cpuid(s, 0x8000000A, 0, R_EDX);
-    x86_cpu_def->kvm_features =
+    x86_cpu_def->features[FEAT_KVM] =
         kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX);
 
 #endif /* CONFIG_KVM */
@@ -1072,29 +1067,29 @@ static int kvm_check_features_against_host(X86CPU *cpu)
     uint32_t mask;
     int rv, i;
     struct model_features_t ft[] = {
-        {&env->cpuid_features,
-            &host_def.features,
+        {&env->features[FEAT_1_EDX],
+            &host_def.features[FEAT_1_EDX],
             FEAT_1_EDX },
-        {&env->cpuid_ext_features,
-            &host_def.ext_features,
+        {&env->features[FEAT_1_ECX],
+            &host_def.features[FEAT_1_ECX],
             FEAT_1_ECX },
-        {&env->cpuid_ext2_features,
-            &host_def.ext2_features,
+        {&env->features[FEAT_8000_0001_EDX],
+            &host_def.features[FEAT_8000_0001_EDX],
             FEAT_8000_0001_EDX },
-        {&env->cpuid_ext3_features,
-            &host_def.ext3_features,
+        {&env->features[FEAT_8000_0001_ECX],
+            &host_def.features[FEAT_8000_0001_ECX],
             FEAT_8000_0001_ECX },
-        {&env->cpuid_ext4_features,
-            &host_def.ext4_features,
+        {&env->features[FEAT_C000_0001_EDX],
+            &host_def.features[FEAT_C000_0001_EDX],
             FEAT_C000_0001_EDX },
-        {&env->cpuid_7_0_ebx_features,
-            &host_def.cpuid_7_0_ebx_features,
+        {&env->features[FEAT_7_0_EBX],
+            &host_def.features[FEAT_7_0_EBX],
             FEAT_7_0_EBX },
-        {&env->cpuid_svm_features,
-            &host_def.svm_features,
+        {&env->features[FEAT_SVM],
+            &host_def.features[FEAT_SVM],
             FEAT_SVM },
-        {&env->cpuid_kvm_features,
-            &host_def.kvm_features,
+        {&env->features[FEAT_KVM],
+            &host_def.features[FEAT_KVM],
             FEAT_KVM },
     };
 
@@ -1546,22 +1541,22 @@ static void cpu_x86_parse_featurestr(X86CPU *cpu, char *features, Error **errp)
         }
         featurestr = strtok(NULL, ",");
     }
-    env->cpuid_features |= plus_features[FEAT_1_EDX];
-    env->cpuid_ext_features |= plus_features[FEAT_1_ECX];
-    env->cpuid_ext2_features |= plus_features[FEAT_8000_0001_EDX];
-    env->cpuid_ext3_features |= plus_features[FEAT_8000_0001_ECX];
-    env->cpuid_ext4_features |= plus_features[FEAT_C000_0001_EDX];
-    env->cpuid_kvm_features |= plus_features[FEAT_KVM];
-    env->cpuid_svm_features |= plus_features[FEAT_SVM];
-    env->cpuid_7_0_ebx_features |= plus_features[FEAT_7_0_EBX];
-    env->cpuid_features &= ~minus_features[FEAT_1_EDX];
-    env->cpuid_ext_features &= ~minus_features[FEAT_1_ECX];
-    env->cpuid_ext2_features &= ~minus_features[FEAT_8000_0001_EDX];
-    env->cpuid_ext3_features &= ~minus_features[FEAT_8000_0001_ECX];
-    env->cpuid_ext4_features &= ~minus_features[FEAT_C000_0001_EDX];
-    env->cpuid_kvm_features &= ~minus_features[FEAT_KVM];
-    env->cpuid_svm_features &= ~minus_features[FEAT_SVM];
-    env->cpuid_7_0_ebx_features &= ~minus_features[FEAT_7_0_EBX];
+    env->features[FEAT_1_EDX] |= plus_features[FEAT_1_EDX];
+    env->features[FEAT_1_ECX] |= plus_features[FEAT_1_ECX];
+    env->features[FEAT_8000_0001_EDX] |= plus_features[FEAT_8000_0001_EDX];
+    env->features[FEAT_8000_0001_ECX] |= plus_features[FEAT_8000_0001_ECX];
+    env->features[FEAT_C000_0001_EDX] |= plus_features[FEAT_C000_0001_EDX];
+    env->features[FEAT_KVM] |= plus_features[FEAT_KVM];
+    env->features[FEAT_SVM] |= plus_features[FEAT_SVM];
+    env->features[FEAT_7_0_EBX] |= plus_features[FEAT_7_0_EBX];
+    env->features[FEAT_1_EDX] &= ~minus_features[FEAT_1_EDX];
+    env->features[FEAT_1_ECX] &= ~minus_features[FEAT_1_ECX];
+    env->features[FEAT_8000_0001_EDX] &= ~minus_features[FEAT_8000_0001_EDX];
+    env->features[FEAT_8000_0001_ECX] &= ~minus_features[FEAT_8000_0001_ECX];
+    env->features[FEAT_C000_0001_EDX] &= ~minus_features[FEAT_C000_0001_EDX];
+    env->features[FEAT_KVM] &= ~minus_features[FEAT_KVM];
+    env->features[FEAT_SVM] &= ~minus_features[FEAT_SVM];
+    env->features[FEAT_7_0_EBX] &= ~minus_features[FEAT_7_0_EBX];
 
 out:
     return;
@@ -1653,21 +1648,21 @@ static void filter_features_for_kvm(X86CPU *cpu)
     CPUX86State *env = &cpu->env;
     KVMState *s = kvm_state;
 
-    env->cpuid_features &=
+    env->features[FEAT_1_EDX] &=
         kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX);
-    env->cpuid_ext_features &=
+    env->features[FEAT_1_ECX] &=
         kvm_arch_get_supported_cpuid(s, 1, 0, R_ECX);
-    env->cpuid_ext2_features &=
+    env->features[FEAT_8000_0001_EDX] &=
         kvm_arch_get_supported_cpuid(s, 0x80000001, 0, R_EDX);
-    env->cpuid_ext3_features &=
+    env->features[FEAT_8000_0001_ECX] &=
         kvm_arch_get_supported_cpuid(s, 0x80000001, 0, R_ECX);
-    env->cpuid_svm_features  &=
+    env->features[FEAT_SVM]  &=
         kvm_arch_get_supported_cpuid(s, 0x8000000A, 0, R_EDX);
-    env->cpuid_7_0_ebx_features &=
+    env->features[FEAT_7_0_EBX] &=
         kvm_arch_get_supported_cpuid(s, 7, 0, R_EBX);
-    env->cpuid_kvm_features &=
+    env->features[FEAT_KVM] &=
         kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX);
-    env->cpuid_ext4_features &=
+    env->features[FEAT_C000_0001_EDX] &=
         kvm_arch_get_supported_cpuid(s, 0xC0000001, 0, R_EDX);
 
 }
@@ -1686,24 +1681,24 @@ static void cpu_x86_register(X86CPU *cpu, const char *name, Error **errp)
     }
 
     if (kvm_enabled()) {
-        def->kvm_features |= kvm_default_features;
+        def->features[FEAT_KVM] |= kvm_default_features;
     }
-    def->ext_features |= CPUID_EXT_HYPERVISOR;
+    def->features[FEAT_1_ECX] |= CPUID_EXT_HYPERVISOR;
 
     object_property_set_str(OBJECT(cpu), def->vendor, "vendor", errp);
     object_property_set_int(OBJECT(cpu), def->level, "level", errp);
     object_property_set_int(OBJECT(cpu), def->family, "family", errp);
     object_property_set_int(OBJECT(cpu), def->model, "model", errp);
     object_property_set_int(OBJECT(cpu), def->stepping, "stepping", errp);
-    env->cpuid_features = def->features;
-    env->cpuid_ext_features = def->ext_features;
-    env->cpuid_ext2_features = def->ext2_features;
-    env->cpuid_ext3_features = def->ext3_features;
+    env->features[FEAT_1_EDX] = def->features[FEAT_1_EDX];
+    env->features[FEAT_1_ECX] = def->features[FEAT_1_ECX];
+    env->features[FEAT_8000_0001_EDX] = def->features[FEAT_8000_0001_EDX];
+    env->features[FEAT_8000_0001_ECX] = def->features[FEAT_8000_0001_ECX];
     object_property_set_int(OBJECT(cpu), def->xlevel, "xlevel", errp);
-    env->cpuid_kvm_features = def->kvm_features;
-    env->cpuid_svm_features = def->svm_features;
-    env->cpuid_ext4_features = def->ext4_features;
-    env->cpuid_7_0_ebx_features = def->cpuid_7_0_ebx_features;
+    env->features[FEAT_KVM] = def->features[FEAT_KVM];
+    env->features[FEAT_SVM] = def->features[FEAT_SVM];
+    env->features[FEAT_C000_0001_EDX] = def->features[FEAT_C000_0001_EDX];
+    env->features[FEAT_7_0_EBX] = def->features[FEAT_7_0_EBX];
     env->cpuid_xlevel2 = def->xlevel2;
 
     object_property_set_str(OBJECT(cpu), def->model_id, "model-id", errp);
@@ -1782,7 +1777,7 @@ out:
 
 void cpu_clear_apic_feature(CPUX86State *env)
 {
-    env->cpuid_features &= ~CPUID_APIC;
+    env->features[FEAT_1_EDX] &= ~CPUID_APIC;
 }
 
 #endif /* !CONFIG_USER_ONLY */
@@ -1857,8 +1852,8 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
     case 1:
         *eax = env->cpuid_version;
         *ebx = (env->cpuid_apic_id << 24) | 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */
-        *ecx = env->cpuid_ext_features;
-        *edx = env->cpuid_features;
+        *ecx = env->features[FEAT_1_ECX];
+        *edx = env->features[FEAT_1_EDX];
         if (cs->nr_cores * cs->nr_threads > 1) {
             *ebx |= (cs->nr_cores * cs->nr_threads) << 16;
             *edx |= 1 << 28;    /* HTT bit */
@@ -1926,7 +1921,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
         /* Structured Extended Feature Flags Enumeration Leaf */
         if (count == 0) {
             *eax = 0; /* Maximum ECX value for sub-leaves */
-            *ebx = env->cpuid_7_0_ebx_features; /* Feature flags */
+            *ebx = env->features[FEAT_7_0_EBX]; /* Feature flags */
             *ecx = 0; /* Reserved */
             *edx = 0; /* Reserved */
         } else {
@@ -1961,7 +1956,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
         break;
     case 0xD:
         /* Processor Extended State */
-        if (!(env->cpuid_ext_features & CPUID_EXT_XSAVE)) {
+        if (!(env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE)) {
             *eax = 0;
             *ebx = 0;
             *ecx = 0;
@@ -1991,8 +1986,8 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
     case 0x80000001:
         *eax = env->cpuid_version;
         *ebx = 0;
-        *ecx = env->cpuid_ext3_features;
-        *edx = env->cpuid_ext2_features;
+        *ecx = env->features[FEAT_8000_0001_ECX];
+        *edx = env->features[FEAT_8000_0001_EDX];
 
         /* The Linux kernel checks for the CMPLegacy bit and
          * discards multiple thread information if it is set.
@@ -2033,12 +2028,12 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
     case 0x80000008:
         /* virtual & phys address size in low 2 bytes. */
 /* XXX: This value must match the one used in the MMU code. */
-        if (env->cpuid_ext2_features & CPUID_EXT2_LM) {
+        if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) {
             /* 64 bit processor */
 /* XXX: The physical address space is limited to 42 bits in exec.c. */
             *eax = 0x00003028; /* 48 bits virtual, 40 bits physical */
         } else {
-            if (env->cpuid_features & CPUID_PSE36) {
+            if (env->features[FEAT_1_EDX] & CPUID_PSE36) {
                 *eax = 0x00000024; /* 36 bits physical */
             } else {
                 *eax = 0x00000020; /* 32 bits physical */
@@ -2052,11 +2047,11 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
         }
         break;
     case 0x8000000A:
-        if (env->cpuid_ext3_features & CPUID_EXT3_SVM) {
+        if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) {
             *eax = 0x00000001; /* SVM Revision */
             *ebx = 0x00000010; /* nr of ASIDs */
             *ecx = 0;
-            *edx = env->cpuid_svm_features; /* optional features */
+            *edx = env->features[FEAT_SVM]; /* optional features */
         } else {
             *eax = 0;
             *ebx = 0;
@@ -2075,7 +2070,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
         *eax = env->cpuid_version;
         *ebx = 0;
         *ecx = 0;
-        *edx = env->cpuid_ext4_features;
+        *edx = env->features[FEAT_C000_0001_EDX];
         break;
     case 0xC0000002:
     case 0xC0000003:
@@ -2207,7 +2202,7 @@ static void mce_init(X86CPU *cpu)
     unsigned int bank;
 
     if (((cenv->cpuid_version >> 8) & 0xf) >= 6
-        && (cenv->cpuid_features & (CPUID_MCE | CPUID_MCA)) ==
+        && (cenv->features[FEAT_1_EDX] & (CPUID_MCE | CPUID_MCA)) ==
             (CPUID_MCE | CPUID_MCA)) {
         cenv->mcg_cap = MCE_CAP_DEF | MCE_BANKS_DEF;
         cenv->mcg_ctl = ~(uint64_t)0;
@@ -2272,7 +2267,7 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
     CPUX86State *env = &cpu->env;
     Error *local_err = NULL;
 
-    if (env->cpuid_7_0_ebx_features && env->cpuid_level < 7) {
+    if (env->features[FEAT_7_0_EBX] && env->cpuid_level < 7) {
         env->cpuid_level = 7;
     }
 
@@ -2282,21 +2277,21 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
     if (env->cpuid_vendor1 == CPUID_VENDOR_AMD_1 &&
         env->cpuid_vendor2 == CPUID_VENDOR_AMD_2 &&
         env->cpuid_vendor3 == CPUID_VENDOR_AMD_3) {
-        env->cpuid_ext2_features &= ~CPUID_EXT2_AMD_ALIASES;
-        env->cpuid_ext2_features |= (env->cpuid_features
+        env->features[FEAT_8000_0001_EDX] &= ~CPUID_EXT2_AMD_ALIASES;
+        env->features[FEAT_8000_0001_EDX] |= (env->features[FEAT_1_EDX]
            & CPUID_EXT2_AMD_ALIASES);
     }
 
     if (!kvm_enabled()) {
-        env->cpuid_features &= TCG_FEATURES;
-        env->cpuid_ext_features &= TCG_EXT_FEATURES;
-        env->cpuid_ext2_features &= (TCG_EXT2_FEATURES
+        env->features[FEAT_1_EDX] &= TCG_FEATURES;
+        env->features[FEAT_1_ECX] &= TCG_EXT_FEATURES;
+        env->features[FEAT_8000_0001_EDX] &= (TCG_EXT2_FEATURES
 #ifdef TARGET_X86_64
             | CPUID_EXT2_SYSCALL | CPUID_EXT2_LM
 #endif
             );
-        env->cpuid_ext3_features &= TCG_EXT3_FEATURES;
-        env->cpuid_svm_features &= TCG_SVM_FEATURES;
+        env->features[FEAT_8000_0001_ECX] &= TCG_EXT3_FEATURES;
+        env->features[FEAT_SVM] &= TCG_SVM_FEATURES;
     } else {
         if (check_cpuid && kvm_check_features_against_host(cpu)
             && enforce_cpuid) {
@@ -2312,7 +2307,7 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
 #ifndef CONFIG_USER_ONLY
     qemu_register_reset(x86_cpu_machine_reset_cb, cpu);
 
-    if (cpu->env.cpuid_features & CPUID_APIC || smp_cpus > 1) {
+    if (cpu->env.features[FEAT_1_EDX] & CPUID_APIC || smp_cpus > 1) {
         x86_cpu_apic_create(cpu, &local_err);
         if (local_err != NULL) {
             goto out;
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 5d16428..3e2e9f6 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -842,16 +842,9 @@ typedef struct CPUX86State {
     uint32_t cpuid_vendor2;
     uint32_t cpuid_vendor3;
     uint32_t cpuid_version;
-    uint32_t cpuid_features;
-    uint32_t cpuid_ext_features;
+    FeatureWordArray features;
     uint32_t cpuid_model[12];
-    uint32_t cpuid_ext2_features;
-    uint32_t cpuid_ext3_features;
     uint32_t cpuid_apic_id;
-    /* Store the results of Centaur's CPUID instructions */
-    uint32_t cpuid_ext4_features;
-    /* Flags from CPUID[EAX=7,ECX=0].EBX */
-    uint32_t cpuid_7_0_ebx_features;
 
     /* MTRRs */
     uint64_t mtrr_fixed[11];
@@ -865,8 +858,6 @@ typedef struct CPUX86State {
     uint8_t soft_interrupt;
     uint8_t has_error_code;
     uint32_t sipi_vector;
-    uint32_t cpuid_kvm_features;
-    uint32_t cpuid_svm_features;
     bool tsc_valid;
     int tsc_khz;
     void *kvm_xsave_buf;
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 282494f..158710a 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -463,7 +463,7 @@ void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
         tlb_flush(env, 1);
     }
     /* SSE handling */
-    if (!(env->cpuid_features & CPUID_SSE)) {
+    if (!(env->features[FEAT_1_EDX] & CPUID_SSE)) {
         new_cr4 &= ~CR4_OSFXSR_MASK;
     }
     env->hflags &= ~HF_OSFXSR_MASK;
@@ -471,7 +471,7 @@ void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
         env->hflags |= HF_OSFXSR_MASK;
     }
 
-    if (!(env->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP)) {
+    if (!(env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_SMAP)) {
         new_cr4 &= ~CR4_SMAP_MASK;
     }
     env->hflags &= ~HF_SMAP_MASK;
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 03d3059..9ffb6ca 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -454,7 +454,7 @@ int kvm_arch_init_vcpu(CPUState *cs)
     c = &cpuid_data.entries[cpuid_i++];
     memset(c, 0, sizeof(*c));
     c->function = KVM_CPUID_FEATURES;
-    c->eax = env->cpuid_kvm_features;
+    c->eax = env->features[FEAT_KVM];
 
     if (hyperv_enabled()) {
         memcpy(signature, "Hv#1\0\0\0\0\0\0\0\0", 12);
@@ -613,7 +613,7 @@ int kvm_arch_init_vcpu(CPUState *cs)
     cpuid_data.cpuid.nent = cpuid_i;
 
     if (((env->cpuid_version >> 8)&0xF) >= 6
-        && (env->cpuid_features & (CPUID_MCE | CPUID_MCA)) ==
+        && (env->features[FEAT_1_EDX] & (CPUID_MCE | CPUID_MCA)) ==
            (CPUID_MCE | CPUID_MCA)
         && kvm_check_extension(cs->kvm_state, KVM_CAP_MCE) > 0) {
         uint64_t mcg_cap;
diff --git a/target-i386/misc_helper.c b/target-i386/misc_helper.c
index dfbc07b..ec834fc 100644
--- a/target-i386/misc_helper.c
+++ b/target-i386/misc_helper.c
@@ -291,22 +291,22 @@ void helper_wrmsr(CPUX86State *env)
             uint64_t update_mask;
 
             update_mask = 0;
-            if (env->cpuid_ext2_features & CPUID_EXT2_SYSCALL) {
+            if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_SYSCALL) {
                 update_mask |= MSR_EFER_SCE;
             }
-            if (env->cpuid_ext2_features & CPUID_EXT2_LM) {
+            if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) {
                 update_mask |= MSR_EFER_LME;
             }
-            if (env->cpuid_ext2_features & CPUID_EXT2_FFXSR) {
+            if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) {
                 update_mask |= MSR_EFER_FFXSR;
             }
-            if (env->cpuid_ext2_features & CPUID_EXT2_NX) {
+            if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_NX) {
                 update_mask |= MSR_EFER_NXE;
             }
-            if (env->cpuid_ext3_features & CPUID_EXT3_SVM) {
+            if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) {
                 update_mask |= MSR_EFER_SVME;
             }
-            if (env->cpuid_ext2_features & CPUID_EXT2_FFXSR) {
+            if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) {
                 update_mask |= MSR_EFER_FFXSR;
             }
             cpu_load_efer(env, (env->efer & ~update_mask) |
@@ -513,7 +513,7 @@ void helper_rdmsr(CPUX86State *env)
         val = env->mtrr_deftype;
         break;
     case MSR_MTRRcap:
-        if (env->cpuid_features & CPUID_MTRR) {
+        if (env->features[FEAT_1_EDX] & CPUID_MTRR) {
             val = MSR_MTRRcap_VCNT | MSR_MTRRcap_FIXRANGE_SUPPORT |
                 MSR_MTRRcap_WC_SUPPORTED;
         } else {
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 40f891d..524a0b4 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -8290,11 +8290,11 @@ static inline void gen_intermediate_code_internal(CPUX86State *env,
     if (flags & HF_SOFTMMU_MASK) {
         dc->mem_index = (cpu_mmu_index(env) + 1) << 2;
     }
-    dc->cpuid_features = env->cpuid_features;
-    dc->cpuid_ext_features = env->cpuid_ext_features;
-    dc->cpuid_ext2_features = env->cpuid_ext2_features;
-    dc->cpuid_ext3_features = env->cpuid_ext3_features;
-    dc->cpuid_7_0_ebx_features = env->cpuid_7_0_ebx_features;
+    dc->cpuid_features = env->features[FEAT_1_EDX];
+    dc->cpuid_ext_features = env->features[FEAT_1_ECX];
+    dc->cpuid_ext2_features = env->features[FEAT_8000_0001_EDX];
+    dc->cpuid_ext3_features = env->features[FEAT_8000_0001_ECX];
+    dc->cpuid_7_0_ebx_features = env->features[FEAT_7_0_EBX];
 #ifdef TARGET_X86_64
     dc->lma = (flags >> HF_LMA_SHIFT) & 1;
     dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
commit 27861ecc47cf9dc35961ac901e26abbd898c377c
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Mon Apr 22 16:00:14 2013 -0300

    target-i386: Break CPUID feature definition lines
    
    Break lines on kvm_check_features_against_host(), kvm_cpu_fill_host(),
    and builtin_x86_defs, so they don't get too long once the *_features
    fields are replaced by an array.
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Reviewed-by: Igor Mammedov <imammedo at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 081b579..424e7c2 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -424,13 +424,17 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 6,
         .model = 2,
         .stepping = 3,
-        .features = PPRO_FEATURES |
+        .features =
+            PPRO_FEATURES |
             CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
             CPUID_PSE36,
-        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_CX16 | CPUID_EXT_POPCNT,
-        .ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
+        .ext_features =
+            CPUID_EXT_SSE3 | CPUID_EXT_CX16 | CPUID_EXT_POPCNT,
+        .ext2_features =
+            (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
             CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
-        .ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
+        .ext3_features =
+            CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
             CPUID_EXT3_ABM | CPUID_EXT3_SSE4A,
         .xlevel = 0x8000000A,
     },
@@ -441,12 +445,15 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 16,
         .model = 2,
         .stepping = 3,
-        .features = PPRO_FEATURES |
+        .features =
+            PPRO_FEATURES |
             CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
             CPUID_PSE36 | CPUID_VME | CPUID_HT,
-        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_CX16 |
+        .ext_features =
+            CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_CX16 |
             CPUID_EXT_POPCNT,
-        .ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
+        .ext2_features =
+            (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
             CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX |
             CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_MMXEXT |
             CPUID_EXT2_FFXSR | CPUID_EXT2_PDPE1GB | CPUID_EXT2_RDTSCP,
@@ -454,9 +461,11 @@ static x86_def_t builtin_x86_defs[] = {
                     CPUID_EXT3_CR8LEG,
                     CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH,
                     CPUID_EXT3_OSVW, CPUID_EXT3_IBS */
-        .ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
+        .ext3_features =
+            CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
             CPUID_EXT3_ABM | CPUID_EXT3_SSE4A,
-        .svm_features = CPUID_SVM_NPT | CPUID_SVM_LBRV,
+        .svm_features =
+            CPUID_SVM_NPT | CPUID_SVM_LBRV,
         .xlevel = 0x8000001A,
         .model_id = "AMD Phenom(tm) 9550 Quad-Core Processor"
     },
@@ -467,15 +476,19 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 6,
         .model = 15,
         .stepping = 11,
-        .features = PPRO_FEATURES |
+        .features =
+            PPRO_FEATURES |
             CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
             CPUID_PSE36 | CPUID_VME | CPUID_DTS | CPUID_ACPI | CPUID_SS |
             CPUID_HT | CPUID_TM | CPUID_PBE,
-        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 |
+        .ext_features =
+            CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 |
             CPUID_EXT_DTES64 | CPUID_EXT_DSCPL | CPUID_EXT_VMX | CPUID_EXT_EST |
             CPUID_EXT_TM2 | CPUID_EXT_CX16 | CPUID_EXT_XTPR | CPUID_EXT_PDCM,
-        .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
-        .ext3_features = CPUID_EXT3_LAHF_LM,
+        .ext2_features =
+            CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
+        .ext3_features =
+            CPUID_EXT3_LAHF_LM,
         .xlevel = 0x80000008,
         .model_id = "Intel(R) Core(TM)2 Duo CPU     T7700  @ 2.40GHz",
     },
@@ -487,19 +500,23 @@ static x86_def_t builtin_x86_defs[] = {
         .model = 6,
         .stepping = 1,
         /* Missing: CPUID_VME, CPUID_HT */
-        .features = PPRO_FEATURES |
+        .features =
+            PPRO_FEATURES |
             CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
             CPUID_PSE36,
         /* Missing: CPUID_EXT_POPCNT, CPUID_EXT_MONITOR */
-        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_CX16,
+        .ext_features =
+            CPUID_EXT_SSE3 | CPUID_EXT_CX16,
         /* Missing: CPUID_EXT2_PDPE1GB, CPUID_EXT2_RDTSCP */
-        .ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
+        .ext2_features =
+            (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
             CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
         /* Missing: CPUID_EXT3_LAHF_LM, CPUID_EXT3_CMP_LEG, CPUID_EXT3_EXTAPIC,
                     CPUID_EXT3_CR8LEG, CPUID_EXT3_ABM, CPUID_EXT3_SSE4A,
                     CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH,
                     CPUID_EXT3_OSVW, CPUID_EXT3_IBS, CPUID_EXT3_SVM */
-        .ext3_features = 0,
+        .ext3_features =
+            0,
         .xlevel = 0x80000008,
         .model_id = "Common KVM processor"
     },
@@ -510,8 +527,10 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 6,
         .model = 3,
         .stepping = 3,
-        .features = PPRO_FEATURES,
-        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_POPCNT,
+        .features =
+            PPRO_FEATURES,
+        .ext_features =
+            CPUID_EXT_SSE3 | CPUID_EXT_POPCNT,
         .xlevel = 0x80000004,
     },
     {
@@ -521,11 +540,15 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 15,
         .model = 6,
         .stepping = 1,
-        .features = PPRO_FEATURES |
+        .features =
+            PPRO_FEATURES |
             CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_PSE36,
-        .ext_features = CPUID_EXT_SSE3,
-        .ext2_features = PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES,
-        .ext3_features = 0,
+        .ext_features =
+            CPUID_EXT_SSE3,
+        .ext2_features =
+            PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES,
+        .ext3_features =
+            0,
         .xlevel = 0x80000008,
         .model_id = "Common 32-bit KVM processor"
     },
@@ -536,12 +559,15 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 6,
         .model = 14,
         .stepping = 8,
-        .features = PPRO_FEATURES | CPUID_VME |
+        .features =
+            PPRO_FEATURES | CPUID_VME |
             CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_DTS | CPUID_ACPI |
             CPUID_SS | CPUID_HT | CPUID_TM | CPUID_PBE,
-        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_VMX |
+        .ext_features =
+            CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_VMX |
             CPUID_EXT_EST | CPUID_EXT_TM2 | CPUID_EXT_XTPR | CPUID_EXT_PDCM,
-        .ext2_features = CPUID_EXT2_NX,
+        .ext2_features =
+            CPUID_EXT2_NX,
         .xlevel = 0x80000008,
         .model_id = "Genuine Intel(R) CPU           T2600  @ 2.16GHz",
     },
@@ -552,7 +578,8 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 4,
         .model = 0,
         .stepping = 0,
-        .features = I486_FEATURES,
+        .features =
+            I486_FEATURES,
         .xlevel = 0,
     },
     {
@@ -562,7 +589,8 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 5,
         .model = 4,
         .stepping = 3,
-        .features = PENTIUM_FEATURES,
+        .features =
+            PENTIUM_FEATURES,
         .xlevel = 0,
     },
     {
@@ -572,7 +600,8 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 6,
         .model = 5,
         .stepping = 2,
-        .features = PENTIUM2_FEATURES,
+        .features =
+            PENTIUM2_FEATURES,
         .xlevel = 0,
     },
     {
@@ -582,7 +611,8 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 6,
         .model = 7,
         .stepping = 3,
-        .features = PENTIUM3_FEATURES,
+        .features =
+            PENTIUM3_FEATURES,
         .xlevel = 0,
     },
     {
@@ -592,9 +622,11 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 6,
         .model = 2,
         .stepping = 3,
-        .features = PPRO_FEATURES | CPUID_PSE36 | CPUID_VME | CPUID_MTRR |
+        .features =
+            PPRO_FEATURES | CPUID_PSE36 | CPUID_VME | CPUID_MTRR |
             CPUID_MCA,
-        .ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
+        .ext2_features =
+            (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
             CPUID_EXT2_MMXEXT | CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT,
         .xlevel = 0x80000008,
     },
@@ -606,15 +638,19 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 6,
         .model = 28,
         .stepping = 2,
-        .features = PPRO_FEATURES |
+        .features =
+            PPRO_FEATURES |
             CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_VME | CPUID_DTS |
             CPUID_ACPI | CPUID_SS | CPUID_HT | CPUID_TM | CPUID_PBE,
             /* Some CPUs got no CPUID_SEP */
-        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 |
+        .ext_features =
+            CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 |
             CPUID_EXT_DSCPL | CPUID_EXT_EST | CPUID_EXT_TM2 | CPUID_EXT_XTPR,
-        .ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
+        .ext2_features =
+            (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
             CPUID_EXT2_NX,
-        .ext3_features = CPUID_EXT3_LAHF_LM,
+        .ext3_features =
+            CPUID_EXT3_LAHF_LM,
         .xlevel = 0x8000000A,
         .model_id = "Intel(R) Atom(TM) CPU N270   @ 1.60GHz",
     },
@@ -625,14 +661,18 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 6,
         .model = 2,
         .stepping = 3,
-        .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
+        .features =
+            CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
              CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
              CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
              CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
              CPUID_DE | CPUID_FP87,
-        .ext_features = CPUID_EXT_SSSE3 | CPUID_EXT_SSE3,
-        .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL,
-        .ext3_features = CPUID_EXT3_LAHF_LM,
+        .ext_features =
+            CPUID_EXT_SSSE3 | CPUID_EXT_SSE3,
+        .ext2_features =
+            CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL,
+        .ext3_features =
+            CPUID_EXT3_LAHF_LM,
         .xlevel = 0x8000000A,
         .model_id = "Intel Celeron_4x0 (Conroe/Merom Class Core 2)",
     },
@@ -643,15 +683,19 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 6,
         .model = 2,
         .stepping = 3,
-        .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
+        .features =
+            CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
              CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
              CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
              CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
              CPUID_DE | CPUID_FP87,
-        .ext_features = CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 |
+        .ext_features =
+            CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 |
              CPUID_EXT_SSE3,
-        .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL,
-        .ext3_features = CPUID_EXT3_LAHF_LM,
+        .ext2_features =
+            CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL,
+        .ext3_features =
+            CPUID_EXT3_LAHF_LM,
         .xlevel = 0x8000000A,
         .model_id = "Intel Core 2 Duo P9xxx (Penryn Class Core 2)",
     },
@@ -662,15 +706,19 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 6,
         .model = 2,
         .stepping = 3,
-        .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
+        .features =
+            CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
              CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
              CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
              CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
              CPUID_DE | CPUID_FP87,
-        .ext_features = CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 |
+        .ext_features =
+            CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 |
              CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_SSE3,
-        .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
-        .ext3_features = CPUID_EXT3_LAHF_LM,
+        .ext2_features =
+            CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
+        .ext3_features =
+            CPUID_EXT3_LAHF_LM,
         .xlevel = 0x8000000A,
         .model_id = "Intel Core i7 9xx (Nehalem Class Core i7)",
     },
@@ -681,16 +729,20 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 6,
         .model = 44,
         .stepping = 1,
-        .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
+        .features =
+            CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
              CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
              CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
              CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
              CPUID_DE | CPUID_FP87,
-        .ext_features = CPUID_EXT_AES | CPUID_EXT_POPCNT | CPUID_EXT_SSE42 |
+        .ext_features =
+            CPUID_EXT_AES | CPUID_EXT_POPCNT | CPUID_EXT_SSE42 |
              CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 |
              CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3,
-        .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
-        .ext3_features = CPUID_EXT3_LAHF_LM,
+        .ext2_features =
+            CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
+        .ext3_features =
+            CPUID_EXT3_LAHF_LM,
         .xlevel = 0x8000000A,
         .model_id = "Westmere E56xx/L56xx/X56xx (Nehalem-C)",
     },
@@ -701,19 +753,23 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 6,
         .model = 42,
         .stepping = 1,
-        .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
+        .features =
+            CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
              CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
              CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
              CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
              CPUID_DE | CPUID_FP87,
-        .ext_features = CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
+        .ext_features =
+            CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
              CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_POPCNT |
              CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 |
              CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ |
              CPUID_EXT_SSE3,
-        .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
+        .ext2_features =
+            CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
              CPUID_EXT2_SYSCALL,
-        .ext3_features = CPUID_EXT3_LAHF_LM,
+        .ext3_features =
+            CPUID_EXT3_LAHF_LM,
         .xlevel = 0x8000000A,
         .model_id = "Intel Xeon E312xx (Sandy Bridge)",
     },
@@ -724,21 +780,26 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 6,
         .model = 60,
         .stepping = 1,
-        .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
+        .features =
+            CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
              CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
              CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
              CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
              CPUID_DE | CPUID_FP87,
-        .ext_features = CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
+        .ext_features =
+            CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
              CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 |
              CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 |
              CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 |
              CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE |
              CPUID_EXT_PCID,
-        .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
+        .ext2_features =
+            CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
              CPUID_EXT2_SYSCALL,
-        .ext3_features = CPUID_EXT3_LAHF_LM,
-        .cpuid_7_0_ebx_features = CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 |
+        .ext3_features =
+            CPUID_EXT3_LAHF_LM,
+        .cpuid_7_0_ebx_features =
+            CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 |
             CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP |
             CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID |
             CPUID_7_0_EBX_RTM,
@@ -752,13 +813,16 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 15,
         .model = 6,
         .stepping = 1,
-        .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
+        .features =
+            CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
              CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
              CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
              CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
              CPUID_DE | CPUID_FP87,
-        .ext_features = CPUID_EXT_SSE3,
-        .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_FXSR | CPUID_EXT2_MMX |
+        .ext_features =
+            CPUID_EXT_SSE3,
+        .ext2_features =
+            CPUID_EXT2_LM | CPUID_EXT2_FXSR | CPUID_EXT2_MMX |
              CPUID_EXT2_NX | CPUID_EXT2_PSE36 | CPUID_EXT2_PAT |
              CPUID_EXT2_CMOV | CPUID_EXT2_MCA | CPUID_EXT2_PGE |
              CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL | CPUID_EXT2_APIC |
@@ -774,20 +838,24 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 15,
         .model = 6,
         .stepping = 1,
-        .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
+        .features =
+            CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
              CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
              CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
              CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
              CPUID_DE | CPUID_FP87,
-        .ext_features = CPUID_EXT_CX16 | CPUID_EXT_SSE3,
-        .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_FXSR |
+        .ext_features =
+            CPUID_EXT_CX16 | CPUID_EXT_SSE3,
+        .ext2_features =
+            CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_FXSR |
              CPUID_EXT2_MMX | CPUID_EXT2_NX | CPUID_EXT2_PSE36 |
              CPUID_EXT2_PAT | CPUID_EXT2_CMOV | CPUID_EXT2_MCA |
              CPUID_EXT2_PGE | CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL |
              CPUID_EXT2_APIC | CPUID_EXT2_CX8 | CPUID_EXT2_MCE |
              CPUID_EXT2_PAE | CPUID_EXT2_MSR | CPUID_EXT2_TSC | CPUID_EXT2_PSE |
              CPUID_EXT2_DE | CPUID_EXT2_FPU,
-        .ext3_features = CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM,
+        .ext3_features =
+            CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM,
         .xlevel = 0x80000008,
         .model_id = "AMD Opteron 22xx (Gen 2 Class Opteron)",
     },
@@ -798,21 +866,25 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 15,
         .model = 6,
         .stepping = 1,
-        .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
+        .features =
+            CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
              CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
              CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
              CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
              CPUID_DE | CPUID_FP87,
-        .ext_features = CPUID_EXT_POPCNT | CPUID_EXT_CX16 | CPUID_EXT_MONITOR |
+        .ext_features =
+            CPUID_EXT_POPCNT | CPUID_EXT_CX16 | CPUID_EXT_MONITOR |
              CPUID_EXT_SSE3,
-        .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_FXSR |
+        .ext2_features =
+            CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_FXSR |
              CPUID_EXT2_MMX | CPUID_EXT2_NX | CPUID_EXT2_PSE36 |
              CPUID_EXT2_PAT | CPUID_EXT2_CMOV | CPUID_EXT2_MCA |
              CPUID_EXT2_PGE | CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL |
              CPUID_EXT2_APIC | CPUID_EXT2_CX8 | CPUID_EXT2_MCE |
              CPUID_EXT2_PAE | CPUID_EXT2_MSR | CPUID_EXT2_TSC | CPUID_EXT2_PSE |
              CPUID_EXT2_DE | CPUID_EXT2_FPU,
-        .ext3_features = CPUID_EXT3_MISALIGNSSE | CPUID_EXT3_SSE4A |
+        .ext3_features =
+            CPUID_EXT3_MISALIGNSSE | CPUID_EXT3_SSE4A |
              CPUID_EXT3_ABM | CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM,
         .xlevel = 0x80000008,
         .model_id = "AMD Opteron 23xx (Gen 3 Class Opteron)",
@@ -824,23 +896,27 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 21,
         .model = 1,
         .stepping = 2,
-        .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
+        .features =
+            CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
              CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
              CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
              CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
              CPUID_DE | CPUID_FP87,
-        .ext_features = CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
+        .ext_features =
+            CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
              CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 |
              CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ |
              CPUID_EXT_SSE3,
-        .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP |
+        .ext2_features =
+            CPUID_EXT2_LM | CPUID_EXT2_RDTSCP |
              CPUID_EXT2_PDPE1GB | CPUID_EXT2_FXSR | CPUID_EXT2_MMX |
              CPUID_EXT2_NX | CPUID_EXT2_PSE36 | CPUID_EXT2_PAT |
              CPUID_EXT2_CMOV | CPUID_EXT2_MCA | CPUID_EXT2_PGE |
              CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL | CPUID_EXT2_APIC |
              CPUID_EXT2_CX8 | CPUID_EXT2_MCE | CPUID_EXT2_PAE | CPUID_EXT2_MSR |
              CPUID_EXT2_TSC | CPUID_EXT2_PSE | CPUID_EXT2_DE | CPUID_EXT2_FPU,
-        .ext3_features = CPUID_EXT3_FMA4 | CPUID_EXT3_XOP |
+        .ext3_features =
+            CPUID_EXT3_FMA4 | CPUID_EXT3_XOP |
              CPUID_EXT3_3DNOWPREFETCH | CPUID_EXT3_MISALIGNSSE |
              CPUID_EXT3_SSE4A | CPUID_EXT3_ABM | CPUID_EXT3_SVM |
              CPUID_EXT3_LAHF_LM,
@@ -854,23 +930,27 @@ static x86_def_t builtin_x86_defs[] = {
         .family = 21,
         .model = 2,
         .stepping = 0,
-        .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
+        .features =
+            CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
              CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
              CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
              CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
              CPUID_DE | CPUID_FP87,
-        .ext_features = CPUID_EXT_F16C | CPUID_EXT_AVX | CPUID_EXT_XSAVE |
+        .ext_features =
+            CPUID_EXT_F16C | CPUID_EXT_AVX | CPUID_EXT_XSAVE |
              CPUID_EXT_AES | CPUID_EXT_POPCNT | CPUID_EXT_SSE42 |
              CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_FMA |
              CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3,
-        .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP |
+        .ext2_features =
+            CPUID_EXT2_LM | CPUID_EXT2_RDTSCP |
              CPUID_EXT2_PDPE1GB | CPUID_EXT2_FXSR | CPUID_EXT2_MMX |
              CPUID_EXT2_NX | CPUID_EXT2_PSE36 | CPUID_EXT2_PAT |
              CPUID_EXT2_CMOV | CPUID_EXT2_MCA | CPUID_EXT2_PGE |
              CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL | CPUID_EXT2_APIC |
              CPUID_EXT2_CX8 | CPUID_EXT2_MCE | CPUID_EXT2_PAE | CPUID_EXT2_MSR |
              CPUID_EXT2_TSC | CPUID_EXT2_PSE | CPUID_EXT2_DE | CPUID_EXT2_FPU,
-        .ext3_features = CPUID_EXT3_TBM | CPUID_EXT3_FMA4 | CPUID_EXT3_XOP |
+        .ext3_features =
+            CPUID_EXT3_TBM | CPUID_EXT3_FMA4 | CPUID_EXT3_XOP |
              CPUID_EXT3_3DNOWPREFETCH | CPUID_EXT3_MISALIGNSSE |
              CPUID_EXT3_SSE4A | CPUID_EXT3_ABM | CPUID_EXT3_SVM |
              CPUID_EXT3_LAHF_LM,
@@ -919,8 +999,10 @@ static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def)
     x86_cpu_def->stepping = eax & 0x0F;
 
     x86_cpu_def->level = kvm_arch_get_supported_cpuid(s, 0x0, 0, R_EAX);
-    x86_cpu_def->features = kvm_arch_get_supported_cpuid(s, 0x1, 0, R_EDX);
-    x86_cpu_def->ext_features = kvm_arch_get_supported_cpuid(s, 0x1, 0, R_ECX);
+    x86_cpu_def->features =
+        kvm_arch_get_supported_cpuid(s, 0x1, 0, R_EDX);
+    x86_cpu_def->ext_features =
+        kvm_arch_get_supported_cpuid(s, 0x1, 0, R_ECX);
 
     if (x86_cpu_def->level >= 7) {
         x86_cpu_def->cpuid_7_0_ebx_features =
@@ -990,21 +1072,29 @@ static int kvm_check_features_against_host(X86CPU *cpu)
     uint32_t mask;
     int rv, i;
     struct model_features_t ft[] = {
-        {&env->cpuid_features, &host_def.features,
+        {&env->cpuid_features,
+            &host_def.features,
             FEAT_1_EDX },
-        {&env->cpuid_ext_features, &host_def.ext_features,
+        {&env->cpuid_ext_features,
+            &host_def.ext_features,
             FEAT_1_ECX },
-        {&env->cpuid_ext2_features, &host_def.ext2_features,
+        {&env->cpuid_ext2_features,
+            &host_def.ext2_features,
             FEAT_8000_0001_EDX },
-        {&env->cpuid_ext3_features, &host_def.ext3_features,
+        {&env->cpuid_ext3_features,
+            &host_def.ext3_features,
             FEAT_8000_0001_ECX },
-        {&env->cpuid_ext4_features, &host_def.ext4_features,
+        {&env->cpuid_ext4_features,
+            &host_def.ext4_features,
             FEAT_C000_0001_EDX },
-        {&env->cpuid_7_0_ebx_features, &host_def.cpuid_7_0_ebx_features,
+        {&env->cpuid_7_0_ebx_features,
+            &host_def.cpuid_7_0_ebx_features,
             FEAT_7_0_EBX },
-        {&env->cpuid_svm_features, &host_def.svm_features,
+        {&env->cpuid_svm_features,
+            &host_def.svm_features,
             FEAT_SVM },
-        {&env->cpuid_kvm_features, &host_def.kvm_features,
+        {&env->cpuid_kvm_features,
+            &host_def.kvm_features,
             FEAT_KVM },
     };
 
commit fc7a504c0126b16aa2bd50d92584e9cc08f636a3
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Mon Apr 22 16:00:13 2013 -0300

    target-i386/kvm.c: Code formatting changes
    
    Add appropriate spaces around operators, and break line where it needs
    to be broken to allow feature-words array to be introduced without
    having too-long lines.
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Reviewed-by: Igor Mammedov <imammedo at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 0e7cc81..03d3059 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -613,7 +613,8 @@ int kvm_arch_init_vcpu(CPUState *cs)
     cpuid_data.cpuid.nent = cpuid_i;
 
     if (((env->cpuid_version >> 8)&0xF) >= 6
-        && (env->cpuid_features&(CPUID_MCE|CPUID_MCA)) == (CPUID_MCE|CPUID_MCA)
+        && (env->cpuid_features & (CPUID_MCE | CPUID_MCA)) ==
+           (CPUID_MCE | CPUID_MCA)
         && kvm_check_extension(cs->kvm_state, KVM_CAP_MCE) > 0) {
         uint64_t mcg_cap;
         int banks;
commit 90e4b0c3de2b3927e71f23d95c3c27d60e5c89cc
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Mon Apr 22 16:00:12 2013 -0300

    target-i386: Group together level, xlevel, xlevel2 fields
    
    Consolidate level, xlevel, xlevel2 fields in x86_def_t and CPUX86State.
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Reviewed-by: Igor Mammedov <imammedo at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index bba41fe..081b579 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -350,6 +350,8 @@ static void add_flagname_to_bitmaps(const char *flagname,
 typedef struct x86_def_t {
     const char *name;
     uint32_t level;
+    uint32_t xlevel;
+    uint32_t xlevel2;
     /* vendor is zero-terminated, 12 character ASCII string */
     char vendor[CPUID_VENDOR_SZ + 1];
     int family;
@@ -357,11 +359,9 @@ typedef struct x86_def_t {
     int stepping;
     uint32_t features, ext_features, ext2_features, ext3_features;
     uint32_t kvm_features, svm_features;
-    uint32_t xlevel;
     char model_id[48];
     /* Store the results of Centaur's CPUID instructions */
     uint32_t ext4_features;
-    uint32_t xlevel2;
     /* The feature bits on CPUID[EAX=7,ECX=0].EBX */
     uint32_t cpuid_7_0_ebx_features;
 } x86_def_t;
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index f193752..5d16428 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -836,19 +836,19 @@ typedef struct CPUX86State {
 
     /* processor features (e.g. for CPUID insn) */
     uint32_t cpuid_level;
+    uint32_t cpuid_xlevel;
+    uint32_t cpuid_xlevel2;
     uint32_t cpuid_vendor1;
     uint32_t cpuid_vendor2;
     uint32_t cpuid_vendor3;
     uint32_t cpuid_version;
     uint32_t cpuid_features;
     uint32_t cpuid_ext_features;
-    uint32_t cpuid_xlevel;
     uint32_t cpuid_model[12];
     uint32_t cpuid_ext2_features;
     uint32_t cpuid_ext3_features;
     uint32_t cpuid_apic_id;
     /* Store the results of Centaur's CPUID instructions */
-    uint32_t cpuid_xlevel2;
     uint32_t cpuid_ext4_features;
     /* Flags from CPUID[EAX=7,ECX=0].EBX */
     uint32_t cpuid_7_0_ebx_features;
commit 6e860b5db4c76c66d7e02f93c9e22e0384bd3c6c
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Wed May 1 07:41:26 2013 +0200

    pvscsi: fix compilation on 32 bit hosts
    
    This fixes the following error:
    In file included from qemu/include/trace.h:4:0,
                     from trace/generated-events.c:3:
    ./trace/generated-tracers.h: In function ‘trace_pvscsi_get_sg_list’:
    ./trace/generated-tracers.h:4271:9: error: format ‘%lu’ expects argument of
    type ‘long unsigned int’, but argument 4 has type ‘size_t’ [-Werror=format]
    
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>

diff --git a/trace-events b/trace-events
index ffaa3f4..55e80be 100644
--- a/trace-events
+++ b/trace-events
@@ -776,7 +776,7 @@ pvscsi_update_irq_msi(void) "sending MSI notification"
 pvscsi_cmp_ring_put(unsigned long addr) "got completion descriptor 0x%lx"
 pvscsi_msg_ring_put(unsigned long addr) "got message descriptor 0x%lx"
 pvscsi_complete_request(uint64_t context, uint64_t len, uint8_t sense_key) "completion: ctx: 0x%"PRIx64", len: 0x%"PRIx64", sense key: %u"
-pvscsi_get_sg_list(int nsg, size_t size) "get SG list: depth: %u, size: %lu"
+pvscsi_get_sg_list(int nsg, size_t size) "get SG list: depth: %u, size: %zu"
 pvscsi_get_next_sg_elem(uint32_t flags) "unknown flags in SG element (val: 0x%x)"
 pvscsi_command_complete_not_found(uint32_t tag) "can't find request for tag 0x%x"
 pvscsi_command_complete_data_run(void) "not all data required for command transferred"
commit 805a25050272fe7cbbc2e9ce911612fc86c7b9a9
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sun Apr 28 11:49:57 2013 +0200

    Trivial grammar and spelling fixes
    
    similiar -> similar
    recieve -> receive
    transfered -> transferred
    preperation -> preparation
    
    Most changes are in comments, one modifies a parameter name in a function
    prototype.
    
    The spelling fixes were made using codespell.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Acked-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>

diff --git a/hw/moxie/moxiesim.c b/hw/moxie/moxiesim.c
index 70bf28f..649f9a7 100644
--- a/hw/moxie/moxiesim.c
+++ b/hw/moxie/moxiesim.c
@@ -1,7 +1,7 @@
 /*
  * QEMU/moxiesim emulation
  *
- * Emulates a very simple machine model similiar to the one use by the
+ * Emulates a very simple machine model similar to the one used by the
  * GDB moxie simulator.
  *
  * Copyright (c) 2008, 2009, 2010, 2013 Anthony Green
diff --git a/include/hw/stream.h b/include/hw/stream.h
index 35eb083..30ccc56 100644
--- a/include/hw/stream.h
+++ b/include/hw/stream.h
@@ -25,9 +25,9 @@ typedef struct StreamSlaveClass {
     /**
      * can push - determine if a stream slave is capable of accepting at least
      * one byte of data. Returns false if cannot accept. If not implemented, the
-     * slave is assumed to always be capable of recieveing.
+     * slave is assumed to always be capable of receiving.
      * @notify: Optional callback that the slave will call when the slave is
-     * capable of recieving again. Only called if false is returned.
+     * capable of receiving again. Only called if false is returned.
      * @notify_opaque: opaque data to pass to notify call.
      */
     bool (*can_push)(StreamSlave *obj, StreamCanPushNotifyFn notify,
@@ -37,7 +37,7 @@ typedef struct StreamSlaveClass {
      * returned. If the slave short returns, the master must wait before trying
      * again, the slave may continue to just return 0 waiting for the vm time to
      * advance. The can_push() function can be used to trap the point in time
-     * where the slave is ready to recieve again, otherwise polling on a QEMU
+     * where the slave is ready to receive again, otherwise polling on a QEMU
      * timer will work.
      * @obj: Stream slave to push to
      * @buf: Data to write
diff --git a/include/sysemu/rng.h b/include/sysemu/rng.h
index 509abd0..7637fac 100644
--- a/include/sysemu/rng.h
+++ b/include/sysemu/rng.h
@@ -37,7 +37,7 @@ struct RngBackendClass
     ObjectClass parent_class;
 
     void (*request_entropy)(RngBackend *s, size_t size,
-                            EntropyReceiveFunc *recieve_entropy, void *opaque);
+                            EntropyReceiveFunc *receive_entropy, void *opaque);
     void (*cancel_requests)(RngBackend *s);
 
     void (*opened)(RngBackend *s, Error **errp);
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 0e89132..d15bec1 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -2493,7 +2493,7 @@ The main json-object contains the following:
             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
+         - "normal" : number of whole pages transferred.  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,
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 0c3cf68..f97e431 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -3806,7 +3806,7 @@ static void cout_tm64(DisasContext *s, DisasOps *o)
 }
 
 /* ====================================================================== */
-/* The "PREPeration" generators.  These initialize the DisasOps.OUT fields
+/* The "PREParation" generators.  These initialize the DisasOps.OUT fields
    with the TCG register to which we will write.  Used in combination with
    the "wout" generators, in some cases we need a new temporary, and in
    some cases we can write to a TCG global.  */
commit 372e47e9b5e31c493823d7f512716644fb02d0fd
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Apr 28 16:27:26 2013 +0200

    configure: Pick up libseccomp include path
    
    openSUSE 12.3 has seccomp.h in /usr/include/libseccomp-1.0.1,
    so add `pkg-config --cflags libseccomp` output to QEMU_CFLAGS.
    
    Cc: qemu-stable at nongnu.org
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>

diff --git a/configure b/configure
index d91b141..c4d85ba 100755
--- a/configure
+++ b/configure
@@ -1499,6 +1499,7 @@ libs_softmmu="$libs_softmmu -lz"
 if test "$seccomp" != "no" ; then
     if $pkg_config --atleast-version=1.0.0 libseccomp --modversion >/dev/null 2>&1; then
         libs_softmmu="$libs_softmmu `$pkg_config --libs libseccomp`"
+        QEMU_CFLAGS="$QEMU_CFLAGS `$pkg_config --cflags libseccomp`"
 	seccomp="yes"
     else
 	if test "$seccomp" = "yes"; then
commit c649983b582687bbdb4019e308f015913e31065e
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Tue Apr 30 18:00:53 2013 +0200

    pc: Implement QEMUMachine::hot_add_cpu hook
    
    Signed-off-by: Igor Mammedov <imammedo at redhat.com>
    Reviewed-by: Eduardo Habkost <ehabkost at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 28f958d..197d218 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -54,6 +54,7 @@
 #include "qemu/config-file.h"
 #include "hw/acpi/acpi.h"
 #include "hw/cpu/icc_bus.h"
+#include "hw/boards.h"
 
 /* debug PC/ISA interrupts */
 //#define DEBUG_IRQ
@@ -919,6 +920,30 @@ static X86CPU *pc_new_cpu(const char *cpu_model, int64_t apic_id,
     return cpu;
 }
 
+static const char *current_cpu_model;
+
+void pc_hot_add_cpu(const int64_t id, Error **errp)
+{
+    DeviceState *icc_bridge;
+    int64_t apic_id = x86_cpu_apic_id_from_index(id);
+
+    if (cpu_exists(apic_id)) {
+        error_setg(errp, "Unable to add CPU: %" PRIi64
+                   ", it already exists", id);
+        return;
+    }
+
+    if (id >= max_cpus) {
+        error_setg(errp, "Unable to add CPU: %" PRIi64
+                   ", max allowed: %d", id, max_cpus - 1);
+        return;
+    }
+
+    icc_bridge = DEVICE(object_resolve_path_type("icc-bridge",
+                                                 TYPE_ICC_BRIDGE, NULL));
+    pc_new_cpu(current_cpu_model, apic_id, icc_bridge, errp);
+}
+
 void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge)
 {
     int i;
@@ -933,6 +958,7 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge)
         cpu_model = "qemu32";
 #endif
     }
+    current_cpu_model = cpu_model;
 
     for (i = 0; i < smp_cpus; i++) {
         cpu = pc_new_cpu(cpu_model, x86_cpu_apic_id_from_index(i),
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 251e18f..fe52e5f 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -335,6 +335,7 @@ static QEMUMachine pc_i440fx_machine_v1_5 = {
     .alias = "pc",
     .desc = "Standard PC (i440FX + PIIX, 1996)",
     .init = pc_init_pci,
+    .hot_add_cpu = pc_hot_add_cpu,
     .max_cpus = 255,
     .is_default = 1,
     DEFAULT_MACHINE_OPTIONS,
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index f46295b..52511e2 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -220,6 +220,7 @@ static QEMUMachine pc_q35_machine_v1_5 = {
     .alias = "q35",
     .desc = "Standard PC (Q35 + ICH9, 2009)",
     .init = pc_q35_init,
+    .hot_add_cpu = pc_hot_add_cpu,
     .max_cpus = 255,
     DEFAULT_MACHINE_OPTIONS,
 };
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index d0bc972..41869e5 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -79,6 +79,7 @@ void pc_register_ferr_irq(qemu_irq irq);
 void pc_acpi_smi_interrupt(void *opaque, int irq, int level);
 
 void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge);
+void pc_hot_add_cpu(const int64_t id, Error **errp);
 void pc_acpi_init(const char *default_dsdt);
 void *pc_memory_init(MemoryRegion *system_memory,
                     const char *kernel_filename,
commit 69ca3ea5e192251f27510554611bcff6f036a00b
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Tue Apr 30 15:41:25 2013 +0200

    QMP: Add cpu-add command
    
    Adds "cpu-add id=xxx" QMP command.
    
    cpu-add's "id" argument is a CPU number in a range [0..max-cpus)
    
    Example QMP command:
     -> { "execute": "cpu-add", "arguments": { "id": 2 } }
     <- { "return": {} }
    
    Signed-off-by: Igor Mammedov <imammedo at redhat.com>
    Acked-by: Luiz Capitulino <lcapitulino at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Eduardo Habkost <ehabkost at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/qapi-schema.json b/qapi-schema.json
index 65be8f4..7797400 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1390,6 +1390,19 @@
 { 'command': 'cpu', 'data': {'index': 'int'} }
 
 ##
+# @cpu-add
+#
+# Adds CPU with specified ID
+#
+# @id: ID of CPU to be created, valid values [0..max_cpus)
+#
+# Returns: Nothing on success
+#
+# Since 1.5
+##
+{ 'command': 'cpu-add', 'data': {'id': 'int'} }
+
+##
 # @memsave:
 #
 # Save a portion of guest memory to a file.
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 0e89132..ed99eb8 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -385,6 +385,29 @@ Note: CPUs' indexes are obtained with the 'query-cpus' command.
 EQMP
 
     {
+        .name       = "cpu-add",
+        .args_type  = "id:i",
+        .mhandler.cmd_new = qmp_marshal_input_cpu_add,
+    },
+
+SQMP
+cpu-add
+-------
+
+Adds virtual cpu
+
+Arguments:
+
+- "id": cpu id (json-int)
+
+Example:
+
+-> { "execute": "cpu-add", "arguments": { "id": 2 } }
+<- { "return": {} }
+
+EQMP
+
+    {
         .name       = "memsave",
         .args_type  = "val:l,size:i,filename:s,cpu:i?",
         .mhandler.cmd_new = qmp_marshal_input_memsave,
diff --git a/qmp.c b/qmp.c
index 4676993..4c149b3 100644
--- a/qmp.c
+++ b/qmp.c
@@ -24,6 +24,7 @@
 #include "hw/qdev.h"
 #include "sysemu/blockdev.h"
 #include "qom/qom-qobject.h"
+#include "hw/boards.h"
 
 NameInfo *qmp_query_name(Error **errp)
 {
@@ -108,6 +109,15 @@ void qmp_cpu(int64_t index, Error **errp)
     /* Just do nothing */
 }
 
+void qmp_cpu_add(int64_t id, Error **errp)
+{
+    if (current_machine->hot_add_cpu) {
+        current_machine->hot_add_cpu(id, errp);
+    } else {
+        error_setg(errp, "Not supported");
+    }
+}
+
 #ifndef CONFIG_VNC
 /* If VNC support is enabled, the "true" query-vnc command is
    defined in the VNC subsystem */
commit b4fc7b4326112538e0dbdc7fd019652ba8cc3281
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Tue Apr 30 15:41:24 2013 +0200

    Add hot_add_cpu hook to QEMUMachine
    
    Hook should be set by machines that implement CPU hot-add
    via cpu-add QMP command.
    
    Signed-off-by: Igor Mammedov <imammedo 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/hw/boards.h b/include/hw/boards.h
index 425bdc7..fb7c6f1 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -22,12 +22,15 @@ typedef void QEMUMachineInitFunc(QEMUMachineInitArgs *args);
 
 typedef void QEMUMachineResetFunc(void);
 
+typedef void QEMUMachineHotAddCPUFunc(const int64_t id, Error **errp);
+
 typedef struct QEMUMachine {
     const char *name;
     const char *alias;
     const char *desc;
     QEMUMachineInitFunc *init;
     QEMUMachineResetFunc *reset;
+    QEMUMachineHotAddCPUFunc *hot_add_cpu;
     BlockInterfaceType block_default_type;
     int max_cpus;
     unsigned int no_serial:1,
commit 53a89e262bd3e97b2da3afec0a60e5466770ae8c
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Mon Apr 29 19:03:01 2013 +0200

    target-i386: Move APIC to ICC bus
    
    It allows APIC to be hotplugged.
    
     * map APIC's mmio at board level if it is present
     * do not register mmio region for each APIC, since
       only one is used/mapped
    
    Signed-off-by: Igor Mammedov <imammedo at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/cpu/icc_bus.c b/hw/cpu/icc_bus.c
index 3ac8eeb..73a1dc9 100644
--- a/hw/cpu/icc_bus.c
+++ b/hw/cpu/icc_bus.c
@@ -80,6 +80,7 @@ typedef struct ICCBridgeState {
     /*< public >*/
 
     ICCBus icc_bus;
+    MemoryRegion apic_container;
 } ICCBridgeState;
 
 #define ICC_BRIGDE(obj) OBJECT_CHECK(ICCBridgeState, (obj), TYPE_ICC_BRIDGE)
@@ -87,8 +88,17 @@ typedef struct ICCBridgeState {
 static void icc_bridge_init(Object *obj)
 {
     ICCBridgeState *s = ICC_BRIGDE(obj);
+    SysBusDevice *sb = SYS_BUS_DEVICE(obj);
 
     qbus_create_inplace(&s->icc_bus, TYPE_ICC_BUS, DEVICE(s), "icc");
+
+    /* Do not change order of registering regions,
+     * APIC must be first registered region, board maps it by 0 index
+     */
+    memory_region_init(&s->apic_container, "icc-apic-container",
+                       APIC_SPACE_SIZE);
+    sysbus_init_mmio(sb, &s->apic_container);
+    s->icc_bus.apic_address_space = &s->apic_container;
 }
 
 static const TypeInfo icc_bridge_info = {
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index c4c4e35..28f958d 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -53,6 +53,7 @@
 #include "qemu/bitmap.h"
 #include "qemu/config-file.h"
 #include "hw/acpi/acpi.h"
+#include "hw/cpu/icc_bus.h"
 
 /* debug PC/ISA interrupts */
 //#define DEBUG_IRQ
@@ -921,6 +922,7 @@ static X86CPU *pc_new_cpu(const char *cpu_model, int64_t apic_id,
 void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge)
 {
     int i;
+    X86CPU *cpu = NULL;
     Error *error = NULL;
 
     /* init CPUs */
@@ -933,14 +935,21 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge)
     }
 
     for (i = 0; i < smp_cpus; i++) {
-        pc_new_cpu(cpu_model, x86_cpu_apic_id_from_index(i),
-                   icc_bridge, &error);
+        cpu = pc_new_cpu(cpu_model, x86_cpu_apic_id_from_index(i),
+                         icc_bridge, &error);
         if (error) {
             fprintf(stderr, "%s\n", error_get_pretty(error));
             error_free(error);
             exit(1);
         }
     }
+
+    /* map APIC MMIO area if CPU has APIC */
+    if (cpu && cpu->env.apic_state) {
+        /* XXX: what if the base changes? */
+        sysbus_mmio_map_overlap(SYS_BUS_DEVICE(icc_bridge), 0,
+                                APIC_DEFAULT_ADDRESS, 0x1000);
+    }
 }
 
 void pc_acpi_init(const char *default_dsdt)
diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c
index e0ae07a..b03e904 100644
--- a/hw/intc/apic_common.c
+++ b/hw/intc/apic_common.c
@@ -21,6 +21,8 @@
 #include "hw/i386/apic_internal.h"
 #include "trace.h"
 #include "sysemu/kvm.h"
+#include "hw/qdev.h"
+#include "hw/sysbus.h"
 
 static int apic_irq_delivered;
 bool apic_report_tpr_access;
@@ -282,12 +284,13 @@ static int apic_load_old(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static int apic_init_common(SysBusDevice *dev)
+static int apic_init_common(ICCDevice *dev)
 {
     APICCommonState *s = APIC_COMMON(dev);
     APICCommonClass *info;
     static DeviceState *vapic;
     static int apic_no;
+    static bool mmio_registered;
 
     if (apic_no >= MAX_APICS) {
         return -1;
@@ -296,8 +299,11 @@ static int apic_init_common(SysBusDevice *dev)
 
     info = APIC_COMMON_GET_CLASS(s);
     info->init(s);
-
-    sysbus_init_mmio(dev, &s->io_memory);
+    if (!mmio_registered) {
+        ICCBus *b = ICC_BUS(qdev_get_parent_bus(DEVICE(dev)));
+        memory_region_add_subregion(b->apic_address_space, 0, &s->io_memory);
+        mmio_registered = true;
+    }
 
     /* Note: We need at least 1M to map the VAPIC option ROM */
     if (!vapic && s->vapic_control & VAPIC_ENABLE_MASK &&
@@ -375,19 +381,19 @@ static Property apic_properties_common[] = {
 
 static void apic_common_class_init(ObjectClass *klass, void *data)
 {
-    SysBusDeviceClass *sc = SYS_BUS_DEVICE_CLASS(klass);
+    ICCDeviceClass *idc = ICC_DEVICE_CLASS(klass);
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->vmsd = &vmstate_apic_common;
     dc->reset = apic_reset_common;
     dc->no_user = 1;
     dc->props = apic_properties_common;
-    sc->init = apic_init_common;
+    idc->init = apic_init_common;
 }
 
 static const TypeInfo apic_common_type = {
     .name = TYPE_APIC_COMMON,
-    .parent = TYPE_SYS_BUS_DEVICE,
+    .parent = TYPE_ICC_DEVICE,
     .instance_size = sizeof(APICCommonState),
     .class_size = sizeof(APICCommonClass),
     .class_init = apic_common_class_init,
diff --git a/include/hw/cpu/icc_bus.h b/include/hw/cpu/icc_bus.h
index d728a7d..b550070 100644
--- a/include/hw/cpu/icc_bus.h
+++ b/include/hw/cpu/icc_bus.h
@@ -22,6 +22,7 @@
 #ifndef ICC_BUS_H
 #define ICC_BUS_H
 
+#include "exec/memory.h"
 #include "hw/qdev-core.h"
 
 #define TYPE_ICC_BUS "icc-bus"
@@ -37,6 +38,8 @@ typedef struct ICCBus {
     /*< private >*/
     BusState parent_obj;
     /*< public >*/
+
+    MemoryRegion *apic_address_space;
 } ICCBus;
 
 #define ICC_BUS(obj) OBJECT_CHECK(ICCBus, (obj), TYPE_ICC_BUS)
diff --git a/include/hw/i386/apic_internal.h b/include/hw/i386/apic_internal.h
index aac6290..1b0a7fb 100644
--- a/include/hw/i386/apic_internal.h
+++ b/include/hw/i386/apic_internal.h
@@ -21,7 +21,7 @@
 #define QEMU_APIC_INTERNAL_H
 
 #include "exec/memory.h"
-#include "hw/sysbus.h"
+#include "hw/cpu/icc_bus.h"
 #include "qemu/timer.h"
 
 /* APIC Local Vector Table */
@@ -78,7 +78,7 @@ typedef struct APICCommonState APICCommonState;
 
 typedef struct APICCommonClass
 {
-    SysBusDeviceClass parent_class;
+    ICCDeviceClass parent_class;
 
     void (*init)(APICCommonState *s);
     void (*set_base)(APICCommonState *s, uint64_t val);
@@ -92,7 +92,7 @@ typedef struct APICCommonClass
 } APICCommonClass;
 
 struct APICCommonState {
-    SysBusDevice busdev;
+    ICCDevice busdev;
 
     MemoryRegion io_memory;
     X86CPU *cpu;
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index a165bcf..bba41fe 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -41,10 +41,10 @@
 #endif
 
 #include "sysemu/sysemu.h"
+#include "hw/qdev-properties.h"
 #include "hw/cpu/icc_bus.h"
 #ifndef CONFIG_USER_ONLY
 #include "hw/xen/xen.h"
-#include "hw/sysbus.h"
 #include "hw/i386/apic_internal.h"
 #endif
 
@@ -2131,6 +2131,7 @@ static void mce_init(X86CPU *cpu)
 static void x86_cpu_apic_create(X86CPU *cpu, Error **errp)
 {
     CPUX86State *env = &cpu->env;
+    DeviceState *dev = DEVICE(cpu);
     APICCommonState *apic;
     const char *apic_type = "apic";
 
@@ -2140,7 +2141,7 @@ static void x86_cpu_apic_create(X86CPU *cpu, Error **errp)
         apic_type = "xen-apic";
     }
 
-    env->apic_state = qdev_try_create(NULL, apic_type);
+    env->apic_state = qdev_try_create(qdev_get_parent_bus(dev), apic_type);
     if (env->apic_state == NULL) {
         error_setg(errp, "APIC device '%s' could not be created", apic_type);
         return;
@@ -2157,7 +2158,6 @@ static void x86_cpu_apic_create(X86CPU *cpu, Error **errp)
 static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)
 {
     CPUX86State *env = &cpu->env;
-    static int apic_mapped;
 
     if (env->apic_state == NULL) {
         return;
@@ -2168,16 +2168,6 @@ static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)
                    object_get_typename(OBJECT(env->apic_state)));
         return;
     }
-
-    /* XXX: mapping more APICs at the same memory location */
-    if (apic_mapped == 0) {
-        /* 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_overlap(SYS_BUS_DEVICE(env->apic_state), 0,
-                                APIC_DEFAULT_ADDRESS, 0x1000);
-        apic_mapped = 1;
-    }
 }
 #else
 static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)
commit 62fc403f11523169eb4264de31279745f48e3ecc
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Mon Apr 29 18:54:13 2013 +0200

    target-i386: Attach ICC bus to CPU on its creation
    
    X86CPU should have parent bus so it could provide bus for child APIC.
    
    Signed-off-by: Igor Mammedov <imammedo at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 6568173..c4c4e35 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -894,12 +894,13 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
     }
 }
 
-static X86CPU *pc_new_cpu(const char *cpu_model, int64_t apic_id, Error **errp)
+static X86CPU *pc_new_cpu(const char *cpu_model, int64_t apic_id,
+                          DeviceState *icc_bridge, Error **errp)
 {
     X86CPU *cpu;
     Error *local_err = NULL;
 
-    cpu = cpu_x86_create(cpu_model, errp);
+    cpu = cpu_x86_create(cpu_model, icc_bridge, errp);
     if (!cpu) {
         return cpu;
     }
@@ -917,7 +918,7 @@ static X86CPU *pc_new_cpu(const char *cpu_model, int64_t apic_id, Error **errp)
     return cpu;
 }
 
-void pc_cpus_init(const char *cpu_model)
+void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge)
 {
     int i;
     Error *error = NULL;
@@ -932,7 +933,8 @@ void pc_cpus_init(const char *cpu_model)
     }
 
     for (i = 0; i < smp_cpus; i++) {
-        pc_new_cpu(cpu_model, x86_cpu_apic_id_from_index(i), &error);
+        pc_new_cpu(cpu_model, x86_cpu_apic_id_from_index(i),
+                   icc_bridge, &error);
         if (error) {
             fprintf(stderr, "%s\n", error_get_pretty(error));
             error_free(error);
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 0ce3fc2..251e18f 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -95,7 +95,7 @@ static void pc_init1(MemoryRegion *system_memory,
     object_property_add_child(qdev_get_machine(), "icc-bridge",
                               OBJECT(icc_bridge), NULL);
 
-    pc_cpus_init(cpu_model);
+    pc_cpus_init(cpu_model, icc_bridge);
     pc_acpi_init("acpi-dsdt.aml");
 
     if (kvmclock_enabled) {
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index a6ba809..f46295b 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -82,7 +82,7 @@ static void pc_q35_init(QEMUMachineInitArgs *args)
     object_property_add_child(qdev_get_machine(), "icc-bridge",
                               OBJECT(icc_bridge), NULL);
 
-    pc_cpus_init(cpu_model);
+    pc_cpus_init(cpu_model, icc_bridge);
     pc_acpi_init("q35-acpi-dsdt.aml");
 
     kvmclock_create();
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index dd6bc24..d0bc972 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -78,7 +78,7 @@ extern int fd_bootchk;
 void pc_register_ferr_irq(qemu_irq irq);
 void pc_acpi_smi_interrupt(void *opaque, int irq, int level);
 
-void pc_cpus_init(const char *cpu_model);
+void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge);
 void pc_acpi_init(const char *default_dsdt);
 void *pc_memory_init(MemoryRegion *system_memory,
                     const char *kernel_filename,
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 40d51be..a165bcf 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -41,6 +41,7 @@
 #endif
 
 #include "sysemu/sysemu.h"
+#include "hw/cpu/icc_bus.h"
 #ifndef CONFIG_USER_ONLY
 #include "hw/xen/xen.h"
 #include "hw/sysbus.h"
@@ -1618,7 +1619,8 @@ static void cpu_x86_register(X86CPU *cpu, const char *name, Error **errp)
     object_property_set_str(OBJECT(cpu), def->model_id, "model-id", errp);
 }
 
-X86CPU *cpu_x86_create(const char *cpu_model, Error **errp)
+X86CPU *cpu_x86_create(const char *cpu_model, DeviceState *icc_bridge,
+                       Error **errp)
 {
     X86CPU *cpu = NULL;
     CPUX86State *env;
@@ -1635,6 +1637,14 @@ X86CPU *cpu_x86_create(const char *cpu_model, Error **errp)
     features = model_pieces[1];
 
     cpu = X86_CPU(object_new(TYPE_X86_CPU));
+#ifndef CONFIG_USER_ONLY
+    if (icc_bridge == NULL) {
+        error_setg(&error, "Invalid icc-bridge value");
+        goto out;
+    }
+    qdev_set_parent_bus(DEVICE(cpu), qdev_get_child_bus(icc_bridge, "icc"));
+    object_unref(OBJECT(cpu));
+#endif
     env = &cpu->env;
     env->cpu_model_str = cpu_model;
 
@@ -1659,7 +1669,7 @@ X86CPU *cpu_x86_init(const char *cpu_model)
     Error *error = NULL;
     X86CPU *cpu;
 
-    cpu = cpu_x86_create(cpu_model, &error);
+    cpu = cpu_x86_create(cpu_model, NULL, &error);
     if (error) {
         goto out;
     }
@@ -2346,6 +2356,7 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
 
     xcc->parent_realize = dc->realize;
     dc->realize = x86_cpu_realizefn;
+    dc->bus_type = TYPE_ICC_BUS;
 
     xcc->parent_reset = cc->reset;
     cc->reset = x86_cpu_reset;
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index ab151d5..f193752 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -897,7 +897,8 @@ typedef struct CPUX86State {
 #include "cpu-qom.h"
 
 X86CPU *cpu_x86_init(const char *cpu_model);
-X86CPU *cpu_x86_create(const char *cpu_model, Error **errp);
+X86CPU *cpu_x86_create(const char *cpu_model, DeviceState *icc_bridge,
+                       Error **errp);
 int cpu_x86_exec(CPUX86State *s);
 void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf);
 void x86_cpudef_setup(void);
commit f0513d2c0156799e0c75a108ab9a049eea4f9607
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Mon Apr 29 17:02:50 2013 +0200

    target-i386: Introduce ICC bus/device/bridge
    
    Provides a hotpluggable bus for APIC and CPU.
    
    * icc-bridge will serve as a parent for icc-bus and provide
      mmio mapping services to child icc-devices.
    * icc-device will replace SysBusDevice as a parent of APIC
      and IOAPIC devices.
    
    Signed-off-by: Igor Mammedov <imammedo at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/MAINTAINERS b/MAINTAINERS
index 4dfd8bf..be02724 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -644,6 +644,12 @@ F: qom/cpu.c
 F: include/qemu/cpu.h
 F: target-i386/cpu.c
 
+ICC Bus
+M: Igor Mammedov <imammedo at redhat.com>
+S: Supported
+F: include/hw/cpu/icc_bus.h
+F: hw/cpu/icc_bus.c
+
 Device Tree
 M: Peter Crosthwaite <peter.crosthwaite at petalogix.com>
 M: Alexander Graf <agraf at suse.de>
diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
index 4e30505..03deca2 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -44,4 +44,5 @@ CONFIG_LPC_ICH9=y
 CONFIG_PCI_Q35=y
 CONFIG_APIC=y
 CONFIG_IOAPIC=y
+CONFIG_ICC_BUS=y
 CONFIG_PVPANIC=y
diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak
index 5af8fd3..599b630 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -44,4 +44,5 @@ CONFIG_LPC_ICH9=y
 CONFIG_PCI_Q35=y
 CONFIG_APIC=y
 CONFIG_IOAPIC=y
+CONFIG_ICC_BUS=y
 CONFIG_PVPANIC=y
diff --git a/hw/cpu/Makefile.objs b/hw/cpu/Makefile.objs
index a49ca04..4461ece 100644
--- a/hw/cpu/Makefile.objs
+++ b/hw/cpu/Makefile.objs
@@ -1,4 +1,5 @@
 obj-$(CONFIG_ARM11MPCORE) += arm11mpcore.o
 obj-$(CONFIG_ARM9MPCORE) += a9mpcore.o
 obj-$(CONFIG_ARM15MPCORE) += a15mpcore.o
+obj-$(CONFIG_ICC_BUS) += icc_bus.o
 
diff --git a/hw/cpu/icc_bus.c b/hw/cpu/icc_bus.c
new file mode 100644
index 0000000..3ac8eeb
--- /dev/null
+++ b/hw/cpu/icc_bus.c
@@ -0,0 +1,109 @@
+/* icc_bus.c
+ * emulate x86 ICC (Interrupt Controller Communications) bus
+ *
+ * Copyright (c) 2013 Red Hat, Inc
+ *
+ * Authors:
+ *     Igor Mammedov <imammedo at redhat.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/cpu/icc_bus.h"
+#include "hw/sysbus.h"
+
+/* icc-bridge implementation */
+
+static void icc_bus_init(Object *obj)
+{
+    BusState *b = BUS(obj);
+
+    b->allow_hotplug = true;
+}
+
+static const TypeInfo icc_bus_info = {
+    .name = TYPE_ICC_BUS,
+    .parent = TYPE_BUS,
+    .instance_size = sizeof(ICCBus),
+    .instance_init = icc_bus_init,
+};
+
+
+/* icc-device implementation */
+
+static void icc_device_realize(DeviceState *dev, Error **errp)
+{
+    ICCDevice *id = ICC_DEVICE(dev);
+    ICCDeviceClass *idc = ICC_DEVICE_GET_CLASS(id);
+
+    if (idc->init) {
+        if (idc->init(id) < 0) {
+            error_setg(errp, "%s initialization failed.",
+                       object_get_typename(OBJECT(dev)));
+        }
+    }
+}
+
+static void icc_device_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+
+    dc->realize = icc_device_realize;
+    dc->bus_type = TYPE_ICC_BUS;
+}
+
+static const TypeInfo icc_device_info = {
+    .name = TYPE_ICC_DEVICE,
+    .parent = TYPE_DEVICE,
+    .abstract = true,
+    .instance_size = sizeof(ICCDevice),
+    .class_size = sizeof(ICCDeviceClass),
+    .class_init = icc_device_class_init,
+};
+
+
+/*  icc-bridge implementation */
+
+typedef struct ICCBridgeState {
+    /*< private >*/
+    SysBusDevice parent_obj;
+    /*< public >*/
+
+    ICCBus icc_bus;
+} ICCBridgeState;
+
+#define ICC_BRIGDE(obj) OBJECT_CHECK(ICCBridgeState, (obj), TYPE_ICC_BRIDGE)
+
+static void icc_bridge_init(Object *obj)
+{
+    ICCBridgeState *s = ICC_BRIGDE(obj);
+
+    qbus_create_inplace(&s->icc_bus, TYPE_ICC_BUS, DEVICE(s), "icc");
+}
+
+static const TypeInfo icc_bridge_info = {
+    .name  = TYPE_ICC_BRIDGE,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_init  = icc_bridge_init,
+    .instance_size  = sizeof(ICCBridgeState),
+};
+
+
+static void icc_bus_register_types(void)
+{
+    type_register_static(&icc_bus_info);
+    type_register_static(&icc_device_info);
+    type_register_static(&icc_bridge_info);
+}
+
+type_init(icc_bus_register_types)
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 852d63b..0ce3fc2 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -37,6 +37,7 @@
 #include "hw/kvm/clock.h"
 #include "sysemu/sysemu.h"
 #include "hw/sysbus.h"
+#include "hw/cpu/icc_bus.h"
 #include "sysemu/arch_init.h"
 #include "sysemu/blockdev.h"
 #include "hw/i2c/smbus.h"
@@ -87,8 +88,13 @@ static void pc_init1(MemoryRegion *system_memory,
     MemoryRegion *ram_memory;
     MemoryRegion *pci_memory;
     MemoryRegion *rom_memory;
+    DeviceState *icc_bridge;
     void *fw_cfg = NULL;
 
+    icc_bridge = qdev_create(NULL, TYPE_ICC_BRIDGE);
+    object_property_add_child(qdev_get_machine(), "icc-bridge",
+                              OBJECT(icc_bridge), NULL);
+
     pc_cpus_init(cpu_model);
     pc_acpi_init("acpi-dsdt.aml");
 
@@ -163,6 +169,7 @@ static void pc_init1(MemoryRegion *system_memory,
     if (pci_enabled) {
         ioapic_init_gsi(gsi_state, "i440fx");
     }
+    qdev_init_nofail(icc_bridge);
 
     pc_register_ferr_irq(gsi[13]);
 
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index d094041..a6ba809 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -41,6 +41,7 @@
 #include "hw/ide/pci.h"
 #include "hw/ide/ahci.h"
 #include "hw/usb.h"
+#include "hw/cpu/icc_bus.h"
 
 /* ICH9 AHCI has 6 ports */
 #define MAX_SATA_PORTS     6
@@ -75,6 +76,11 @@ static void pc_q35_init(QEMUMachineInitArgs *args)
     int i;
     ICH9LPCState *ich9_lpc;
     PCIDevice *ahci;
+    DeviceState *icc_bridge;
+
+    icc_bridge = qdev_create(NULL, TYPE_ICC_BRIDGE);
+    object_property_add_child(qdev_get_machine(), "icc-bridge",
+                              OBJECT(icc_bridge), NULL);
 
     pc_cpus_init(cpu_model);
     pc_acpi_init("q35-acpi-dsdt.aml");
@@ -158,6 +164,7 @@ static void pc_q35_init(QEMUMachineInitArgs *args)
     if (pci_enabled) {
         ioapic_init_gsi(gsi_state, NULL);
     }
+    qdev_init_nofail(icc_bridge);
 
     pc_register_ferr_irq(gsi[13]);
 
diff --git a/include/hw/cpu/icc_bus.h b/include/hw/cpu/icc_bus.h
new file mode 100644
index 0000000..d728a7d
--- /dev/null
+++ b/include/hw/cpu/icc_bus.h
@@ -0,0 +1,79 @@
+/* icc_bus.h
+ * emulate x86 ICC (Interrupt Controller Communications) bus
+ *
+ * Copyright (c) 2013 Red Hat, Inc
+ *
+ * Authors:
+ *     Igor Mammedov <imammedo at redhat.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 ICC_BUS_H
+#define ICC_BUS_H
+
+#include "hw/qdev-core.h"
+
+#define TYPE_ICC_BUS "icc-bus"
+
+#ifndef CONFIG_USER_ONLY
+
+/**
+ * ICCBus:
+ *
+ * ICC bus
+ */
+typedef struct ICCBus {
+    /*< private >*/
+    BusState parent_obj;
+    /*< public >*/
+} ICCBus;
+
+#define ICC_BUS(obj) OBJECT_CHECK(ICCBus, (obj), TYPE_ICC_BUS)
+
+/**
+ * ICCDevice:
+ *
+ * ICC device
+ */
+typedef struct ICCDevice {
+    /*< private >*/
+    DeviceState qdev;
+    /*< public >*/
+} ICCDevice;
+
+/**
+ * ICCDeviceClass:
+ * @init: Initialization callback for derived classes.
+ *
+ * ICC device class
+ */
+typedef struct ICCDeviceClass {
+    /*< private >*/
+    DeviceClass parent_class;
+    /*< public >*/
+
+    int (*init)(ICCDevice *dev); /* TODO replace with QOM realize */
+} ICCDeviceClass;
+
+#define TYPE_ICC_DEVICE "icc-device"
+#define ICC_DEVICE(obj) OBJECT_CHECK(ICCDevice, (obj), TYPE_ICC_DEVICE)
+#define ICC_DEVICE_CLASS(klass) \
+     OBJECT_CLASS_CHECK(ICCDeviceClass, (klass), TYPE_ICC_DEVICE)
+#define ICC_DEVICE_GET_CLASS(obj) \
+     OBJECT_GET_CLASS(ICCDeviceClass, (obj), TYPE_ICC_DEVICE)
+
+#define TYPE_ICC_BRIDGE "icc-bridge"
+
+#endif /* CONFIG_USER_ONLY */
+#endif
commit c72bf468259935a80ea185f2cbe807c3da9c1bbd
Author: Jens Freimann <jfrei at linux.vnet.ibm.com>
Date:   Fri Apr 19 16:45:06 2013 +0200

    cpu: Move cpu_write_elfXX_note() functions to CPUState
    
    Convert cpu_write_elfXX_note() functions to CPUClass methods and pass
    CPUState as argument. Update target-i386 accordingly.
    
    Signed-off-by: Jens Freimann <jfrei at linux.vnet.ibm.com>
    [AF: Retain stubs as CPUClass' default method implementation; style changes]
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/dump-stub.c b/dump-stub.c
index a9d0b3c..b3f42cb 100644
--- a/dump-stub.c
+++ b/dump-stub.c
@@ -24,34 +24,6 @@ void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin,
     error_set(errp, QERR_UNSUPPORTED);
 }
 
-int cpu_write_elf64_note(write_core_dump_function f,
-                                       CPUArchState *env, int cpuid,
-                                       void *opaque)
-{
-    return -1;
-}
-
-int cpu_write_elf32_note(write_core_dump_function f,
-                                       CPUArchState *env, int cpuid,
-                                       void *opaque)
-{
-    return -1;
-}
-
-int cpu_write_elf64_qemunote(write_core_dump_function f,
-                                           CPUArchState *env,
-                                           void *opaque)
-{
-    return -1;
-}
-
-int cpu_write_elf32_qemunote(write_core_dump_function f,
-                                           CPUArchState *env,
-                                           void *opaque)
-{
-    return -1;
-}
-
 int cpu_get_dump_info(ArchDumpInfo *info)
 {
     return -1;
diff --git a/dump.c b/dump.c
index b34f143..c0d3da5 100644
--- a/dump.c
+++ b/dump.c
@@ -282,7 +282,7 @@ static int write_elf64_notes(DumpState *s)
     for (env = first_cpu; env != NULL; env = env->next_cpu) {
         cpu = ENV_GET_CPU(env);
         id = cpu_index(cpu);
-        ret = cpu_write_elf64_note(fd_write_vmcore, env, id, s);
+        ret = cpu_write_elf64_note(fd_write_vmcore, cpu, id, s);
         if (ret < 0) {
             dump_error(s, "dump: failed to write elf notes.\n");
             return -1;
@@ -290,7 +290,7 @@ static int write_elf64_notes(DumpState *s)
     }
 
     for (env = first_cpu; env != NULL; env = env->next_cpu) {
-        ret = cpu_write_elf64_qemunote(fd_write_vmcore, env, s);
+        ret = cpu_write_elf64_qemunote(fd_write_vmcore, cpu, s);
         if (ret < 0) {
             dump_error(s, "dump: failed to write CPU status.\n");
             return -1;
@@ -334,7 +334,7 @@ static int write_elf32_notes(DumpState *s)
     for (env = first_cpu; env != NULL; env = env->next_cpu) {
         cpu = ENV_GET_CPU(env);
         id = cpu_index(cpu);
-        ret = cpu_write_elf32_note(fd_write_vmcore, env, id, s);
+        ret = cpu_write_elf32_note(fd_write_vmcore, cpu, id, s);
         if (ret < 0) {
             dump_error(s, "dump: failed to write elf notes.\n");
             return -1;
@@ -342,7 +342,7 @@ static int write_elf32_notes(DumpState *s)
     }
 
     for (env = first_cpu; env != NULL; env = env->next_cpu) {
-        ret = cpu_write_elf32_qemunote(fd_write_vmcore, env, s);
+        ret = cpu_write_elf32_qemunote(fd_write_vmcore, cpu, s);
         if (ret < 0) {
             dump_error(s, "dump: failed to write CPU status.\n");
             return -1;
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index e54579b..7cd9442 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -24,6 +24,8 @@
 #include "hw/qdev-core.h"
 #include "qemu/thread.h"
 
+typedef int (*WriteCoreDumpFunction)(void *buf, size_t size, void *opaque);
+
 /**
  * SECTION:cpu
  * @section_id: QEMU-cpu
@@ -62,6 +64,14 @@ typedef struct CPUClass {
     int64_t (*get_arch_id)(CPUState *cpu);
 
     const struct VMStateDescription *vmsd;
+    int (*write_elf64_note)(WriteCoreDumpFunction f, CPUState *cpu,
+                            int cpuid, void *opaque);
+    int (*write_elf64_qemunote)(WriteCoreDumpFunction f, CPUState *cpu,
+                                void *opaque);
+    int (*write_elf32_note)(WriteCoreDumpFunction f, CPUState *cpu,
+                            int cpuid, void *opaque);
+    int (*write_elf32_qemunote)(WriteCoreDumpFunction f, CPUState *cpu,
+                                void *opaque);
 } CPUClass;
 
 struct KVMState;
@@ -127,6 +137,45 @@ struct CPUState {
     uint32_t halted; /* used by alpha, cris, ppc TCG */
 };
 
+/**
+ * cpu_write_elf64_note:
+ * @f: pointer to a function that writes memory to a file
+ * @cpu: The CPU whose memory is to be dumped
+ * @cpuid: ID number of the CPU
+ * @opaque: pointer to the CPUState struct
+ */
+int cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cpu,
+                         int cpuid, void *opaque);
+
+/**
+ * cpu_write_elf64_qemunote:
+ * @f: pointer to a function that writes memory to a file
+ * @cpu: The CPU whose memory is to be dumped
+ * @cpuid: ID number of the CPU
+ * @opaque: pointer to the CPUState struct
+ */
+int cpu_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
+                             void *opaque);
+
+/**
+ * cpu_write_elf32_note:
+ * @f: pointer to a function that writes memory to a file
+ * @cpu: The CPU whose memory is to be dumped
+ * @cpuid: ID number of the CPU
+ * @opaque: pointer to the CPUState struct
+ */
+int cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cpu,
+                         int cpuid, void *opaque);
+
+/**
+ * cpu_write_elf32_qemunote:
+ * @f: pointer to a function that writes memory to a file
+ * @cpu: The CPU whose memory is to be dumped
+ * @cpuid: ID number of the CPU
+ * @opaque: pointer to the CPUState struct
+ */
+int cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
+                             void *opaque);
 
 /**
  * cpu_reset:
diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h
index e25b7cf..b8c770f 100644
--- a/include/sysemu/dump.h
+++ b/include/sysemu/dump.h
@@ -20,15 +20,6 @@ typedef struct ArchDumpInfo {
     int d_class;    /* ELFCLASS32 or ELFCLASS64 */
 } ArchDumpInfo;
 
-typedef int (*write_core_dump_function)(void *buf, size_t size, void *opaque);
-int cpu_write_elf64_note(write_core_dump_function f, CPUArchState *env,
-                                                  int cpuid, void *opaque);
-int cpu_write_elf32_note(write_core_dump_function f, CPUArchState *env,
-                                                  int cpuid, void *opaque);
-int cpu_write_elf64_qemunote(write_core_dump_function f, CPUArchState *env,
-                                                          void *opaque);
-int cpu_write_elf32_qemunote(write_core_dump_function f, CPUArchState *env,
-                                                          void *opaque);
 int cpu_get_dump_info(ArchDumpInfo *info);
 ssize_t cpu_get_note_size(int class, int machine, int nr_cpus);
 
diff --git a/qom/cpu.c b/qom/cpu.c
index 3dc8208..04aefbb 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -64,6 +64,65 @@ void cpu_reset_interrupt(CPUState *cpu, int mask)
     cpu->interrupt_request &= ~mask;
 }
 
+int cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
+                             void *opaque)
+{
+    CPUClass *cc = CPU_GET_CLASS(cpu);
+
+    return (*cc->write_elf32_qemunote)(f, cpu, opaque);
+}
+
+static int cpu_common_write_elf32_qemunote(WriteCoreDumpFunction f,
+                                           CPUState *cpu, void *opaque)
+{
+    return -1;
+}
+
+int cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cpu,
+                         int cpuid, void *opaque)
+{
+    CPUClass *cc = CPU_GET_CLASS(cpu);
+
+    return (*cc->write_elf32_note)(f, cpu, cpuid, opaque);
+}
+
+static int cpu_common_write_elf32_note(WriteCoreDumpFunction f,
+                                       CPUState *cpu, int cpuid,
+                                       void *opaque)
+{
+    return -1;
+}
+
+int cpu_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
+                             void *opaque)
+{
+    CPUClass *cc = CPU_GET_CLASS(cpu);
+
+    return (*cc->write_elf64_qemunote)(f, cpu, opaque);
+}
+
+static int cpu_common_write_elf64_qemunote(WriteCoreDumpFunction f,
+                                           CPUState *cpu, void *opaque)
+{
+    return -1;
+}
+
+int cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cpu,
+                         int cpuid, void *opaque)
+{
+    CPUClass *cc = CPU_GET_CLASS(cpu);
+
+    return (*cc->write_elf64_note)(f, cpu, cpuid, opaque);
+}
+
+static int cpu_common_write_elf64_note(WriteCoreDumpFunction f,
+                                       CPUState *cpu, int cpuid,
+                                       void *opaque)
+{
+    return -1;
+}
+
+
 void cpu_reset(CPUState *cpu)
 {
     CPUClass *klass = CPU_GET_CLASS(cpu);
@@ -117,6 +176,10 @@ static void cpu_class_init(ObjectClass *klass, void *data)
     k->class_by_name = cpu_common_class_by_name;
     k->reset = cpu_common_reset;
     k->get_arch_id = cpu_common_get_arch_id;
+    k->write_elf32_qemunote = cpu_common_write_elf32_qemunote;
+    k->write_elf32_note = cpu_common_write_elf32_note;
+    k->write_elf64_qemunote = cpu_common_write_elf64_qemunote;
+    k->write_elf64_note = cpu_common_write_elf64_note;
     dc->realize = cpu_common_realizefn;
     dc->no_user = 1;
 }
diff --git a/target-i386/arch_dump.c b/target-i386/arch_dump.c
index 2cd2f7f..83898cd 100644
--- a/target-i386/arch_dump.c
+++ b/target-i386/arch_dump.c
@@ -34,7 +34,7 @@ typedef struct {
     char pad3[8];
 } x86_64_elf_prstatus;
 
-static int x86_64_write_elf64_note(write_core_dump_function f,
+static int x86_64_write_elf64_note(WriteCoreDumpFunction f,
                                    CPUArchState *env, int id,
                                    void *opaque)
 {
@@ -144,7 +144,7 @@ static void x86_fill_elf_prstatus(x86_elf_prstatus *prstatus, CPUArchState *env,
     prstatus->pid = id;
 }
 
-static int x86_write_elf64_note(write_core_dump_function f, CPUArchState *env,
+static int x86_write_elf64_note(WriteCoreDumpFunction f, CPUArchState *env,
                                 int id, void *opaque)
 {
     x86_elf_prstatus prstatus;
@@ -179,18 +179,19 @@ static int x86_write_elf64_note(write_core_dump_function f, CPUArchState *env,
     return 0;
 }
 
-int cpu_write_elf64_note(write_core_dump_function f, CPUArchState *env,
-                         int cpuid, void *opaque)
+int x86_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
+                             int cpuid, void *opaque)
 {
+    X86CPU *cpu = X86_CPU(cs);
     int ret;
 #ifdef TARGET_X86_64
     bool lma = !!(first_cpu->hflags & HF_LMA_MASK);
 
     if (lma) {
-        ret = x86_64_write_elf64_note(f, env, cpuid, opaque);
+        ret = x86_64_write_elf64_note(f, &cpu->env, cpuid, opaque);
     } else {
 #endif
-        ret = x86_write_elf64_note(f, env, cpuid, opaque);
+        ret = x86_write_elf64_note(f, &cpu->env, cpuid, opaque);
 #ifdef TARGET_X86_64
     }
 #endif
@@ -198,9 +199,10 @@ int cpu_write_elf64_note(write_core_dump_function f, CPUArchState *env,
     return ret;
 }
 
-int cpu_write_elf32_note(write_core_dump_function f, CPUArchState *env,
-                         int cpuid, void *opaque)
+int x86_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
+                             int cpuid, void *opaque)
 {
+    X86CPU *cpu = X86_CPU(cs);
     x86_elf_prstatus prstatus;
     Elf32_Nhdr *note;
     char *buf;
@@ -208,7 +210,7 @@ int cpu_write_elf32_note(write_core_dump_function f, CPUArchState *env,
     const char *name = "CORE";
     int ret;
 
-    x86_fill_elf_prstatus(&prstatus, env, cpuid);
+    x86_fill_elf_prstatus(&prstatus, &cpu->env, cpuid);
     descsz = sizeof(x86_elf_prstatus);
     note_size = ((sizeof(Elf32_Nhdr) + 3) / 4 + (name_size + 3) / 4 +
                 (descsz + 3) / 4) * 4;
@@ -317,7 +319,7 @@ static void qemu_get_cpustate(QEMUCPUState *s, CPUArchState *env)
     s->cr[4] = env->cr[4];
 }
 
-static inline int cpu_write_qemu_note(write_core_dump_function f,
+static inline int cpu_write_qemu_note(WriteCoreDumpFunction f,
                                       CPUArchState *env,
                                       void *opaque,
                                       int type)
@@ -370,16 +372,20 @@ static inline int cpu_write_qemu_note(write_core_dump_function f,
     return 0;
 }
 
-int cpu_write_elf64_qemunote(write_core_dump_function f, CPUArchState *env,
-                             void *opaque)
+int x86_cpu_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cs,
+                                 void *opaque)
 {
-    return cpu_write_qemu_note(f, env, opaque, 1);
+    X86CPU *cpu = X86_CPU(cs);
+
+    return cpu_write_qemu_note(f, &cpu->env, opaque, 1);
 }
 
-int cpu_write_elf32_qemunote(write_core_dump_function f, CPUArchState *env,
-                             void *opaque)
+int x86_cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cs,
+                                 void *opaque)
 {
-    return cpu_write_qemu_note(f, env, opaque, 0);
+    X86CPU *cpu = X86_CPU(cs);
+
+    return cpu_write_qemu_note(f, &cpu->env, opaque, 0);
 }
 
 int cpu_get_dump_info(ArchDumpInfo *info)
diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h
index 08f9eb6..f890f1c 100644
--- a/target-i386/cpu-qom.h
+++ b/target-i386/cpu-qom.h
@@ -86,4 +86,13 @@ extern const struct VMStateDescription vmstate_x86_cpu;
  */
 void x86_cpu_do_interrupt(CPUState *cpu);
 
+int x86_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cpu,
+                             int cpuid, void *opaque);
+int x86_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cpu,
+                             int cpuid, void *opaque);
+int x86_cpu_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
+                                 void *opaque);
+int x86_cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
+                                 void *opaque);
+
 #endif
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 0d9493d..40d51be 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -2351,6 +2351,12 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
     cc->reset = x86_cpu_reset;
 
     cc->do_interrupt = x86_cpu_do_interrupt;
+#ifndef CONFIG_USER_ONLY
+    cc->write_elf64_note = x86_cpu_write_elf64_note;
+    cc->write_elf64_qemunote = x86_cpu_write_elf64_qemunote;
+    cc->write_elf32_note = x86_cpu_write_elf32_note;
+    cc->write_elf32_qemunote = x86_cpu_write_elf32_qemunote;
+#endif
     cpu_class_set_vmsd(cc, &vmstate_x86_cpu);
 
     cc->get_arch_id = x86_cpu_get_arch_id;
commit 5f8df3ce6e0a057ec23cea74b6e629e59e085ac4
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Thu Apr 25 16:05:30 2013 +0200

    kvmvapic: Make dependency on sysbus.h explicit
    
    Allows kvmvapic to compile if sysbus.h is removed from apic_internal.h,
    from which it is indirectly included.
    sysbus.h will be removed from apic_internal.h after converting
    APICs to ICCDevice.
    
    Signed-off-by: Igor Mammedov <imammedo at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c
index 3a10c07..5b558aa 100644
--- a/hw/i386/kvmvapic.c
+++ b/hw/i386/kvmvapic.c
@@ -12,6 +12,7 @@
 #include "sysemu/cpus.h"
 #include "sysemu/kvm.h"
 #include "hw/i386/apic_internal.h"
+#include "hw/sysbus.h"
 
 #define VAPIC_IO_PORT           0x7e
 
commit baaeda08ff34ad17150b50a6f52d0faec9f3db36
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Thu Apr 25 16:05:29 2013 +0200

    target-i386: Replace MSI_SPACE_SIZE with APIC_SPACE_SIZE
    
    Put APIC_SPACE_SIZE in a public header so that it can be
    reused elsewhere later.
    
    Signed-off-by: Igor Mammedov <imammedo at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/i386/kvm/apic.c b/hw/i386/kvm/apic.c
index c6ff982..8f80425 100644
--- a/hw/i386/kvm/apic.c
+++ b/hw/i386/kvm/apic.c
@@ -174,7 +174,7 @@ static const MemoryRegionOps kvm_apic_io_ops = {
 static void kvm_apic_init(APICCommonState *s)
 {
     memory_region_init_io(&s->io_memory, &kvm_apic_io_ops, s, "kvm-apic-msi",
-                          MSI_SPACE_SIZE);
+                          APIC_SPACE_SIZE);
 
     if (kvm_has_gsi_routing()) {
         msi_supported = true;
diff --git a/hw/intc/apic.c b/hw/intc/apic.c
index 2d79a9e..756dff0 100644
--- a/hw/intc/apic.c
+++ b/hw/intc/apic.c
@@ -874,7 +874,7 @@ static const MemoryRegionOps apic_io_ops = {
 static void apic_init(APICCommonState *s)
 {
     memory_region_init_io(&s->io_memory, &apic_io_ops, s, "apic-msi",
-                          MSI_SPACE_SIZE);
+                          APIC_SPACE_SIZE);
 
     s->timer = qemu_new_timer_ns(vm_clock, apic_timer, s);
     local_apics[s->idx] = s;
diff --git a/hw/xen/xen_apic.c b/hw/xen/xen_apic.c
index a2eb8a1..a958782 100644
--- a/hw/xen/xen_apic.c
+++ b/hw/xen/xen_apic.c
@@ -39,7 +39,7 @@ static const MemoryRegionOps xen_apic_io_ops = {
 static void xen_apic_init(APICCommonState *s)
 {
     memory_region_init_io(&s->io_memory, &xen_apic_io_ops, s, "xen-apic-msi",
-                          MSI_SPACE_SIZE);
+                          APIC_SPACE_SIZE);
 
 #if defined(CONFIG_XEN_CTRL_INTERFACE_VERSION) \
     && CONFIG_XEN_CTRL_INTERFACE_VERSION >= 420
diff --git a/include/hw/i386/apic_internal.h b/include/hw/i386/apic_internal.h
index 578241f..aac6290 100644
--- a/include/hw/i386/apic_internal.h
+++ b/include/hw/i386/apic_internal.h
@@ -66,8 +66,6 @@
 
 #define MAX_APICS 255
 
-#define MSI_SPACE_SIZE                  0x100000
-
 typedef struct APICCommonState APICCommonState;
 
 #define TYPE_APIC_COMMON "apic-common"
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index a1614e8..ab151d5 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -1270,5 +1270,6 @@ uint32_t x86_cpu_apic_id_from_index(unsigned int cpu_index);
 void enable_compat_apic_id_mode(void);
 
 #define APIC_DEFAULT_ADDRESS 0xfee00000
+#define APIC_SPACE_SIZE      0x100000
 
 #endif /* CPU_I386_H */
commit 8d6d4980c9421f3b9d1800dbc320da6a0bf754bd
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Fri Apr 26 19:51:52 2013 +0200

    target-i386: Do not allow to set apic-id once CPU is realized
    
    Signed-off-by: Igor Mammedov <imammedo at redhat.com>
    Reviewed-by: Eduardo Habkost <ehabkost at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index f1cecc0..0d9493d 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -1284,11 +1284,18 @@ static void x86_cpuid_set_apic_id(Object *obj, Visitor *v, void *opaque,
                                   const char *name, Error **errp)
 {
     X86CPU *cpu = X86_CPU(obj);
+    DeviceState *dev = DEVICE(obj);
     const int64_t min = 0;
     const int64_t max = UINT32_MAX;
     Error *error = NULL;
     int64_t value;
 
+    if (dev->realized) {
+        error_setg(errp, "Attempt to set property '%s' on '%s' after "
+                   "it was realized", name, object_get_typename(obj));
+        return;
+    }
+
     visit_type_int(v, &value, name, &error);
     if (error) {
         error_propagate(errp, error);
commit 310509304e1a83c1926471f1984c1cbf7d813631
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Thu Apr 25 16:05:26 2013 +0200

    target-i386: Introduce apic-id CPU property
    
    The property is used from board level to set APIC ID for CPUs it
    creates. Do so in a new pc_new_cpu() helper, to be reused for hot-plug.
    
    Signed-off-by: Igor Mammedov <imammedo at redhat.com>
    Reviewed-by: Eduardo Habkost <ehabkost at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 867add7..6568173 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -894,9 +894,33 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
     }
 }
 
+static X86CPU *pc_new_cpu(const char *cpu_model, int64_t apic_id, Error **errp)
+{
+    X86CPU *cpu;
+    Error *local_err = NULL;
+
+    cpu = cpu_x86_create(cpu_model, errp);
+    if (!cpu) {
+        return cpu;
+    }
+
+    object_property_set_int(OBJECT(cpu), apic_id, "apic-id", &local_err);
+    object_property_set_bool(OBJECT(cpu), true, "realized", &local_err);
+
+    if (local_err) {
+        if (cpu != NULL) {
+            object_unref(OBJECT(cpu));
+            cpu = NULL;
+        }
+        error_propagate(errp, local_err);
+    }
+    return cpu;
+}
+
 void pc_cpus_init(const char *cpu_model)
 {
     int i;
+    Error *error = NULL;
 
     /* init CPUs */
     if (cpu_model == NULL) {
@@ -908,7 +932,10 @@ void pc_cpus_init(const char *cpu_model)
     }
 
     for (i = 0; i < smp_cpus; i++) {
-        if (!cpu_x86_init(cpu_model)) {
+        pc_new_cpu(cpu_model, x86_cpu_apic_id_from_index(i), &error);
+        if (error) {
+            fprintf(stderr, "%s\n", error_get_pretty(error));
+            error_free(error);
             exit(1);
         }
     }
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 697848d..f1cecc0 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -1271,6 +1271,43 @@ static void x86_cpuid_set_tsc_freq(Object *obj, Visitor *v, void *opaque,
     cpu->env.tsc_khz = value / 1000;
 }
 
+static void x86_cpuid_get_apic_id(Object *obj, Visitor *v, void *opaque,
+                                  const char *name, Error **errp)
+{
+    X86CPU *cpu = X86_CPU(obj);
+    int64_t value = cpu->env.cpuid_apic_id;
+
+    visit_type_int(v, &value, name, errp);
+}
+
+static void x86_cpuid_set_apic_id(Object *obj, Visitor *v, void *opaque,
+                                  const char *name, Error **errp)
+{
+    X86CPU *cpu = X86_CPU(obj);
+    const int64_t min = 0;
+    const int64_t max = UINT32_MAX;
+    Error *error = NULL;
+    int64_t value;
+
+    visit_type_int(v, &value, name, &error);
+    if (error) {
+        error_propagate(errp, error);
+        return;
+    }
+    if (value < min || value > max) {
+        error_setg(errp, "Property %s.%s doesn't take value %" PRId64
+                   " (minimum: %" PRId64 ", maximum: %" PRId64 ")" ,
+                   object_get_typename(obj), name, value, min, max);
+        return;
+    }
+
+    if ((value != cpu->env.cpuid_apic_id) && cpu_exists(value)) {
+        error_setg(errp, "CPU with APIC ID %" PRIi64 " exists", value);
+        return;
+    }
+    cpu->env.cpuid_apic_id = value;
+}
+
 static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *name)
 {
     x86_def_t *def;
@@ -2270,6 +2307,9 @@ static void x86_cpu_initfn(Object *obj)
     object_property_add(obj, "tsc-frequency", "int",
                         x86_cpuid_get_tsc_freq,
                         x86_cpuid_set_tsc_freq, NULL, NULL, NULL);
+    object_property_add(obj, "apic-id", "int",
+                        x86_cpuid_get_apic_id,
+                        x86_cpuid_set_apic_id, NULL, NULL, NULL);
 
     env->cpuid_apic_id = x86_cpu_apic_id_from_index(cs->cpu_index);
 
commit 72ac2e876ddc6158f5b6d5f758d4e38c436010ed
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Fri Apr 26 18:04:32 2013 +0200

    target-i386: Introduce feat2prop() for CPU properties
    
    This helper replaces '_' with '-' in a uniform way.
    As a side effect, even custom mappings must use '-' now.
    
    Signed-off-by: Igor Mammedov <imammedo at redhat.com>
    [AF: Split off; operate on NUL-terminated string rather than '=' delimiter]
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index f34ba23..697848d 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -1307,6 +1307,16 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *name)
     return -1;
 }
 
+/* Convert all '_' in a feature string option name to '-', to make feature
+ * name conform to QOM property naming rule, which uses '-' instead of '_'.
+ */
+static inline void feat2prop(char *s)
+{
+    while ((s = strchr(s, '_'))) {
+        *s = '-';
+    }
+}
+
 /* Parse "+feature,-feature,feature=foo" CPU feature string
  */
 static void cpu_x86_parse_featurestr(X86CPU *cpu, char *features, Error **errp)
@@ -1329,6 +1339,7 @@ static void cpu_x86_parse_featurestr(X86CPU *cpu, char *features, Error **errp)
             add_flagname_to_bitmaps(featurestr + 1, minus_features);
         } else if ((val = strchr(featurestr, '='))) {
             *val = 0; val++;
+            feat2prop(featurestr);
             if (!strcmp(featurestr, "family")) {
                 object_property_parse(OBJECT(cpu), val, featurestr, errp);
             } else if (!strcmp(featurestr, "model")) {
@@ -1355,9 +1366,9 @@ static void cpu_x86_parse_featurestr(X86CPU *cpu, char *features, Error **errp)
                 object_property_parse(OBJECT(cpu), num, featurestr, errp);
             } else if (!strcmp(featurestr, "vendor")) {
                 object_property_parse(OBJECT(cpu), val, featurestr, errp);
-            } else if (!strcmp(featurestr, "model_id")) {
-                object_property_parse(OBJECT(cpu), val, "model-id", errp);
-            } else if (!strcmp(featurestr, "tsc_freq")) {
+            } else if (!strcmp(featurestr, "model-id")) {
+                object_property_parse(OBJECT(cpu), val, featurestr, errp);
+            } else if (!strcmp(featurestr, "tsc-freq")) {
                 int64_t tsc_freq;
                 char *err;
                 char num[32];
@@ -1370,7 +1381,7 @@ static void cpu_x86_parse_featurestr(X86CPU *cpu, char *features, Error **errp)
                 }
                 snprintf(num, sizeof(num), "%" PRId64, tsc_freq);
                 object_property_parse(OBJECT(cpu), num, "tsc-frequency", errp);
-            } else if (!strcmp(featurestr, "hv_spinlocks")) {
+            } else if (!strcmp(featurestr, "hv-spinlocks")) {
                 char *err;
                 numvalue = strtoul(val, &err, 0);
                 if (!*val || *err) {
commit b8622725cf0196f672f272922b0941dc8ba1c408
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Thu Apr 25 16:05:25 2013 +0200

    acpi_piix4: Add infrastructure to send CPU hot-plug GPE to guest
    
    * introduce processor status bitmask visible to guest at 0xaf00 addr,
      where ACPI asl code expects it
    * set bit corresponding to APIC ID in processor status bitmask on
      receiving CPU hot-plug notification
    * trigger CPU hot-plug SCI, to notify guest about CPU hot-plug event
    
    Signed-off-by: Igor Mammedov <imammedo at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/docs/specs/acpi_cpu_hotplug.txt b/docs/specs/acpi_cpu_hotplug.txt
new file mode 100644
index 0000000..5dec0c5
--- /dev/null
+++ b/docs/specs/acpi_cpu_hotplug.txt
@@ -0,0 +1,22 @@
+QEMU<->ACPI BIOS CPU hotplug interface
+--------------------------------------
+
+QEMU supports CPU hotplug via ACPI. This document
+describes the interface between QEMU and the ACPI BIOS.
+
+ACPI GPE block (IO ports 0xafe0-0xafe3, byte access):
+-----------------------------------------
+
+Generic ACPI GPE block. Bit 2 (GPE.2) used to notify CPU
+hot-add/remove event to ACPI BIOS, via SCI interrupt.
+
+CPU present bitmap (IO port 0xaf00-0xae1f, 1-byte access):
+---------------------------------------------------------------
+One bit per CPU. Bit position reflects corresponding CPU APIC ID.
+Read-only.
+
+CPU hot-add/remove notification:
+-----------------------------------------------------
+QEMU sets/clears corresponding CPU bit on hot-add/remove event.
+CPU present map read by ACPI BIOS GPE.2 handler to notify OS of CPU
+hot-(un)plug events.
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index 88386d7..c4af1cc 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -48,19 +48,28 @@
 #define PCI_EJ_BASE 0xae08
 #define PCI_RMV_BASE 0xae0c
 
+#define PIIX4_PROC_BASE 0xaf00
+#define PIIX4_PROC_LEN 32
+
 #define PIIX4_PCI_HOTPLUG_STATUS 2
+#define PIIX4_CPU_HOTPLUG_STATUS 4
 
 struct pci_status {
     uint32_t up; /* deprecated, maintained for migration compatibility */
     uint32_t down;
 };
 
+typedef struct CPUStatus {
+    uint8_t sts[PIIX4_PROC_LEN];
+} CPUStatus;
+
 typedef struct PIIX4PMState {
     PCIDevice dev;
 
     MemoryRegion io;
     MemoryRegion io_gpe;
     MemoryRegion io_pci;
+    MemoryRegion io_cpu;
     ACPIREGS ar;
 
     APMState apm;
@@ -82,6 +91,9 @@ typedef struct PIIX4PMState {
     uint8_t disable_s3;
     uint8_t disable_s4;
     uint8_t s4_val;
+
+    CPUStatus gpe_cpu;
+    Notifier cpu_added_notifier;
 } PIIX4PMState;
 
 static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
@@ -100,8 +112,8 @@ static void pm_update_sci(PIIX4PMState *s)
                    ACPI_BITMASK_POWER_BUTTON_ENABLE |
                    ACPI_BITMASK_GLOBAL_LOCK_ENABLE |
                    ACPI_BITMASK_TIMER_ENABLE)) != 0) ||
-        (((s->ar.gpe.sts[0] & s->ar.gpe.en[0])
-          & PIIX4_PCI_HOTPLUG_STATUS) != 0);
+        (((s->ar.gpe.sts[0] & s->ar.gpe.en[0]) &
+          (PIIX4_PCI_HOTPLUG_STATUS | PIIX4_CPU_HOTPLUG_STATUS)) != 0);
 
     qemu_set_irq(s->irq, sci_level);
     /* schedule a timer interruption if needed */
@@ -585,6 +597,73 @@ static const MemoryRegionOps piix4_pci_ops = {
     },
 };
 
+static uint64_t cpu_status_read(void *opaque, hwaddr addr, unsigned int size)
+{
+    PIIX4PMState *s = opaque;
+    CPUStatus *cpus = &s->gpe_cpu;
+    uint64_t val = cpus->sts[addr];
+
+    return val;
+}
+
+static void cpu_status_write(void *opaque, hwaddr addr, uint64_t data,
+                             unsigned int size)
+{
+    /* TODO: implement VCPU removal on guest signal that CPU can be removed */
+}
+
+static const MemoryRegionOps cpu_hotplug_ops = {
+    .read = cpu_status_read,
+    .write = cpu_status_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
+};
+
+typedef enum {
+    PLUG,
+    UNPLUG,
+} HotplugEventType;
+
+static void piix4_cpu_hotplug_req(PIIX4PMState *s, CPUState *cpu,
+                                  HotplugEventType action)
+{
+    CPUStatus *g = &s->gpe_cpu;
+    ACPIGPE *gpe = &s->ar.gpe;
+    CPUClass *k = CPU_GET_CLASS(cpu);
+    int64_t cpu_id;
+
+    assert(s != NULL);
+
+    *gpe->sts = *gpe->sts | PIIX4_CPU_HOTPLUG_STATUS;
+    cpu_id = k->get_arch_id(CPU(cpu));
+    if (action == PLUG) {
+        g->sts[cpu_id / 8] |= (1 << (cpu_id % 8));
+    } else {
+        g->sts[cpu_id / 8] &= ~(1 << (cpu_id % 8));
+    }
+    pm_update_sci(s);
+}
+
+static void piix4_cpu_added_req(Notifier *n, void *opaque)
+{
+    PIIX4PMState *s = container_of(n, PIIX4PMState, cpu_added_notifier);
+
+    piix4_cpu_hotplug_req(s, CPU(opaque), PLUG);
+}
+
+static void piix4_init_cpu_status(CPUState *cpu, void *data)
+{
+    CPUStatus *g = (CPUStatus *)data;
+    CPUClass *k = CPU_GET_CLASS(cpu);
+    int64_t id = k->get_arch_id(cpu);
+
+    g_assert((id / 8) < PIIX4_PROC_LEN);
+    g->sts[id / 8] |= (1 << (id % 8));
+}
+
 static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
                                 PCIHotplugState state);
 
@@ -600,6 +679,13 @@ static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
     memory_region_add_subregion(parent, PCI_HOTPLUG_ADDR,
                                 &s->io_pci);
     pci_bus_hotplug(bus, piix4_device_hotplug, &s->dev.qdev);
+
+    qemu_for_each_cpu(piix4_init_cpu_status, &s->gpe_cpu);
+    memory_region_init_io(&s->io_cpu, &cpu_hotplug_ops, s, "apci-cpu-hotplug",
+                          PIIX4_PROC_LEN);
+    memory_region_add_subregion(parent, PIIX4_PROC_BASE, &s->io_cpu);
+    s->cpu_added_notifier.notify = piix4_cpu_added_req;
+    qemu_register_cpu_added_notifier(&s->cpu_added_notifier);
 }
 
 static void enable_device(PIIX4PMState *s, int slot)
commit 69e5ff067ae724155fd7465119ee6db5721288b6
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Thu Apr 25 16:05:24 2013 +0200

    cpu: Add helper cpu_exists(), to check if CPU with specified id exists
    
    Signed-off-by: Igor Mammedov <imammedo 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 a28e5ff..e54579b 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -234,6 +234,16 @@ void qemu_for_each_cpu(void (*func)(CPUState *cpu, void *data), void *data);
  */
 CPUState *qemu_get_cpu(int index);
 
+/**
+ * cpu_exists:
+ * @id: Guest-exposed CPU ID to lookup.
+ *
+ * Search for CPU with specified ID.
+ *
+ * Returns: %true - CPU is found, %false - CPU isn't found.
+ */
+bool cpu_exists(int64_t id);
+
 #ifndef CONFIG_USER_ONLY
 
 typedef void (*CPUInterruptHandler)(CPUState *, int);
diff --git a/qom/cpu.c b/qom/cpu.c
index 9a4457b..3dc8208 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -24,6 +24,32 @@
 #include "qemu/notify.h"
 #include "sysemu/sysemu.h"
 
+typedef struct CPUExistsArgs {
+    int64_t id;
+    bool found;
+} CPUExistsArgs;
+
+static void cpu_exist_cb(CPUState *cpu, void *data)
+{
+    CPUClass *klass = CPU_GET_CLASS(cpu);
+    CPUExistsArgs *arg = data;
+
+    if (klass->get_arch_id(cpu) == arg->id) {
+        arg->found = true;
+    }
+}
+
+bool cpu_exists(int64_t id)
+{
+    CPUExistsArgs data = {
+        .id = id,
+        .found = false,
+    };
+
+    qemu_for_each_cpu(cpu_exist_cb, &data);
+    return data.found;
+}
+
 /* CPU hot-plug notifiers */
 static NotifierList cpu_added_notifiers =
     NOTIFIER_LIST_INITIALIZER(cpu_add_notifiers);
commit a37677c32bb313f5ba48aaf89f81cdc10c23ce56
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Tue Apr 23 10:29:42 2013 +0200

    cpus: Use qemu_for_each_cpu() in TCG thread
    
    Replaces an open-coded loop and hides unused CPUArchState.
    
    Signed-off-by: Igor Mammedov <imammedo at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/cpus.c b/cpus.c
index 1d88761..a2d92c7 100644
--- a/cpus.c
+++ b/cpus.c
@@ -812,6 +812,12 @@ static void *qemu_dummy_cpu_thread_fn(void *arg)
 
 static void tcg_exec_all(void);
 
+static void tcg_signal_cpu_creation(CPUState *cpu, void *data)
+{
+    cpu->thread_id = qemu_get_thread_id();
+    cpu->created = true;
+}
+
 static void *qemu_tcg_cpu_thread_fn(void *arg)
 {
     CPUState *cpu = arg;
@@ -820,13 +826,8 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
     qemu_tcg_init_cpu_signals();
     qemu_thread_get_self(cpu->thread);
 
-    /* signal CPU creation */
     qemu_mutex_lock(&qemu_global_mutex);
-    for (env = first_cpu; env != NULL; env = env->next_cpu) {
-        cpu = ENV_GET_CPU(env);
-        cpu->thread_id = qemu_get_thread_id();
-        cpu->created = true;
-    }
+    qemu_for_each_cpu(tcg_signal_cpu_creation, NULL);
     qemu_cond_signal(&qemu_cpu_cond);
 
     /* wait for initial kick-off after machine start */
commit d6b9e0d60cc511eca210834428bb74508cff3d33
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Wed Apr 24 22:58:04 2013 +0200

    cpu: Add qemu_for_each_cpu()
    
    Wrapper to avoid open-coded loops and to make CPUState iteration
    independent of CPUArchState.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    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 fa1e0c3..19725db 100644
--- a/exec.c
+++ b/exec.c
@@ -265,6 +265,16 @@ CPUState *qemu_get_cpu(int index)
     return env ? cpu : NULL;
 }
 
+void qemu_for_each_cpu(void (*func)(CPUState *cpu, void *data), void *data)
+{
+    CPUArchState *env = first_cpu;
+
+    while (env) {
+        func(ENV_GET_CPU(env), data);
+        env = env->next_cpu;
+    }
+}
+
 void cpu_exec_init(CPUArchState *env)
 {
     CPUState *cpu = ENV_GET_CPU(env);
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 1b4de17..a28e5ff 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -216,6 +216,15 @@ bool cpu_is_stopped(CPUState *cpu);
 void run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data);
 
 /**
+ * qemu_for_each_cpu:
+ * @func: The function to be executed.
+ * @data: Data to pass to the function.
+ *
+ * Executes @func for each CPU.
+ */
+void qemu_for_each_cpu(void (*func)(CPUState *cpu, void *data), void *data);
+
+/**
  * qemu_get_cpu:
  * @index: The CPUState at cpu_index value of the CPU to obtain.
  *
commit 997395d3888fcde6ce41535a8208d7aa919d824b
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Tue Apr 23 10:29:41 2013 +0200

    cpu: Introduce get_arch_id() method and override it for X86CPU
    
    get_arch_id() adds possibility for generic code to get a guest-visible
    CPU ID without accessing CPUArchState.
    If derived classes don't override it, it will return cpu_index.
    
    Override it on target-i386 in X86CPU to return the APIC ID.
    
    Signed-off-by: Igor Mammedov <imammedo at redhat.com>
    Reviewed-by: Eduardo Habkost <ehabkost at redhat.com>
    Reviewed-by: liguang <lig.fnst at cn.fujitsu.com>
    Acked-by: Michael S. Tsirkin <mst 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 ac93dce..1b4de17 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -45,6 +45,7 @@ typedef struct CPUState CPUState;
  * instantiatable CPU type.
  * @reset: Callback to reset the #CPUState to its initial state.
  * @do_interrupt: Callback for interrupt handling.
+ * @get_arch_id: Callback for getting architecture-dependent CPU ID.
  * @vmsd: State description for migration.
  *
  * Represents a CPU family or model.
@@ -58,6 +59,7 @@ typedef struct CPUClass {
 
     void (*reset)(CPUState *cpu);
     void (*do_interrupt)(CPUState *cpu);
+    int64_t (*get_arch_id)(CPUState *cpu);
 
     const struct VMStateDescription *vmsd;
 } CPUClass;
diff --git a/qom/cpu.c b/qom/cpu.c
index 34fa805..9a4457b 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -78,6 +78,11 @@ static void cpu_common_realizefn(DeviceState *dev, Error **errp)
     }
 }
 
+static int64_t cpu_common_get_arch_id(CPUState *cpu)
+{
+    return cpu->cpu_index;
+}
+
 static void cpu_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
@@ -85,6 +90,7 @@ static void cpu_class_init(ObjectClass *klass, void *data)
 
     k->class_by_name = cpu_common_class_by_name;
     k->reset = cpu_common_reset;
+    k->get_arch_id = cpu_common_get_arch_id;
     dc->realize = cpu_common_realizefn;
     dc->no_user = 1;
 }
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index e2302d8..f34ba23 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -2272,6 +2272,14 @@ static void x86_cpu_initfn(Object *obj)
     }
 }
 
+static int64_t x86_cpu_get_arch_id(CPUState *cs)
+{
+    X86CPU *cpu = X86_CPU(cs);
+    CPUX86State *env = &cpu->env;
+
+    return env->cpuid_apic_id;
+}
+
 static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
 {
     X86CPUClass *xcc = X86_CPU_CLASS(oc);
@@ -2286,6 +2294,8 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
 
     cc->do_interrupt = x86_cpu_do_interrupt;
     cpu_class_set_vmsd(cc, &vmstate_x86_cpu);
+
+    cc->get_arch_id = x86_cpu_get_arch_id;
 }
 
 static const TypeInfo x86_cpu_type_info = {
commit b8b7456d6ab7edb450ae5ec6473d3cd9a80412f4
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Tue Apr 23 10:29:40 2013 +0200

    pc: Update rtc_cmos on CPU hot-plug
    
    It provides updated currently available CPUs count to BIOS on reboot.
    
    Signed-off-by: Igor Mammedov <imammedo at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 29d2703..867add7 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -338,6 +338,21 @@ static void pc_cmos_init_late(void *opaque)
     qemu_unregister_reset(pc_cmos_init_late, opaque);
 }
 
+typedef struct RTCCPUHotplugArg {
+    Notifier cpu_added_notifier;
+    ISADevice *rtc_state;
+} RTCCPUHotplugArg;
+
+static void rtc_notify_cpu_added(Notifier *notifier, void *data)
+{
+    RTCCPUHotplugArg *arg = container_of(notifier, RTCCPUHotplugArg,
+                                         cpu_added_notifier);
+    ISADevice *s = arg->rtc_state;
+
+    /* increment the number of CPUs */
+    rtc_set_memory(s, 0x5f, rtc_get_memory(s, 0x5f) + 1);
+}
+
 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,
@@ -346,6 +361,7 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
     int val, nb, i;
     FDriveType fd_type[2] = { FDRIVE_DRV_NONE, FDRIVE_DRV_NONE };
     static pc_cmos_init_late_arg arg;
+    static RTCCPUHotplugArg cpu_hotplug_cb;
 
     /* various important CMOS locations needed by PC/Bochs bios */
 
@@ -384,6 +400,10 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
 
     /* set the number of CPU */
     rtc_set_memory(s, 0x5f, smp_cpus - 1);
+    /* init CPU hotplug notifier */
+    cpu_hotplug_cb.rtc_state = s;
+    cpu_hotplug_cb.cpu_added_notifier.notify = rtc_notify_cpu_added;
+    qemu_register_cpu_added_notifier(&cpu_hotplug_cb.cpu_added_notifier);
 
     /* set boot devices, and disable floppy signature check if requested */
     if (set_boot_dev(s, boot_device, fd_bootchk)) {
diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index afbd0db..481604d 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -680,6 +680,13 @@ void rtc_set_memory(ISADevice *dev, int addr, int val)
         s->cmos_data[addr] = val;
 }
 
+int rtc_get_memory(ISADevice *dev, int addr)
+{
+    RTCState *s = MC146818_RTC(dev);
+    assert(addr >= 0 && addr <= 127);
+    return s->cmos_data[addr];
+}
+
 static void rtc_set_date_from_host(ISADevice *dev)
 {
     RTCState *s = MC146818_RTC(dev);
diff --git a/include/hw/timer/mc146818rtc.h b/include/hw/timer/mc146818rtc.h
index 425bd17..753dda6 100644
--- a/include/hw/timer/mc146818rtc.h
+++ b/include/hw/timer/mc146818rtc.h
@@ -8,6 +8,7 @@
 
 ISADevice *rtc_init(ISABus *bus, int base_year, qemu_irq intercept_irq);
 void rtc_set_memory(ISADevice *dev, int addr, int val);
+int rtc_get_memory(ISADevice *dev, int addr);
 void rtc_set_date(ISADevice *dev, const struct tm *tm);
 
 #endif /* !MC146818RTC_H */
commit 066e9b2710be887f435e0e899fa71f1f4314f702
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Tue Apr 23 10:29:39 2013 +0200

    cpu: Introduce CPU hot-plug notifier
    
    Hot-add CPU event will be distributed to acpi_piix4 and rtc_cmos.
    
    Signed-off-by: Igor Mammedov <imammedo at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 010e412..2fb71af 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -153,6 +153,9 @@ void do_pci_device_hot_remove(Monitor *mon, const QDict *qdict);
 /* generic hotplug */
 void drive_hot_add(Monitor *mon, const QDict *qdict);
 
+/* CPU hotplug */
+void qemu_register_cpu_added_notifier(Notifier *notifier);
+
 /* pcie aer error injection */
 void pcie_aer_inject_error_print(Monitor *mon, const QObject *data);
 int do_pcie_aer_inject_error(Monitor *mon,
diff --git a/qom/cpu.c b/qom/cpu.c
index b91213e..34fa805 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -21,6 +21,17 @@
 #include "qom/cpu.h"
 #include "qemu-common.h"
 #include "sysemu/kvm.h"
+#include "qemu/notify.h"
+#include "sysemu/sysemu.h"
+
+/* CPU hot-plug notifiers */
+static NotifierList cpu_added_notifiers =
+    NOTIFIER_LIST_INITIALIZER(cpu_add_notifiers);
+
+void qemu_register_cpu_added_notifier(Notifier *notifier)
+{
+    notifier_list_add(&cpu_added_notifiers, notifier);
+}
 
 void cpu_reset_interrupt(CPUState *cpu, int mask)
 {
@@ -62,6 +73,7 @@ static void cpu_common_realizefn(DeviceState *dev, Error **errp)
 
     if (dev->hotplugged) {
         cpu_synchronize_post_init(cpu);
+        notifier_list_notify(&cpu_added_notifiers, dev);
         cpu_resume(cpu);
     }
 }
commit 6afb4721f3e45da727110470a61aafcd6682395e
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Tue Apr 23 10:29:38 2013 +0200

    cpu: Resume CPU from DeviceClass::realize() if hot-plugged
    
    Signed-off-by: Igor Mammedov <imammedo at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/qom/cpu.c b/qom/cpu.c
index 66f7c00..b91213e 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -62,6 +62,7 @@ static void cpu_common_realizefn(DeviceState *dev, Error **errp)
 
     if (dev->hotplugged) {
         cpu_synchronize_post_init(cpu);
+        cpu_resume(cpu);
     }
 }
 
commit 2993683b0fde0f836777c945baaddcaa5937903f
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Tue Apr 23 10:29:37 2013 +0200

    cpu: Introduce cpu_resume(), for single CPU
    
    Also add a stub for it, to make possible to use it in qom/cpu.c,
    which is shared with user emulators.
    
    Signed-off-by: Igor Mammedov <imammedo at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/cpus.c b/cpus.c
index 5a98a37..1d88761 100644
--- a/cpus.c
+++ b/cpus.c
@@ -993,6 +993,13 @@ void pause_all_vcpus(void)
     }
 }
 
+void cpu_resume(CPUState *cpu)
+{
+    cpu->stop = false;
+    cpu->stopped = false;
+    qemu_cpu_kick(cpu);
+}
+
 void resume_all_vcpus(void)
 {
     CPUArchState *penv = first_cpu;
@@ -1000,9 +1007,7 @@ void resume_all_vcpus(void)
     qemu_clock_enable(vm_clock, true);
     while (penv) {
         CPUState *pcpu = ENV_GET_CPU(penv);
-        pcpu->stop = false;
-        pcpu->stopped = false;
-        qemu_cpu_kick(pcpu);
+        cpu_resume(pcpu);
         penv = penv->next_cpu;
     }
 }
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 3664a1b..ac93dce 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -256,5 +256,12 @@ void cpu_interrupt(CPUState *cpu, int mask);
  */
 void cpu_reset_interrupt(CPUState *cpu, int mask);
 
+/**
+ * cpu_resume:
+ * @cpu: The CPU to resume.
+ *
+ * Resumes CPU, i.e. puts CPU into runnable state.
+ */
+void cpu_resume(CPUState *cpu);
 
 #endif
diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
index 9c55b34..03dff20 100644
--- a/stubs/Makefile.objs
+++ b/stubs/Makefile.objs
@@ -23,3 +23,4 @@ stub-obj-y += sysbus.o
 stub-obj-y += vm-stop.o
 stub-obj-y += vmstate.o
 stub-obj-$(CONFIG_WIN32) += fd-register.o
+stub-obj-y += cpus.o
diff --git a/stubs/cpus.c b/stubs/cpus.c
new file mode 100644
index 0000000..37000dd
--- /dev/null
+++ b/stubs/cpus.c
@@ -0,0 +1,5 @@
+#include "qom/cpu.h"
+
+void cpu_resume(CPUState *cpu)
+{
+}
commit 13eed94ed5617b98e657163490584dc2a0cc4b32
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Tue Apr 23 10:29:36 2013 +0200

    cpu: Call cpu_synchronize_post_init() from DeviceClass::realize()
    
    If hotplugged, synchronize CPU state to KVM.
    
    Signed-off-by: Igor Mammedov <imammedo 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/sysemu/kvm.h b/include/sysemu/kvm.h
index 2bc1f6b..9735c1d 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -250,8 +250,6 @@ int kvm_check_extension(KVMState *s, unsigned int extension);
 uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function,
                                       uint32_t index, int reg);
 void kvm_cpu_synchronize_state(CPUArchState *env);
-void kvm_cpu_synchronize_post_reset(CPUState *cpu);
-void kvm_cpu_synchronize_post_init(CPUState *cpu);
 
 /* generic hooks - to be moved/refactored once there are more users */
 
@@ -262,6 +260,16 @@ static inline void cpu_synchronize_state(CPUArchState *env)
     }
 }
 
+#if !defined(CONFIG_USER_ONLY)
+int kvm_physical_memory_addr_from_host(KVMState *s, void *ram_addr,
+                                       hwaddr *phys_addr);
+#endif
+
+#endif /* NEED_CPU_H */
+
+void kvm_cpu_synchronize_post_reset(CPUState *cpu);
+void kvm_cpu_synchronize_post_init(CPUState *cpu);
+
 static inline void cpu_synchronize_post_reset(CPUState *cpu)
 {
     if (kvm_enabled()) {
@@ -276,14 +284,6 @@ static inline void cpu_synchronize_post_init(CPUState *cpu)
     }
 }
 
-
-#if !defined(CONFIG_USER_ONLY)
-int kvm_physical_memory_addr_from_host(KVMState *s, void *ram_addr,
-                                       hwaddr *phys_addr);
-#endif
-
-#endif
-
 int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg);
 int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg);
 void kvm_irqchip_release_virq(KVMState *s, int virq);
diff --git a/kvm-all.c b/kvm-all.c
index 2d92721..f6c0f4a 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -109,6 +109,7 @@ bool kvm_async_interrupts_allowed;
 bool kvm_irqfds_allowed;
 bool kvm_msi_via_irqfd_allowed;
 bool kvm_gsi_routing_allowed;
+bool kvm_allowed;
 
 static const KVMCapabilityInfo kvm_required_capabilites[] = {
     KVM_CAP_INFO(USER_MEMORY),
diff --git a/kvm-stub.c b/kvm-stub.c
index b228378..b2c8f9b 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -25,6 +25,7 @@ bool kvm_async_interrupts_allowed;
 bool kvm_irqfds_allowed;
 bool kvm_msi_via_irqfd_allowed;
 bool kvm_gsi_routing_allowed;
+bool kvm_allowed;
 
 int kvm_init_vcpu(CPUState *cpu)
 {
diff --git a/qom/cpu.c b/qom/cpu.c
index e242dcb..66f7c00 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -20,6 +20,7 @@
 
 #include "qom/cpu.h"
 #include "qemu-common.h"
+#include "sysemu/kvm.h"
 
 void cpu_reset_interrupt(CPUState *cpu, int mask)
 {
@@ -57,6 +58,11 @@ static ObjectClass *cpu_common_class_by_name(const char *cpu_model)
 
 static void cpu_common_realizefn(DeviceState *dev, Error **errp)
 {
+    CPUState *cpu = CPU(dev);
+
+    if (dev->hotplugged) {
+        cpu_synchronize_post_init(cpu);
+    }
 }
 
 static void cpu_class_init(ObjectClass *klass, void *data)
diff --git a/vl.c b/vl.c
index b5a547e..41c367d 100644
--- a/vl.c
+++ b/vl.c
@@ -267,7 +267,6 @@ static NotifierList machine_init_done_notifiers =
     NOTIFIER_LIST_INITIALIZER(machine_init_done_notifiers);
 
 static bool tcg_allowed = true;
-bool kvm_allowed;
 bool xen_allowed;
 uint32_t xen_domid;
 enum xen_mode xen_mode = XEN_EMULATE;
commit c4cfef5e8a6371aa5e6577f2b980315c2dc46cfb
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Tue Apr 23 10:29:35 2013 +0200

    cpu: Make kvm-stub.o available outside softmmu
    
    It will provide stubs for *-user targets once softmmu-specific calls
    are attempted from common CPU code.
    
    Signed-off-by: Igor Mammedov <imammedo at redhat.com>
    Reviewed-by: Eduardo Habkost <ehabkost at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/Makefile.target b/Makefile.target
index 6583b05..ce4391f 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -60,6 +60,12 @@ all: $(PROGS) stap
 # Dummy command so that make thinks it has done something
 	@true
 
+CONFIG_NO_PCI = $(if $(subst n,,$(CONFIG_PCI)),n,y)
+CONFIG_NO_KVM = $(if $(subst n,,$(CONFIG_KVM)),n,y)
+CONFIG_NO_XEN = $(if $(subst n,,$(CONFIG_XEN)),n,y)
+CONFIG_NO_GET_MEMORY_MAPPING = $(if $(subst n,,$(CONFIG_HAVE_GET_MEMORY_MAPPING)),n,y)
+CONFIG_NO_CORE_DUMP = $(if $(subst n,,$(CONFIG_HAVE_CORE_DUMP)),n,y)
+
 #########################################################
 # cpu emulator library
 obj-y = exec.o translate-all.o cpu-exec.o
@@ -70,6 +76,7 @@ obj-y += fpu/softfloat.o
 obj-y += target-$(TARGET_BASE_ARCH)/
 obj-y += disas.o
 obj-$(CONFIG_GDBSTUB_XML) += gdbstub-xml.o
+obj-$(CONFIG_NO_KVM) += kvm-stub.o
 
 #########################################################
 # Linux user emulator target
@@ -98,18 +105,11 @@ endif #CONFIG_BSD_USER
 #########################################################
 # System emulator target
 ifdef CONFIG_SOFTMMU
-CONFIG_NO_PCI = $(if $(subst n,,$(CONFIG_PCI)),n,y)
-CONFIG_NO_KVM = $(if $(subst n,,$(CONFIG_KVM)),n,y)
-CONFIG_NO_XEN = $(if $(subst n,,$(CONFIG_XEN)),n,y)
-CONFIG_NO_GET_MEMORY_MAPPING = $(if $(subst n,,$(CONFIG_HAVE_GET_MEMORY_MAPPING)),n,y)
-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
 obj-$(CONFIG_HAVE_GET_MEMORY_MAPPING) += memory_mapping.o
 obj-$(CONFIG_HAVE_CORE_DUMP) += dump.o
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index 75bd7d9..2bc1f6b 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -144,10 +144,10 @@ int kvm_cpu_exec(CPUArchState *env);
 #if !defined(CONFIG_USER_ONLY)
 void *kvm_vmalloc(ram_addr_t size);
 void *kvm_arch_vmalloc(ram_addr_t size);
-void kvm_setup_guest_memory(void *start, size_t size);
+#endif
 
+void kvm_setup_guest_memory(void *start, size_t size);
 void kvm_flush_coalesced_mmio_buffer(void);
-#endif
 
 int kvm_insert_breakpoint(CPUArchState *current_env, target_ulong addr,
                           target_ulong len, int type);
diff --git a/kvm-stub.c b/kvm-stub.c
index 5f52186..b228378 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -12,10 +12,13 @@
 
 #include "qemu-common.h"
 #include "hw/hw.h"
-#include "hw/pci/msi.h"
 #include "cpu.h"
 #include "sysemu/kvm.h"
 
+#ifndef CONFIG_USER_ONLY
+#include "hw/pci/msi.h"
+#endif
+
 KVMState *kvm_state;
 bool kvm_kernel_irqchip;
 bool kvm_async_interrupts_allowed;
@@ -111,6 +114,7 @@ int kvm_on_sigbus(int code, void *addr)
     return 1;
 }
 
+#ifndef CONFIG_USER_ONLY
 int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg)
 {
     return -ENOSYS;
@@ -134,3 +138,4 @@ int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n, int virq)
 {
     return -ENOSYS;
 }
+#endif
commit e9016ee2bda1b7757072b856b2196f691aee3388
Author: Jason Wang <jasowang at redhat.com>
Date:   Thu Apr 25 15:26:54 2013 +0800

    virtio-net: count VIRTIO_NET_F_MAC when calculating config_len
    
    Commit 14f9b664 (hw/virtio-net.c: set config size using host features) tries to
    calculate config size based on the host features. But it forgets the
    VIRTIO_NET_F_MAC were always set for qemu later. This will lead a zero config
    len for virtio-net device when both VIRTIO_NET_F_STATUS and VIRTIO_NET_F_MQ were
    disabled form command line. Then qemu will crash when user tries to read the
    config of virtio-net.
    
    Fix this by counting VIRTIO_NET_F_MAC and make sure the config at least contains
    the mac address.
    
    Cc: Jesse Larrew <jlarrew at linux.vnet.ibm.com>
    Signed-off-by: Jason Wang <jasowang at redhat.com>
    Reviewed-by: Michael S. Tsirkin <mst at redhat.com>
    Acked-by: Michael S. Tsirkin <mst at redhat.com>
    Message-id: 1366874814-2658-1-git-send-email-jasowang at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index b2d99f9..908e7b8 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -1266,6 +1266,7 @@ static void virtio_net_guest_notifier_mask(VirtIODevice *vdev, int idx,
 void virtio_net_set_config_size(VirtIONet *n, uint32_t host_features)
 {
     int i, config_size = 0;
+    host_features |= (1 << VIRTIO_NET_F_MAC);
     for (i = 0; feature_sizes[i].flags != 0; i++) {
         if (host_features & feature_sizes[i].flags) {
             config_size = MAX(feature_sizes[i].end, config_size);
commit 9f032464c06c563fe0df49eac9caaaa90a68a219
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Tue Apr 30 12:41:50 2013 +0300

    sysemu: drop register_devices from header
    
    No user in sight.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Message-id: 20130430094149.GA29094 at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index f42a5ec..010e412 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -176,8 +176,6 @@ void usb_info(Monitor *mon, const QDict *qdict);
 
 void rtc_change_mon_event(struct tm *tm);
 
-void register_devices(void);
-
 void add_boot_device_path(int32_t bootindex, DeviceState *dev,
                           const char *suffix);
 char *get_boot_devices_list(size_t *size);
commit beb54a87ba74dfac00906b4c876945c6602cd293
Author: Jesse Larrew <jlarrew at linux.vnet.ibm.com>
Date:   Mon Apr 29 10:52:52 2013 -0500

    libqtest: only call fclose() on open files
    
    libqtest.c can segfault when calling fclose() if the pidfile wasn't
    opened successfully. This patch fixes the issue.
    
    Signed-off-by: Jesse Larrew <jlarrew at linux.vnet.ibm.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1367250772-17928-1-git-send-email-jlarrew at linux.vnet.ibm.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/tests/libqtest.c b/tests/libqtest.c
index 884f959..879ffe9 100644
--- a/tests/libqtest.c
+++ b/tests/libqtest.c
@@ -99,8 +99,8 @@ static pid_t qtest_qemu_pid(QTestState *s)
         if (fgets(buffer, sizeof(buffer), f)) {
             pid = atoi(buffer);
         }
+        fclose(f);
     }
-    fclose(f);
     return pid;
 }
 
commit 08eb8c85e3967b97865d46acadf26dc908fbb094
Author: Christian Borntraeger <borntraeger at de.ibm.com>
Date:   Fri Apr 26 11:24:47 2013 +0800

    Wire up disabled wait a panicked event on s390
    
    On s390 the disabled wait state indicates a state of attention.
    For example Linux uses that state after a panic. Lets
    put the system into panicked state.
    
    An alternative implementation would be to state
    disabled-wait <address> instead of pause in the action field.
    (e.g. z/OS, z/VM and other classic OSes use the address of the
    disabled wait to indicate an error code).
    
    Signed-off-by: Christian Borntraeger <borntraeger at de.ibm.com>
    Message-id: 6cf41156322e27e81a727b69f03728dbc225d5bb.1366945969.git.hutao at cn.fujitsu.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index fb006ee..a585392 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -34,6 +34,8 @@
 #include "sysemu/kvm.h"
 #include "cpu.h"
 #include "sysemu/device_tree.h"
+#include "qapi/qmp/qjson.h"
+#include "monitor/monitor.h"
 
 /* #define DEBUG_KVM */
 
@@ -779,9 +781,18 @@ static int handle_intercept(S390CPU *cpu)
             r = handle_instruction(cpu, run);
             break;
         case ICPT_WAITPSW:
-            if (s390_del_running_cpu(cpu) == 0 &&
-                is_special_wait_psw(cs)) {
-                qemu_system_shutdown_request();
+            /* disabled wait, since enabled wait is handled in kernel */
+            if (s390_del_running_cpu(cpu) == 0) {
+                if (is_special_wait_psw(cs)) {
+                    qemu_system_shutdown_request();
+                } else {
+                    QObject *data;
+
+                    data = qobject_from_jsonf("{ 'action': %s }", "pause");
+                    monitor_protocol_event(QEVENT_GUEST_PANICKED, data);
+                    qobject_decref(data);
+                    vm_stop(RUN_STATE_GUEST_PANICKED);
+                }
             }
             r = EXCP_HALTED;
             break;
commit 3ab135f3462af4c523a4b5969f9d6c67b2ac427a
Author: Hu Tao <hutao at cn.fujitsu.com>
Date:   Fri Apr 26 11:24:46 2013 +0800

    pvpanic: create pvpanic by default for machine 1.5
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Hu Tao <hutao at cn.fujitsu.com>
    Reviewed-by: Markus Armbruster <armbru at redhat.com>
    Message-id: f840042f0e1205041f8feaf0d39ca639884f3a00.1366945969.git.hutao at cn.fujitsu.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 2bda79e..852d63b 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -55,6 +55,8 @@ 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 };
 
+static bool has_pvpanic = true;
+
 /* PC hardware initialisation */
 static void pc_init1(MemoryRegion *system_memory,
                      MemoryRegion *system_io,
@@ -216,6 +218,10 @@ static void pc_init1(MemoryRegion *system_memory,
     if (pci_enabled) {
         pc_pci_device_init(pci_bus);
     }
+
+    if (has_pvpanic) {
+        pvpanic_init(isa_bus);
+    }
 }
 
 static void pc_init_pci(QEMUMachineInitArgs *args)
@@ -236,6 +242,7 @@ static void pc_init_pci(QEMUMachineInitArgs *args)
 static void pc_init_pci_1_4(QEMUMachineInitArgs *args)
 {
     pc_sysfw_flash_vs_rom_bug_compatible = true;
+    has_pvpanic = false;
     pc_init_pci(args);
 }
 
@@ -243,6 +250,7 @@ static void pc_init_pci_1_3(QEMUMachineInitArgs *args)
 {
     enable_compat_apic_id_mode();
     pc_sysfw_flash_vs_rom_bug_compatible = true;
+    has_pvpanic = false;
     pc_init_pci(args);
 }
 
@@ -252,6 +260,7 @@ static void pc_init_pci_1_2(QEMUMachineInitArgs *args)
     disable_kvm_pv_eoi();
     enable_compat_apic_id_mode();
     pc_sysfw_flash_vs_rom_bug_compatible = true;
+    has_pvpanic = false;
     pc_init_pci(args);
 }
 
@@ -260,6 +269,7 @@ static void pc_init_pci_1_0(QEMUMachineInitArgs *args)
 {
     disable_kvm_pv_eoi();
     enable_compat_apic_id_mode();
+    has_pvpanic = false;
     pc_init_pci(args);
 }
 
@@ -272,6 +282,7 @@ static void pc_init_pci_no_kvmclock(QEMUMachineInitArgs *args)
     const char *kernel_cmdline = args->kernel_cmdline;
     const char *initrd_filename = args->initrd_filename;
     const char *boot_device = args->boot_device;
+    has_pvpanic = false;
     disable_kvm_pv_eoi();
     enable_compat_apic_id_mode();
     pc_init1(get_system_memory(),
@@ -289,6 +300,7 @@ static void pc_init_isa(QEMUMachineInitArgs *args)
     const char *kernel_cmdline = args->kernel_cmdline;
     const char *initrd_filename = args->initrd_filename;
     const char *boot_device = args->boot_device;
+    has_pvpanic = false;
     if (cpu_model == NULL)
         cpu_model = "486";
     disable_kvm_pv_eoi();
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index d445bdf..d094041 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -45,6 +45,8 @@
 /* ICH9 AHCI has 6 ports */
 #define MAX_SATA_PORTS     6
 
+static bool has_pvpanic = true;
+
 /* PC hardware initialisation */
 static void pc_q35_init(QEMUMachineInitArgs *args)
 {
@@ -193,11 +195,16 @@ static void pc_q35_init(QEMUMachineInitArgs *args)
     if (pci_enabled) {
         pc_pci_device_init(host_bus);
     }
+
+    if (has_pvpanic) {
+        pvpanic_init(isa_bus);
+    }
 }
 
 static void pc_q35_init_1_4(QEMUMachineInitArgs *args)
 {
     pc_sysfw_flash_vs_rom_bug_compatible = true;
+    has_pvpanic = false;
     pc_q35_init(args);
 }
 
diff --git a/hw/misc/pvpanic.c b/hw/misc/pvpanic.c
index a80fae5..31e1b1d 100644
--- a/hw/misc/pvpanic.c
+++ b/hw/misc/pvpanic.c
@@ -19,6 +19,7 @@
 #include "qemu/log.h"
 
 #include "hw/nvram/fw_cfg.h"
+#include "hw/i386/pc.h"
 
 /* The bit of supported pv event */
 #define PVPANIC_F_PANICKED      0
@@ -107,6 +108,12 @@ static int pvpanic_isa_initfn(ISADevice *dev)
     return 0;
 }
 
+int pvpanic_init(ISABus *bus)
+{
+    isa_create_simple(bus, TYPE_ISA_PVPANIC_DEVICE);
+    return 0;
+}
+
 static Property pvpanic_isa_properties[] = {
     DEFINE_PROP_UINT16("ioport", PVPanicState, ioport, 0x505),
     DEFINE_PROP_END_OF_LIST(),
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 14b504c..dd6bc24 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -171,6 +171,9 @@ static inline bool isa_ne2000_init(ISABus *bus, int base, int irq, NICInfo *nd)
 extern bool pc_sysfw_flash_vs_rom_bug_compatible;
 void pc_system_firmware_init(MemoryRegion *rom_memory);
 
+/* pvpanic.c */
+int pvpanic_init(ISABus *bus);
+
 /* e820 types */
 #define E820_RAM        1
 #define E820_RESERVED   2
commit b42ffe60d8b510cd2f76ef50f6a1057f91a3dd34
Author: Hu Tao <hutao at cn.fujitsu.com>
Date:   Fri Apr 26 11:24:45 2013 +0800

    pvpanic: add document of pvpanic
    
    Signed-off-by: Hu Tao <hutao at cn.fujitsu.com>
    Reviewed-by: Markus Armbruster <armbru at redhat.com>
    Message-id: a5db4ce406647e8f4663b639eae62d880531df8b.1366945969.git.hutao at cn.fujitsu.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/docs/specs/pvpanic.txt b/docs/specs/pvpanic.txt
new file mode 100644
index 0000000..c7bbacc
--- /dev/null
+++ b/docs/specs/pvpanic.txt
@@ -0,0 +1,39 @@
+PVPANIC DEVICE
+==============
+
+pvpanic device is a simulated ISA device, through which a guest panic
+event is sent to qemu, and a QMP event is generated. This allows
+management apps (e.g. libvirt) to be notified and respond to the event.
+
+The management app has the option of waiting for GUEST_PANICKED events,
+and/or polling for guest-panicked RunState, to learn when the pvpanic
+device has fired a panic event.
+
+ISA Interface
+-------------
+
+pvpanic exposes a single I/O port, by default 0x505. On read, the bits
+recognized by the device are set. Software should ignore bits it doesn't
+recognize. On write, the bits not recognized by the device are ignored.
+Software should set only bits both itself and the device recognize.
+Currently, only bit 0 is recognized, setting it indicates a guest panic
+has happened.
+
+ACPI Interface
+--------------
+
+pvpanic device is defined with ACPI ID "QEMU0001". Custom methods:
+
+RDPT:       To determine whether guest panic notification is supported.
+Arguments:  None
+Return:     Returns a byte, bit 0 set to indicate guest panic
+            notification is supported. Other bits are reserved and
+            should be ignored.
+
+WRPT:       To send a guest panic event
+Arguments:  Arg0 is a byte, with bit 0 set to indicate guest panic has
+            happened. Other bits are reserved and should be cleared.
+Return:     None
+
+The ACPI device will automatically refer to the right port in case it
+is modified.
commit 10a584b2875a391d1036adac18955a892e56f5e3
Author: Hu Tao <hutao at cn.fujitsu.com>
Date:   Fri Apr 26 11:24:44 2013 +0800

    pvpanic: pass configurable ioport to seabios
    
    This lets seabios patch the corresponding SSDT entry.
    
    Also add fw_cfg object to /machine/fw_cfg so we can reference
    it elsewhere.
    
    Signed-off-by: Hu Tao <hutao at cn.fujitsu.com>
    Reviewed-by: Markus Armbruster <armbru at redhat.com>
    Message-id: 60c65d95fe2b23b12bea67099126566010a11a1a.1366945969.git.hutao at cn.fujitsu.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/misc/pvpanic.c b/hw/misc/pvpanic.c
index 01cfe0b..a80fae5 100644
--- a/hw/misc/pvpanic.c
+++ b/hw/misc/pvpanic.c
@@ -18,6 +18,8 @@
 #include "sysemu/sysemu.h"
 #include "qemu/log.h"
 
+#include "hw/nvram/fw_cfg.h"
+
 /* The bit of supported pv event */
 #define PVPANIC_F_PANICKED      0
 
@@ -86,10 +88,22 @@ static const MemoryRegionOps pvpanic_ops = {
 static int pvpanic_isa_initfn(ISADevice *dev)
 {
     PVPanicState *s = ISA_PVPANIC_DEVICE(dev);
+    static bool port_configured;
+    void *fw_cfg;
 
     memory_region_init_io(&s->io, &pvpanic_ops, s, "pvpanic", 1);
     isa_register_ioport(dev, &s->io, s->ioport);
 
+    if (!port_configured) {
+        fw_cfg = object_resolve_path("/machine/fw_cfg", NULL);
+        if (fw_cfg) {
+            fw_cfg_add_file(fw_cfg, "etc/pvpanic-port",
+                            g_memdup(&s->ioport, sizeof(s->ioport)),
+                            sizeof(s->ioport));
+            port_configured = true;
+        }
+    }
+
     return 0;
 }
 
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index 97bba87..1a7e49c 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -489,11 +489,17 @@ FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
     dev = qdev_create(NULL, "fw_cfg");
     qdev_prop_set_uint32(dev, "ctl_iobase", ctl_port);
     qdev_prop_set_uint32(dev, "data_iobase", data_port);
-    qdev_init_nofail(dev);
     d = SYS_BUS_DEVICE(dev);
 
     s = DO_UPCAST(FWCfgState, busdev.qdev, dev);
 
+    if (!object_resolve_path("/machine/fw_cfg", NULL)) {
+        object_property_add_child(qdev_get_machine(), "fw_cfg", OBJECT(s),
+                                  NULL);
+    }
+
+    qdev_init_nofail(dev);
+
     if (ctl_addr) {
         sysbus_mmio_map(d, 0, ctl_addr);
     }
commit 1dfe5057e5cf45b296ae67a7f84bdc6fa618d602
Author: Hu Tao <hutao at cn.fujitsu.com>
Date:   Fri Apr 26 11:24:43 2013 +0800

    fw_cfg: add required header files
    
    If fw_cfg.h is included alone, gcc gives error messages like these:
    
      error: unknown type name ‘uint32_t’
      error: unknown type name ‘size_t’
      error: unknown type name ‘hwaddr’
      ...
    
    Signed-off-by: Hu Tao <hutao at cn.fujitsu.com>
    Reviewed-by: Markus Armbruster <armbru at redhat.com>
    Message-id: d63f8bcdbfbec8135b1b57f9247c513a3e25762c.1366945969.git.hutao at cn.fujitsu.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/include/hw/nvram/fw_cfg.h b/include/hw/nvram/fw_cfg.h
index 05c8df1..3e4a334 100644
--- a/include/hw/nvram/fw_cfg.h
+++ b/include/hw/nvram/fw_cfg.h
@@ -1,6 +1,13 @@
 #ifndef FW_CFG_H
 #define FW_CFG_H
 
+#ifndef NO_QEMU_PROTOS
+#include <stdint.h>
+#include <stddef.h>
+
+#include "exec/hwaddr.h"
+#endif
+
 #define FW_CFG_SIGNATURE        0x00
 #define FW_CFG_ID               0x01
 #define FW_CFG_UUID             0x02
commit eec3d2adc98dd9ef7352823ce6597f88a51cf7cb
Author: Hu Tao <hutao at cn.fujitsu.com>
Date:   Fri Apr 26 11:24:42 2013 +0800

    introduce a new qom device to deal with panicked event
    
    pvpanic device is used to send guest panic event from guest to qemu.
    
    When guest panic happens, pvpanic device driver will write a event
    number to IO port 0x505(which is the IO port occupied by pvpanic device,
    by default). On receiving the event, pvpanic device will pause guest
    cpu(s), and send a qmp event QEVENT_GUEST_PANICKED.
    
    Signed-off-by: Wen Congyang <wency at cn.fujitsu.com>
    Signed-off-by: Hu Tao <hutao at cn.fujitsu.com>
    Reviewed-by: Markus Armbruster <armbru at redhat.com>
    Message-id: b66077a40235b3531632a05a6ff373850afc7d2e.1366945969.git.hutao at cn.fujitsu.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 bc716a0..4e30505 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -44,3 +44,4 @@ CONFIG_LPC_ICH9=y
 CONFIG_PCI_Q35=y
 CONFIG_APIC=y
 CONFIG_IOAPIC=y
+CONFIG_PVPANIC=y
diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak
index e53f627..5af8fd3 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -44,3 +44,4 @@ CONFIG_LPC_ICH9=y
 CONFIG_PCI_Q35=y
 CONFIG_APIC=y
 CONFIG_IOAPIC=y
+CONFIG_PVPANIC=y
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 11b18a4..2578e29 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -39,3 +39,5 @@ obj-$(CONFIG_OMAP) += omap_tap.o
 obj-$(CONFIG_PXA2XX) += pxa2xx_pcmcia.o
 obj-$(CONFIG_SLAVIO) += slavio_misc.o
 obj-$(CONFIG_ZYNQ) += zynq_slcr.o
+
+obj-$(CONFIG_PVPANIC) += pvpanic.o
diff --git a/hw/misc/pvpanic.c b/hw/misc/pvpanic.c
new file mode 100644
index 0000000..01cfe0b
--- /dev/null
+++ b/hw/misc/pvpanic.c
@@ -0,0 +1,123 @@
+/*
+ * QEMU simulated pvpanic device.
+ *
+ * Copyright Fujitsu, Corp. 2013
+ *
+ * Authors:
+ *     Wen Congyang <wency at cn.fujitsu.com>
+ *     Hu Tao <hutao at cn.fujitsu.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 "qapi/qmp/qobject.h"
+#include "qapi/qmp/qjson.h"
+#include "monitor/monitor.h"
+#include "sysemu/sysemu.h"
+#include "qemu/log.h"
+
+/* The bit of supported pv event */
+#define PVPANIC_F_PANICKED      0
+
+/* The pv event value */
+#define PVPANIC_PANICKED        (1 << PVPANIC_F_PANICKED)
+
+#define TYPE_ISA_PVPANIC_DEVICE    "pvpanic"
+#define ISA_PVPANIC_DEVICE(obj)    \
+    OBJECT_CHECK(PVPanicState, (obj), TYPE_ISA_PVPANIC_DEVICE)
+
+static void panicked_mon_event(const char *action)
+{
+    QObject *data;
+
+    data = qobject_from_jsonf("{ 'action': %s }", action);
+    monitor_protocol_event(QEVENT_GUEST_PANICKED, data);
+    qobject_decref(data);
+}
+
+static void handle_event(int event)
+{
+    static bool logged;
+
+    if (event & ~PVPANIC_PANICKED && !logged) {
+        qemu_log_mask(LOG_GUEST_ERROR, "pvpanic: unknown event %#x.\n", event);
+        logged = true;
+    }
+
+    if (event & PVPANIC_PANICKED) {
+        panicked_mon_event("pause");
+        vm_stop(RUN_STATE_GUEST_PANICKED);
+        return;
+    }
+}
+
+#include "hw/isa/isa.h"
+
+typedef struct PVPanicState {
+    ISADevice parent_obj;
+
+    MemoryRegion io;
+    uint16_t ioport;
+} PVPanicState;
+
+/* return supported events on read */
+static uint64_t pvpanic_ioport_read(void *opaque, hwaddr addr, unsigned size)
+{
+    return PVPANIC_PANICKED;
+}
+
+static void pvpanic_ioport_write(void *opaque, hwaddr addr, uint64_t val,
+                                 unsigned size)
+{
+    handle_event(val);
+}
+
+static const MemoryRegionOps pvpanic_ops = {
+    .read = pvpanic_ioport_read,
+    .write = pvpanic_ioport_write,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
+};
+
+static int pvpanic_isa_initfn(ISADevice *dev)
+{
+    PVPanicState *s = ISA_PVPANIC_DEVICE(dev);
+
+    memory_region_init_io(&s->io, &pvpanic_ops, s, "pvpanic", 1);
+    isa_register_ioport(dev, &s->io, s->ioport);
+
+    return 0;
+}
+
+static Property pvpanic_isa_properties[] = {
+    DEFINE_PROP_UINT16("ioport", PVPanicState, ioport, 0x505),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void pvpanic_isa_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
+
+    ic->init = pvpanic_isa_initfn;
+    dc->no_user = 1;
+    dc->props = pvpanic_isa_properties;
+}
+
+static TypeInfo pvpanic_isa_info = {
+    .name          = TYPE_ISA_PVPANIC_DEVICE,
+    .parent        = TYPE_ISA_DEVICE,
+    .instance_size = sizeof(PVPanicState),
+    .class_init    = pvpanic_isa_class_init,
+};
+
+static void pvpanic_register_types(void)
+{
+    type_register_static(&pvpanic_isa_info);
+}
+
+type_init(pvpanic_register_types)
commit c401a8a5156a2596b285586002d544c595d40cf7
Author: Hu Tao <hutao at cn.fujitsu.com>
Date:   Fri Apr 26 11:24:41 2013 +0800

    add a new qevent: QEVENT_GUEST_PANICKED
    
    This event will be emited when qemu detects guest panic.
    
    Signed-off-by: Wen Congyang <wency at cn.fujitsu.com>
    Signed-off-by: Hu Tao <hutao at cn.fujitsu.com>
    Reviewed-by: Markus Armbruster <armbru at redhat.com>
    Message-id: cf0bc45ecf9ecd3699bc72dc39f8cbab8ed79d8c.1366945969.git.hutao at cn.fujitsu.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/QMP/qmp-events.txt b/QMP/qmp-events.txt
index dcc826d..92fe5fb 100644
--- a/QMP/qmp-events.txt
+++ b/QMP/qmp-events.txt
@@ -446,3 +446,17 @@ Example:
 
 Note: If action is "reset", "shutdown", or "pause" the WATCHDOG event is
 followed respectively by the RESET, SHUTDOWN, or STOP events.
+
+GUEST_PANICKED
+--------------
+
+Emitted when guest OS panic is detected.
+
+Data:
+
+- "action": Action that has been taken (json-string, currently always "pause").
+
+Example:
+
+{ "event": "GUEST_PANICKED",
+     "data": { "action": "pause" } }
diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
index b868760..1a6cfcf 100644
--- a/include/monitor/monitor.h
+++ b/include/monitor/monitor.h
@@ -46,6 +46,7 @@ typedef enum MonitorEvent {
     QEVENT_WAKEUP,
     QEVENT_BALLOON_CHANGE,
     QEVENT_SPICE_MIGRATE_COMPLETED,
+    QEVENT_GUEST_PANICKED,
 
     /* Add to 'monitor_event_names' array in monitor.c when
      * defining new events here */
diff --git a/monitor.c b/monitor.c
index 8f828d4..62aaebe 100644
--- a/monitor.c
+++ b/monitor.c
@@ -496,6 +496,7 @@ static const char *monitor_event_names[] = {
     [QEVENT_WAKEUP] = "WAKEUP",
     [QEVENT_BALLOON_CHANGE] = "BALLOON_CHANGE",
     [QEVENT_SPICE_MIGRATE_COMPLETED] = "SPICE_MIGRATE_COMPLETED",
+    [QEVENT_GUEST_PANICKED] = "GUEST_PANICKED",
 };
 QEMU_BUILD_BUG_ON(ARRAY_SIZE(monitor_event_names) != QEVENT_MAX)
 
commit ede085b3fedfde36cb566968c4efcfbad4845af1
Author: Hu Tao <hutao at cn.fujitsu.com>
Date:   Fri Apr 26 11:24:40 2013 +0800

    add a new runstate: RUN_STATE_GUEST_PANICKED
    
    The guest will be in this state when it is panicked.
    
    Signed-off-by: Wen Congyang <wency at cn.fujitsu.com>
    Signed-off-by: Hu Tao <hutao at cn.fujitsu.com>
    Reviewed-by: Markus Armbruster <armbru at redhat.com>
    Message-id: 0255f263ffdc2a3716f73e89098b96fd79a235b3.1366945969.git.hutao at cn.fujitsu.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 43b961c..f42a5ec 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -22,6 +22,7 @@ int qemu_uuid_parse(const char *str, uint8_t *uuid);
 bool runstate_check(RunState state);
 void runstate_set(RunState new_state);
 int runstate_is_running(void);
+bool runstate_needs_reset(void);
 typedef struct vm_change_state_entry VMChangeStateEntry;
 typedef void VMChangeStateHandler(void *opaque, int running, RunState state);
 
diff --git a/qapi-schema.json b/qapi-schema.json
index 5b0fb3b..65be8f4 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -174,11 +174,14 @@
 # @suspended: guest is suspended (ACPI S3)
 #
 # @watchdog: the watchdog action is configured to pause and has been triggered
+#
+# @guest-panicked: guest has been panicked as a result of guest OS panic
 ##
 { 'enum': 'RunState',
   'data': [ 'debug', 'inmigrate', 'internal-error', 'io-error', 'paused',
             'postmigrate', 'prelaunch', 'finish-migrate', 'restore-vm',
-            'running', 'save-vm', 'shutdown', 'suspended', 'watchdog' ] }
+            'running', 'save-vm', 'shutdown', 'suspended', 'watchdog',
+            'guest-panicked' ] }
 
 ##
 # @SnapshotInfo
diff --git a/qmp.c b/qmp.c
index ed6c7ef..4676993 100644
--- a/qmp.c
+++ b/qmp.c
@@ -149,8 +149,7 @@ void qmp_cont(Error **errp)
 {
     Error *local_err = NULL;
 
-    if (runstate_check(RUN_STATE_INTERNAL_ERROR) ||
-               runstate_check(RUN_STATE_SHUTDOWN)) {
+    if (runstate_needs_reset()) {
         error_set(errp, QERR_RESET_REQUIRED);
         return;
     } else if (runstate_check(RUN_STATE_SUSPENDED)) {
diff --git a/vl.c b/vl.c
index 617ff2c..b5a547e 100644
--- a/vl.c
+++ b/vl.c
@@ -594,6 +594,7 @@ static const RunStateTransition runstate_transitions_def[] = {
     { RUN_STATE_RUNNING, RUN_STATE_SAVE_VM },
     { RUN_STATE_RUNNING, RUN_STATE_SHUTDOWN },
     { RUN_STATE_RUNNING, RUN_STATE_WATCHDOG },
+    { RUN_STATE_RUNNING, RUN_STATE_GUEST_PANICKED },
 
     { RUN_STATE_SAVE_VM, RUN_STATE_RUNNING },
 
@@ -608,6 +609,8 @@ static const RunStateTransition runstate_transitions_def[] = {
     { RUN_STATE_WATCHDOG, RUN_STATE_RUNNING },
     { RUN_STATE_WATCHDOG, RUN_STATE_FINISH_MIGRATE },
 
+    { RUN_STATE_GUEST_PANICKED, RUN_STATE_PAUSED },
+
     { RUN_STATE_MAX, RUN_STATE_MAX },
 };
 
@@ -649,6 +652,13 @@ int runstate_is_running(void)
     return runstate_check(RUN_STATE_RUNNING);
 }
 
+bool runstate_needs_reset(void)
+{
+    return runstate_check(RUN_STATE_INTERNAL_ERROR) ||
+        runstate_check(RUN_STATE_SHUTDOWN) ||
+        runstate_check(RUN_STATE_GUEST_PANICKED);
+}
+
 StatusInfo *qmp_query_status(Error **errp)
 {
     StatusInfo *info = g_malloc0(sizeof(*info));
@@ -1984,8 +1994,7 @@ static bool main_loop_should_exit(void)
         cpu_synchronize_all_states();
         qemu_system_reset(VMRESET_REPORT);
         resume_all_vcpus();
-        if (runstate_check(RUN_STATE_INTERNAL_ERROR) ||
-            runstate_check(RUN_STATE_SHUTDOWN)) {
+        if (runstate_needs_reset()) {
             runstate_set(RUN_STATE_PAUSED);
         }
     }
commit cffc5113a421feba767af57ec87fdd53a29e9f9c
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Apr 29 14:35:08 2013 +0200

    qdev: Report errors collected during device realization
    
    Better than just releasing the error object silently.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Message-id: 517E68FC.6030400 at siemens.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 4eb0134..ab1d8f5 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -162,6 +162,7 @@ int qdev_init(DeviceState *dev)
 
     object_property_set_bool(OBJECT(dev), true, "realized", &local_err);
     if (local_err != NULL) {
+        qerror_report_err(local_err);
         error_free(local_err);
         qdev_free(dev);
         return -1;
commit 7e7da8e35827abf602fa886fda1af9b001c20d3e
Author: Dunrong Huang <riegamaths at gmail.com>
Date:   Mon Apr 29 22:52:12 2013 +0800

    rules.mk: Fix build breakage
    
    The following error occurs when building dtc module:
    
            CHK version_gen.h
             CC libfdt/fdt.o
    cc1: error: dtc: No such file or directory [-Werror]
    cc1: all warnings being treated as errors
    make[1]: *** [libfdt/fdt.o] Error 1
    make: *** [subdir-dtc] Error 2
    
    In rules.mak, "-I$(<D) -I$(@D)" was expanded to "-Idtc -I." when
    building submodule dct. Due to the using of "-Wmissing-include-dirs,
    a warning would be rarsed. To avoid it, add "-I$(<D) -I$(@D)" to
    QEMU_INCLUDES instead of QEMU_CFLAGS so that QEMU_CFLAGS does not
    contain the "-Idtc".
    
    Cc: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Cc: Blue Swirl <blauwirbel at gmail.com>
    Cc: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Dunrong Huang <riegamaths at gmail.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Message-id: 1367247132-19622-1-git-send-email-riegamaths at gmail.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/rules.mak b/rules.mak
index 197a9d7..b21383b 100644
--- a/rules.mak
+++ b/rules.mak
@@ -15,7 +15,7 @@ MAKEFLAGS += -rR
 QEMU_DGFLAGS += -MMD -MP -MT $@ -MF $(*D)/$(*F).d
 
 # Same as -I$(SRC_PATH) -I., but for the nested source/object directories
-QEMU_CFLAGS += -I$(<D) -I$(@D)
+QEMU_INCLUDES += -I$(<D) -I$(@D)
 
 %.o: %.c
 	$(call quiet-command,$(CC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<,"  CC    $(TARGET_DIR)$@")
commit 9ab880b3a2f4b80bd5d8b18a312b3afed65dc036
Author: Alexander Graf <agraf at suse.de>
Date:   Tue Apr 30 15:02:16 2013 +0200

    QOM: Fail casts for unknown types
    
    When we try to cast an object to an unknown type, fail the cast. Today
    we would simply run into an assert().
    
    This fixes a bug on qemu-system-s390x for me that gets triggered by the
    audio code looking for PCI and ISA buses.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Message-id: 1367326936-28539-1-git-send-email-agraf at suse.de
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qom/object.c b/qom/object.c
index dd53d24..75e6aac 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -453,6 +453,11 @@ ObjectClass *object_class_dynamic_cast(ObjectClass *class,
     TypeImpl *type = class->type;
     ObjectClass *ret = NULL;
 
+    if (!target_type) {
+        /* target class type unknown, so fail the cast */
+        return NULL;
+    }
+
     if (type->class->interfaces &&
             type_is_ancestor(target_type, type_interface)) {
         int found = 0;
commit b7da6c60814a5c8703e9fa0d943ec3240e9d94ab
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Apr 30 16:00:32 2013 +0200

    pc_piix: remove undesired change in pc_init1
    
    Introduced when applying commit f81222b (audio: look for the ISA and
    PCI buses, 2013-04-18).
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Message-id: 1367330432-14417-1-git-send-email-pbonzini at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index c1113e0..2bda79e 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -88,6 +88,7 @@ static void pc_init1(MemoryRegion *system_memory,
     void *fw_cfg = NULL;
 
     pc_cpus_init(cpu_model);
+    pc_acpi_init("acpi-dsdt.aml");
 
     if (kvmclock_enabled) {
         kvmclock_create();
commit b3e6d591b05538056d665572f3e3bbfb3cbb70e7
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Apr 18 18:44:04 2013 +0200

    audio: enable PCI audio cards for all PCI-enabled targets
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Message-id: 1366303444-24620-9-git-send-email-pbonzini at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/default-configs/pci.mak b/default-configs/pci.mak
index 8a5b565..d557eab 100644
--- a/default-configs/pci.mak
+++ b/default-configs/pci.mak
@@ -9,6 +9,9 @@ CONFIG_NE2000_PCI=y
 CONFIG_EEPRO100_PCI=y
 CONFIG_PCNET_PCI=y
 CONFIG_PCNET_COMMON=y
+CONFIG_AC97=y
+CONFIG_HDA=y
+CONFIG_ES1370=y
 CONFIG_LSI_SCSI_PCI=y
 CONFIG_VMW_PVSCSI_SCSI_PCI=y
 CONFIG_MEGASAS_SCSI_PCI=y
diff --git a/default-configs/sound.mak b/default-configs/sound.mak
index ed20388..ff69c4d 100644
--- a/default-configs/sound.mak
+++ b/default-configs/sound.mak
@@ -1,7 +1,4 @@
 CONFIG_SB16=y
-CONFIG_AC97=y
-CONFIG_HDA=y
-CONFIG_ES1370=y
 #CONFIG_ADLIB=y
 #CONFIG_GUS=y
 #CONFIG_CS4231A=y
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index da91e70..c1113e0 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -193,8 +193,6 @@ static void pc_init1(MemoryRegion *system_memory,
         }
     }
 
-    audio_init();
-
     pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device,
                  floppy, idebus[0], idebus[1], rtc_state);
 
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 7ed0cd4..d445bdf 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -189,7 +189,6 @@ static void pc_q35_init(QEMUMachineInitArgs *args)
 
     /* the rest devices to which pci devfn is automatically assigned */
     pc_vga_init(isa_bus, host_bus);
-    audio_init();
     pc_nic_init(isa_bus, host_bus);
     if (pci_enabled) {
         pc_pci_device_init(host_bus);
diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c
index 822d300..94d9570 100644
--- a/hw/mips/mips_jazz.c
+++ b/hw/mips/mips_jazz.c
@@ -288,9 +288,7 @@ static void mips_jazz_init(MemoryRegion *address_space,
         parallel_mm_init(address_space, 0x80008000, 0, rc4030[0],
                          parallel_hds[0]);
 
-    /* Sound card */
     /* FIXME: missing Jazz sound at 0x8000c000, rc4030[2] */
-    audio_init();
 
     /* NVRAM */
     dev = qdev_create(NULL, "ds1225y");
diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index a2d01e1..9d521cc 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -985,9 +985,6 @@ void mips_malta_init(QEMUMachineInitArgs *args)
     }
     fdctrl_init_isa(isa_bus, fd);
 
-    /* Sound card */
-    audio_init();
-
     /* Network card */
     network_init();
 
diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
index 82bd27e..59c7da3 100644
--- a/hw/ppc/prep.c
+++ b/hw/ppc/prep.c
@@ -658,9 +658,6 @@ static void ppc_prep_init(QEMUMachineInitArgs *args)
 
     /* Special port to get debug messages from Open-Firmware */
     register_ioport_write(0x0F00, 4, 1, &PPC_debug_write, NULL);
-
-    /* Initialize audio subsystem */
-    audio_init();
 }
 
 static QEMUMachine prep_machine = {
diff --git a/vl.c b/vl.c
index 6668b12..617ff2c 100644
--- a/vl.c
+++ b/vl.c
@@ -4294,6 +4294,8 @@ int main(int argc, char **argv, char **envp)
                                  .cpu_model = cpu_model };
     machine->init(&args);
 
+    audio_init();
+
     cpu_synchronize_all_post_init();
 
     set_numa_modes();
commit f81222bc0cf68464fe82117521917cc1533c3ff4
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Apr 18 18:44:03 2013 +0200

    audio: look for the ISA and PCI buses
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Message-id: 1366303444-24620-8-git-send-email-pbonzini at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/arch_init.c b/arch_init.c
index 655dfa5..49c5dc2 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -987,20 +987,26 @@ void select_soundhw(const char *optarg)
     }
 }
 
-void audio_init(ISABus *isa_bus, PCIBus *pci_bus)
+void audio_init(void)
 {
     struct soundhw *c;
+    ISABus *isa_bus = (ISABus *) object_resolve_path_type("", TYPE_ISA_BUS, NULL);
+    PCIBus *pci_bus = (PCIBus *) object_resolve_path_type("", TYPE_PCI_BUS, NULL);
 
     for (c = soundhw; c->name; ++c) {
         if (c->enabled) {
             if (c->isa) {
-                if (isa_bus) {
-                    c->init.init_isa(isa_bus);
+                if (!isa_bus) {
+                    fprintf(stderr, "ISA bus not available for %s\n", c->name);
+                    exit(1);
                 }
+                c->init.init_isa(isa_bus);
             } else {
-                if (pci_bus) {
-                    c->init.init_pci(pci_bus);
+                if (!pci_bus) {
+                    fprintf(stderr, "PCI bus not available for %s\n", c->name);
+                    exit(1);
                 }
+                c->init.init_pci(pci_bus);
             }
         }
     }
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 08dd61d..da91e70 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -88,7 +88,6 @@ static void pc_init1(MemoryRegion *system_memory,
     void *fw_cfg = NULL;
 
     pc_cpus_init(cpu_model);
-    pc_acpi_init("acpi-dsdt.aml");
 
     if (kvmclock_enabled) {
         kvmclock_create();
@@ -194,7 +193,7 @@ static void pc_init1(MemoryRegion *system_memory,
         }
     }
 
-    audio_init(isa_bus, pci_enabled ? pci_bus : NULL);
+    audio_init();
 
     pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device,
                  floppy, idebus[0], idebus[1], rtc_state);
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index f160893..7ed0cd4 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -189,7 +189,7 @@ static void pc_q35_init(QEMUMachineInitArgs *args)
 
     /* the rest devices to which pci devfn is automatically assigned */
     pc_vga_init(isa_bus, host_bus);
-    audio_init(isa_bus, host_bus);
+    audio_init();
     pc_nic_init(isa_bus, host_bus);
     if (pci_enabled) {
         pc_pci_device_init(host_bus);
diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c
index fd3a5f9..822d300 100644
--- a/hw/mips/mips_jazz.c
+++ b/hw/mips/mips_jazz.c
@@ -290,7 +290,7 @@ static void mips_jazz_init(MemoryRegion *address_space,
 
     /* Sound card */
     /* FIXME: missing Jazz sound at 0x8000c000, rc4030[2] */
-    audio_init(isa_bus, NULL);
+    audio_init();
 
     /* NVRAM */
     dev = qdev_create(NULL, "ds1225y");
diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index 86f42b2..a2d01e1 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -986,7 +986,7 @@ void mips_malta_init(QEMUMachineInitArgs *args)
     fdctrl_init_isa(isa_bus, fd);
 
     /* Sound card */
-    audio_init(isa_bus, pci_bus);
+    audio_init();
 
     /* Network card */
     network_init();
diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
index cceab3e..82bd27e 100644
--- a/hw/ppc/prep.c
+++ b/hw/ppc/prep.c
@@ -660,7 +660,7 @@ static void ppc_prep_init(QEMUMachineInitArgs *args)
     register_ioport_write(0x0F00, 4, 1, &PPC_debug_write, NULL);
 
     /* Initialize audio subsystem */
-    audio_init(isa_bus, pci_bus);
+    audio_init();
 }
 
 static QEMUMachine prep_machine = {
diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h
index f18de33..dece913 100644
--- a/include/sysemu/arch_init.h
+++ b/include/sysemu/arch_init.h
@@ -30,7 +30,7 @@ void select_soundhw(const char *optarg);
 void do_acpitable_option(const QemuOpts *opts);
 void do_smbios_option(const char *optarg);
 void cpudef_init(void);
-void audio_init(ISABus *isa_bus, PCIBus *pci_bus);
+void audio_init(void);
 int tcg_available(void);
 int kvm_available(void);
 int xen_available(void);
commit 2e1103f60a871923ecd390804aba07b6031e0dc0
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Apr 18 18:44:02 2013 +0200

    qom: do not return root for empty path
    
    An empty path will return the sole object of that type in the
    QOM tree.  This is different from "/", which returns the root.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Message-id: 1366303444-24620-7-git-send-email-pbonzini at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qom/object.c b/qom/object.c
index 093502e..dd53d24 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -1113,21 +1113,13 @@ static Object *object_resolve_partial_path(Object *parent,
 Object *object_resolve_path_type(const char *path, const char *typename,
                                  bool *ambiguous)
 {
-    bool partial_path = true;
     Object *obj;
     gchar **parts;
 
     parts = g_strsplit(path, "/", 0);
-    if (parts == NULL || parts[0] == NULL) {
-        g_strfreev(parts);
-        return object_get_root();
-    }
-
-    if (strcmp(parts[0], "") == 0) {
-        partial_path = false;
-    }
+    assert(parts);
 
-    if (partial_path) {
+    if (parts[0] == NULL || strcmp(parts[0], "") != 0) {
         if (ambiguous) {
             *ambiguous = false;
         }
commit 98af93fde2e37b5b0c8cee9036e028fe6df6446c
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Apr 18 18:44:01 2013 +0200

    audio: replace audio card configuration with default-configs
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Message-id: 1366303444-24620-6-git-send-email-pbonzini at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/configure b/configure
index a3ba782..d91b141 100755
--- a/configure
+++ b/configure
@@ -123,8 +123,6 @@ interp_prefix="/usr/gnemul/qemu-%M"
 static="no"
 cross_prefix=""
 audio_drv_list=""
-audio_card_list="ac97 es1370 sb16 hda"
-audio_possible_cards="ac97 es1370 sb16 cs4231a adlib gus hda"
 block_drv_whitelist=""
 host_cc="cc"
 libs_softmmu=""
@@ -704,8 +702,6 @@ for opt do
   ;;
   --oss-lib=*) oss_lib="$optarg"
   ;;
-  --audio-card-list=*) audio_card_list=`echo "$optarg" | sed -e 's/,/ /g'`
-  ;;
   --audio-drv-list=*) audio_drv_list="$optarg"
   ;;
   --block-drv-whitelist=*) block_drv_whitelist=`echo "$optarg" | sed -e 's/,/ /g'`
@@ -1105,8 +1101,6 @@ echo "  --disable-cocoa          disable Cocoa (Mac OS X only)"
 echo "  --enable-cocoa           enable Cocoa (default on Mac OS X)"
 echo "  --audio-drv-list=LIST    set audio drivers list:"
 echo "                           Available drivers: $audio_possible_drivers"
-echo "  --audio-card-list=LIST   set list of emulated audio cards [$audio_card_list]"
-echo "                           Available cards: $audio_possible_cards"
 echo "  --block-drv-whitelist=L  set block driver whitelist"
 echo "                           (affects only QEMU, not qemu-img)"
 echo "  --enable-mixemu          enable mixer emulation"
@@ -3513,7 +3507,6 @@ echo "curses support    $curses"
 echo "curl support      $curl"
 echo "mingw32 support   $mingw32"
 echo "Audio drivers     $audio_drv_list"
-echo "Extra audio cards $audio_card_list"
 echo "Block whitelist   $block_drv_whitelist"
 echo "Mixer emulation   $mixemu"
 echo "VirtFS support    $virtfs"
diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
index 368a776..bc716a0 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -1,6 +1,7 @@
 # Default configuration for i386-softmmu
 
 include pci.mak
+include sound.mak
 include usb.mak
 CONFIG_VGA=y
 CONFIG_QXL=$(CONFIG_SPICE)
@@ -22,7 +23,6 @@ CONFIG_IDE_ISA=y
 CONFIG_IDE_PIIX=y
 CONFIG_NE2000_ISA=y
 CONFIG_PIIX_PCI=y
-CONFIG_SOUND=y
 CONFIG_HPET=y
 CONFIG_APPLESMC=y
 CONFIG_I8259=y
diff --git a/default-configs/mips-softmmu.mak b/default-configs/mips-softmmu.mak
index b764360..b443702 100644
--- a/default-configs/mips-softmmu.mak
+++ b/default-configs/mips-softmmu.mak
@@ -1,6 +1,7 @@
 # Default configuration for mips-softmmu
 
 include pci.mak
+include sound.mak
 include usb.mak
 CONFIG_ISA_MMIO=y
 CONFIG_ESP=y
@@ -23,7 +24,6 @@ CONFIG_PIIX4=y
 CONFIG_IDE_ISA=y
 CONFIG_IDE_PIIX=y
 CONFIG_NE2000_ISA=y
-CONFIG_SOUND=y
 CONFIG_RC4030=y
 CONFIG_DP8393X=y
 CONFIG_DS1225Y=y
diff --git a/default-configs/mips64-softmmu.mak b/default-configs/mips64-softmmu.mak
index 0e4e65d..d638957 100644
--- a/default-configs/mips64-softmmu.mak
+++ b/default-configs/mips64-softmmu.mak
@@ -1,6 +1,7 @@
 # Default configuration for mips64-softmmu
 
 include pci.mak
+include sound.mak
 include usb.mak
 CONFIG_ISA_MMIO=y
 CONFIG_ESP=y
@@ -23,7 +24,6 @@ CONFIG_PIIX4=y
 CONFIG_IDE_ISA=y
 CONFIG_IDE_PIIX=y
 CONFIG_NE2000_ISA=y
-CONFIG_SOUND=y
 CONFIG_RC4030=y
 CONFIG_DP8393X=y
 CONFIG_DS1225Y=y
diff --git a/default-configs/mips64el-softmmu.mak b/default-configs/mips64el-softmmu.mak
index 0a6c4f7..c9be3f4 100644
--- a/default-configs/mips64el-softmmu.mak
+++ b/default-configs/mips64el-softmmu.mak
@@ -1,6 +1,7 @@
 # Default configuration for mips64el-softmmu
 
 include pci.mak
+include sound.mak
 include usb.mak
 CONFIG_ISA_MMIO=y
 CONFIG_ESP=y
@@ -24,7 +25,6 @@ CONFIG_IDE_ISA=y
 CONFIG_IDE_PIIX=y
 CONFIG_IDE_VIA=y
 CONFIG_NE2000_ISA=y
-CONFIG_SOUND=y
 CONFIG_RC4030=y
 CONFIG_DP8393X=y
 CONFIG_DS1225Y=y
diff --git a/default-configs/mipsel-softmmu.mak b/default-configs/mipsel-softmmu.mak
index 9f9c6da..4f4a449 100644
--- a/default-configs/mipsel-softmmu.mak
+++ b/default-configs/mipsel-softmmu.mak
@@ -1,6 +1,7 @@
 # Default configuration for mipsel-softmmu
 
 include pci.mak
+include sound.mak
 include usb.mak
 CONFIG_ISA_MMIO=y
 CONFIG_ESP=y
@@ -23,7 +24,6 @@ CONFIG_PIIX4=y
 CONFIG_IDE_ISA=y
 CONFIG_IDE_PIIX=y
 CONFIG_NE2000_ISA=y
-CONFIG_SOUND=y
 CONFIG_RC4030=y
 CONFIG_DP8393X=y
 CONFIG_DS1225Y=y
diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
index 50034fc..cc3587f 100644
--- a/default-configs/ppc-softmmu.mak
+++ b/default-configs/ppc-softmmu.mak
@@ -1,6 +1,7 @@
 # Default configuration for ppc-softmmu
 
 include pci.mak
+include sound.mak
 include usb.mak
 CONFIG_GDBSTUB_XML=y
 CONFIG_ISA_MMIO=y
@@ -34,7 +35,6 @@ CONFIG_IDE_ISA=y
 CONFIG_IDE_CMD646=y
 CONFIG_IDE_MACIO=y
 CONFIG_NE2000_ISA=y
-CONFIG_SOUND=y
 CONFIG_PFLASH_CFI01=y
 CONFIG_PFLASH_CFI02=y
 CONFIG_PTIMER=y
diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak
index 6398d60..884ea8a 100644
--- a/default-configs/ppc64-softmmu.mak
+++ b/default-configs/ppc64-softmmu.mak
@@ -1,6 +1,7 @@
 # Default configuration for ppc64-softmmu
 
 include pci.mak
+include sound.mak
 include usb.mak
 CONFIG_GDBSTUB_XML=y
 CONFIG_ISA_MMIO=y
@@ -34,7 +35,6 @@ CONFIG_IDE_ISA=y
 CONFIG_IDE_CMD646=y
 CONFIG_IDE_MACIO=y
 CONFIG_NE2000_ISA=y
-CONFIG_SOUND=y
 CONFIG_PFLASH_CFI01=y
 CONFIG_PFLASH_CFI02=y
 CONFIG_PTIMER=y
diff --git a/default-configs/ppcemb-softmmu.mak b/default-configs/ppcemb-softmmu.mak
index 05b50d6..be93e03 100644
--- a/default-configs/ppcemb-softmmu.mak
+++ b/default-configs/ppcemb-softmmu.mak
@@ -1,6 +1,7 @@
 # Default configuration for ppcemb-softmmu
 
 include pci.mak
+include sound.mak
 include usb.mak
 CONFIG_GDBSTUB_XML=y
 CONFIG_ISA_MMIO=y
@@ -29,7 +30,6 @@ CONFIG_IDE_ISA=y
 CONFIG_IDE_CMD646=y
 CONFIG_IDE_MACIO=y
 CONFIG_NE2000_ISA=y
-CONFIG_SOUND=y
 CONFIG_PFLASH_CFI01=y
 CONFIG_PFLASH_CFI02=y
 CONFIG_PTIMER=y
diff --git a/default-configs/sound.mak b/default-configs/sound.mak
new file mode 100644
index 0000000..ed20388
--- /dev/null
+++ b/default-configs/sound.mak
@@ -0,0 +1,7 @@
+CONFIG_SB16=y
+CONFIG_AC97=y
+CONFIG_HDA=y
+CONFIG_ES1370=y
+#CONFIG_ADLIB=y
+#CONFIG_GUS=y
+#CONFIG_CS4231A=y
diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak
index 2711b83..e53f627 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -1,6 +1,7 @@
 # Default configuration for x86_64-softmmu
 
 include pci.mak
+include sound.mak
 include usb.mak
 CONFIG_VGA=y
 CONFIG_QXL=$(CONFIG_SPICE)
@@ -22,7 +23,6 @@ CONFIG_IDE_ISA=y
 CONFIG_IDE_PIIX=y
 CONFIG_NE2000_ISA=y
 CONFIG_PIIX_PCI=y
-CONFIG_SOUND=y
 CONFIG_HPET=y
 CONFIG_APPLESMC=y
 CONFIG_I8259=y
diff --git a/hw/audio/Makefile.objs b/hw/audio/Makefile.objs
index 2375102..7ce85a2 100644
--- a/hw/audio/Makefile.objs
+++ b/hw/audio/Makefile.objs
@@ -1,14 +1,12 @@
 # Sound
-sound-obj-y =
-sound-obj-$(CONFIG_SB16) += sb16.o
-sound-obj-$(CONFIG_ES1370) += es1370.o
-sound-obj-$(CONFIG_AC97) += ac97.o
-sound-obj-$(CONFIG_ADLIB) += fmopl.o adlib.o
-sound-obj-$(CONFIG_GUS) += gus.o gusemu_hal.o gusemu_mixer.o
-sound-obj-$(CONFIG_CS4231A) += cs4231a.o
-sound-obj-$(CONFIG_HDA) += intel-hda.o hda-codec.o
+common-obj-$(CONFIG_SB16) += sb16.o
+common-obj-$(CONFIG_ES1370) += es1370.o
+common-obj-$(CONFIG_AC97) += ac97.o
+common-obj-$(CONFIG_ADLIB) += fmopl.o adlib.o
+common-obj-$(CONFIG_GUS) += gus.o gusemu_hal.o gusemu_mixer.o
+common-obj-$(CONFIG_CS4231A) += cs4231a.o
+common-obj-$(CONFIG_HDA) += intel-hda.o hda-codec.o
 
-common-obj-$(CONFIG_SOUND) += $(sound-obj-y)
 common-obj-$(CONFIG_PCSPK) += pcspk.o
 common-obj-$(CONFIG_WM8750) += wm8750.o
 common-obj-$(CONFIG_PL041) += pl041.o lm4549.o
commit f6547f07d41491d74179e8dd100f7477abdd43b1
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Apr 18 18:44:00 2013 +0200

    audio: remove CONFIG_* symbols
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Message-id: 1366303444-24620-5-git-send-email-pbonzini at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/configure b/configure
index 09b3c30..a3ba782 100755
--- a/configure
+++ b/configure
@@ -3678,10 +3678,6 @@ fi
 if test "$cap_ng" = "yes" ; then
   echo "CONFIG_LIBCAP=y" >> $config_host_mak
 fi
-for card in $audio_card_list; do
-    def=CONFIG_`echo $card | LC_ALL=C tr '[a-z]' '[A-Z]'`
-    echo "$def=y" >> $config_host_mak
-done
 echo "CONFIG_AUDIO_DRIVERS=$audio_drv_list" >> $config_host_mak
 for drv in $audio_drv_list; do
     def=CONFIG_`echo $drv | LC_ALL=C tr '[a-z]' '[A-Z]'`
@@ -4363,11 +4359,6 @@ if test "$target_bsd_user" = "yes" ; then
   echo "CONFIG_BSD_USER=y" >> $config_target_mak
 fi
 
-# the static way of configuring available audio cards requires this workaround
-if test "$target_user_only" != "yes" && grep -q CONFIG_PCSPK $source_path/default-configs/$target.mak; then
-  echo "CONFIG_PCSPK=y" >> $config_target_mak
-fi
-
 # generate QEMU_CFLAGS/LDFLAGS for targets
 
 cflags=""
commit ffa48cf5ab719e1e181e51b87bc0f5d397b791fa
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Apr 18 18:43:59 2013 +0200

    audio: remove HAS_AUDIO
    
    Several targets can have wavcapture/-soundhw support via PCI cards.
    HAS_AUDIO is a useless limitation, remove it.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Message-id: 1366303444-24620-4-git-send-email-pbonzini at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/arch_init.c b/arch_init.c
index 0504184..655dfa5 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -887,7 +887,6 @@ SaveVMHandlers savevm_ram_handlers = {
     .cancel = ram_migration_cancel,
 };
 
-#ifdef HAS_AUDIO
 struct soundhw {
     const char *name;
     const char *descr;
@@ -1006,14 +1005,6 @@ void audio_init(ISABus *isa_bus, PCIBus *pci_bus)
         }
     }
 }
-#else
-void select_soundhw(const char *optarg)
-{
-}
-void audio_init(ISABus *isa_bus, PCIBus *pci_bus)
-{
-}
-#endif
 
 int qemu_uuid_parse(const char *str, uint8_t *uuid)
 {
@@ -1069,15 +1060,6 @@ void cpudef_init(void)
 #endif
 }
 
-int audio_available(void)
-{
-#ifdef HAS_AUDIO
-    return 1;
-#else
-    return 0;
-#endif
-}
-
 int tcg_available(void)
 {
     return 1;
diff --git a/configure b/configure
index 34e8cbb..09b3c30 100755
--- a/configure
+++ b/configure
@@ -4457,14 +4457,6 @@ alpha)
 ;;
 esac
 
-if test "$target_softmmu" = "yes" ; then
-  case "$TARGET_BASE_ARCH" in
-  arm|lm32|i386|mips|ppc)
-    cflags="-DHAS_AUDIO $cflags"
-  ;;
-  esac
-fi
-
 if test "$gprof" = "yes" ; then
   echo "TARGET_GPROF=yes" >> $config_target_mak
   if test "$target_linux_user" = "yes" ; then
diff --git a/hmp-commands.hx b/hmp-commands.hx
index df44906..9cea415 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -736,7 +736,6 @@ info mice
 @end example
 ETEXI
 
-#ifdef HAS_AUDIO
     {
         .name       = "wavcapture",
         .args_type  = "path:F,freq:i?,bits:i?,nchannels:i?",
@@ -744,7 +743,6 @@ ETEXI
         .help       = "capture audio to a wave file (default frequency=44100 bits=16 channels=2)",
         .mhandler.cmd = do_wav_capture,
     },
-#endif
 STEXI
 @item wavcapture @var{filename} [@var{frequency} [@var{bits} [@var{channels}]]]
 @findex wavcapture
@@ -759,7 +757,6 @@ Defaults:
 @end itemize
 ETEXI
 
-#ifdef HAS_AUDIO
     {
         .name       = "stopcapture",
         .args_type  = "n:i",
@@ -767,7 +764,6 @@ ETEXI
         .help       = "stop capture",
         .mhandler.cmd = do_stop_capture,
     },
-#endif
 STEXI
 @item stopcapture @var{index}
 @findex stopcapture
diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h
index aed3d1d..f18de33 100644
--- a/include/sysemu/arch_init.h
+++ b/include/sysemu/arch_init.h
@@ -30,7 +30,6 @@ void select_soundhw(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);
 void audio_init(ISABus *isa_bus, PCIBus *pci_bus);
 int tcg_available(void);
 int kvm_available(void);
diff --git a/monitor.c b/monitor.c
index 332abe7..8f828d4 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1862,7 +1862,6 @@ static void do_info_capture(Monitor *mon, const QDict *qdict)
     }
 }
 
-#ifdef HAS_AUDIO
 static void do_stop_capture(Monitor *mon, const QDict *qdict)
 {
     int i;
@@ -1903,7 +1902,6 @@ static void do_wav_capture(Monitor *mon, const QDict *qdict)
     }
     QLIST_INSERT_HEAD (&capture_head, s, entries);
 }
-#endif
 
 static qemu_acl *find_acl(Monitor *mon, const char *name)
 {
diff --git a/vl.c b/vl.c
index 322ea80..6668b12 100644
--- a/vl.c
+++ b/vl.c
@@ -3232,18 +3232,10 @@ int main(int argc, char **argv, char **envp)
                 add_device_config(DEV_BT, optarg);
                 break;
             case QEMU_OPTION_audio_help:
-                if (!(audio_available())) {
-                    printf("Option %s not supported for this target\n", popt->name);
-                    exit(1);
-                }
                 AUD_help ();
                 exit (0);
                 break;
             case QEMU_OPTION_soundhw:
-                if (!(audio_available())) {
-                    printf("Option %s not supported for this target\n", popt->name);
-                    exit(1);
-                }
                 select_soundhw (optarg);
                 break;
             case QEMU_OPTION_h:
commit 36cd6f6f20724d49aac1910e310f81a43e0cb657
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Apr 18 18:43:58 2013 +0200

    audio: remove the need for audio card CONFIG_* symbols
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Message-id: 1366303444-24620-3-git-send-email-pbonzini at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/arch_init.c b/arch_init.c
index 92de1bd..0504184 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -899,96 +899,30 @@ struct soundhw {
     } init;
 };
 
-static struct soundhw soundhw[] = {
-#ifdef HAS_AUDIO_CHOICE
-#ifdef CONFIG_PCSPK
-    {
-        "pcspk",
-        "PC speaker",
-        0,
-        1,
-        { .init_isa = pcspk_audio_init }
-    },
-#endif
-
-#ifdef CONFIG_SB16
-    {
-        "sb16",
-        "Creative Sound Blaster 16",
-        0,
-        1,
-        { .init_isa = SB16_init }
-    },
-#endif
-
-#ifdef CONFIG_CS4231A
-    {
-        "cs4231a",
-        "CS4231A",
-        0,
-        1,
-        { .init_isa = cs4231a_init }
-    },
-#endif
-
-#ifdef CONFIG_ADLIB
-    {
-        "adlib",
-#ifdef HAS_YMF262
-        "Yamaha YMF262 (OPL3)",
-#else
-        "Yamaha YM3812 (OPL2)",
-#endif
-        0,
-        1,
-        { .init_isa = Adlib_init }
-    },
-#endif
-
-#ifdef CONFIG_GUS
-    {
-        "gus",
-        "Gravis Ultrasound GF1",
-        0,
-        1,
-        { .init_isa = GUS_init }
-    },
-#endif
-
-#ifdef CONFIG_AC97
-    {
-        "ac97",
-        "Intel 82801AA AC97 Audio",
-        0,
-        0,
-        { .init_pci = ac97_init }
-    },
-#endif
+static struct soundhw soundhw[9];
+static int soundhw_count;
 
-#ifdef CONFIG_ES1370
-    {
-        "es1370",
-        "ENSONIQ AudioPCI ES1370",
-        0,
-        0,
-        { .init_pci = es1370_init }
-    },
-#endif
-
-#ifdef CONFIG_HDA
-    {
-        "hda",
-        "Intel HD Audio",
-        0,
-        0,
-        { .init_pci = intel_hda_and_codec_init }
-    },
-#endif
-
-#endif /* HAS_AUDIO_CHOICE */
+void isa_register_soundhw(const char *name, const char *descr,
+                          int (*init_isa)(ISABus *bus))
+{
+    assert(soundhw_count < ARRAY_SIZE(soundhw) - 1);
+    soundhw[soundhw_count].name = name;
+    soundhw[soundhw_count].descr = descr;
+    soundhw[soundhw_count].isa = 1;
+    soundhw[soundhw_count].init.init_isa = init_isa;
+    soundhw_count++;
+}
 
-    { NULL, NULL, 0, 0, { NULL } }
-};
+void pci_register_soundhw(const char *name, const char *descr,
+                          int (*init_pci)(PCIBus *bus))
+{
+    assert(soundhw_count < ARRAY_SIZE(soundhw) - 1);
+    soundhw[soundhw_count].name = name;
+    soundhw[soundhw_count].descr = descr;
+    soundhw[soundhw_count].isa = 0;
+    soundhw[soundhw_count].init.init_pci = init_pci;
+    soundhw_count++;
+}
 
 void select_soundhw(const char *optarg)
 {
@@ -997,16 +931,16 @@ void select_soundhw(const char *optarg)
     if (is_help_option(optarg)) {
     show_valid_cards:
 
-#ifdef HAS_AUDIO_CHOICE
-        printf("Valid sound card names (comma separated):\n");
-        for (c = soundhw; c->name; ++c) {
-            printf ("%-11s %s\n", c->name, c->descr);
+        if (soundhw_count) {
+             printf("Valid sound card names (comma separated):\n");
+             for (c = soundhw; c->name; ++c) {
+                 printf ("%-11s %s\n", c->name, c->descr);
+             }
+             printf("\n-soundhw all will enable all of the above\n");
+        } else {
+             printf("Machine has no user-selectable audio hardware "
+                    "(it may or may not have always-present audio hardware).\n");
         }
-        printf("\n-soundhw all will enable all of the above\n");
-#else
-        printf("Machine has no user-selectable audio hardware "
-               "(it may or may not have always-present audio hardware).\n");
-#endif
         exit(!is_help_option(optarg));
     }
     else {
diff --git a/configure b/configure
index 21438d4..34e8cbb 100755
--- a/configure
+++ b/configure
@@ -4459,15 +4459,9 @@ esac
 
 if test "$target_softmmu" = "yes" ; then
   case "$TARGET_BASE_ARCH" in
-  arm)
+  arm|lm32|i386|mips|ppc)
     cflags="-DHAS_AUDIO $cflags"
   ;;
-  lm32)
-    cflags="-DHAS_AUDIO $cflags"
-  ;;
-  i386|mips|ppc)
-    cflags="-DHAS_AUDIO -DHAS_AUDIO_CHOICE $cflags"
-  ;;
   esac
 fi
 
diff --git a/hw/audio/ac97.c b/hw/audio/ac97.c
index ab68ec6..baf138b 100644
--- a/hw/audio/ac97.c
+++ b/hw/audio/ac97.c
@@ -1396,7 +1396,7 @@ static void ac97_exitfn (PCIDevice *dev)
     memory_region_destroy (&s->io_nabm);
 }
 
-int ac97_init (PCIBus *bus)
+static int ac97_init (PCIBus *bus)
 {
     pci_create_simple (bus, -1, "AC97");
     return 0;
@@ -1433,6 +1433,7 @@ static const TypeInfo ac97_info = {
 static void ac97_register_types (void)
 {
     type_register_static (&ac97_info);
+    pci_register_soundhw("ac97", "Intel 82801AA AC97 Audio", ac97_init);
 }
 
 type_init (ac97_register_types)
diff --git a/hw/audio/adlib.c b/hw/audio/adlib.c
index fb41f9d..fc20857 100644
--- a/hw/audio/adlib.c
+++ b/hw/audio/adlib.c
@@ -372,7 +372,7 @@ static const TypeInfo adlib_info = {
     .class_init    = adlib_class_initfn,
 };
 
-int Adlib_init (ISABus *bus)
+static int Adlib_init (ISABus *bus)
 {
     isa_create_simple (bus, TYPE_ADLIB);
     return 0;
@@ -381,6 +381,7 @@ int Adlib_init (ISABus *bus)
 static void adlib_register_types (void)
 {
     type_register_static (&adlib_info);
+    isa_register_soundhw("adlib", ADLIB_DESC, Adlib_init);
 }
 
 type_init (adlib_register_types)
diff --git a/hw/audio/cs4231a.c b/hw/audio/cs4231a.c
index 5711b62..cc605e5 100644
--- a/hw/audio/cs4231a.c
+++ b/hw/audio/cs4231a.c
@@ -659,7 +659,7 @@ static int cs4231a_initfn (ISADevice *dev)
     return 0;
 }
 
-int cs4231a_init (ISABus *bus)
+static int cs4231a_init (ISABus *bus)
 {
     isa_create_simple (bus, "cs4231a");
     return 0;
@@ -692,6 +692,7 @@ static const TypeInfo cs4231a_info = {
 static void cs4231a_register_types (void)
 {
     type_register_static (&cs4231a_info);
+    isa_register_soundhw("cs4231a", "CS4231A", cs4231a_init);
 }
 
 type_init (cs4231a_register_types)
diff --git a/hw/audio/es1370.c b/hw/audio/es1370.c
index 9fe5708..c1cd169 100644
--- a/hw/audio/es1370.c
+++ b/hw/audio/es1370.c
@@ -1051,7 +1051,7 @@ static void es1370_exitfn (PCIDevice *dev)
     memory_region_destroy (&s->io);
 }
 
-int es1370_init (PCIBus *bus)
+static int es1370_init (PCIBus *bus)
 {
     pci_create_simple (bus, -1, "ES1370");
     return 0;
@@ -1083,6 +1083,7 @@ static const TypeInfo es1370_info = {
 static void es1370_register_types (void)
 {
     type_register_static (&es1370_info);
+    pci_register_soundhw("es1370", "ENSONIQ AudioPCI ES1370", es1370_init);
 }
 
 type_init (es1370_register_types)
diff --git a/hw/audio/gus.c b/hw/audio/gus.c
index 0604d6e..a91921c 100644
--- a/hw/audio/gus.c
+++ b/hw/audio/gus.c
@@ -293,7 +293,7 @@ static int gus_initfn (ISADevice *dev)
     return 0;
 }
 
-int GUS_init (ISABus *bus)
+static int GUS_init (ISABus *bus)
 {
     isa_create_simple (bus, "gus");
     return 0;
@@ -327,6 +327,7 @@ static const TypeInfo gus_info = {
 static void gus_register_types (void)
 {
     type_register_static (&gus_info);
+    isa_register_soundhw("gus", "Gravis Ultrasound GF1", GUS_init);
 }
 
 type_init (gus_register_types)
diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c
index 3d8077a..1016af0 100644
--- a/hw/audio/intel-hda.c
+++ b/hw/audio/intel-hda.c
@@ -1300,21 +1300,11 @@ static const TypeInfo hda_codec_device_type_info = {
     .class_init = hda_codec_device_class_init,
 };
 
-static void intel_hda_register_types(void)
-{
-    type_register_static(&hda_codec_bus_info);
-    type_register_static(&intel_hda_info_ich6);
-    type_register_static(&intel_hda_info_ich9);
-    type_register_static(&hda_codec_device_type_info);
-}
-
-type_init(intel_hda_register_types)
-
 /*
  * create intel hda controller with codec attached to it,
  * so '-soundhw hda' works.
  */
-int intel_hda_and_codec_init(PCIBus *bus)
+static int intel_hda_and_codec_init(PCIBus *bus)
 {
     PCIDevice *controller;
     BusState *hdabus;
@@ -1327,3 +1317,13 @@ int intel_hda_and_codec_init(PCIBus *bus)
     return 0;
 }
 
+static void intel_hda_register_types(void)
+{
+    type_register_static(&hda_codec_bus_info);
+    type_register_static(&intel_hda_info_ich6);
+    type_register_static(&intel_hda_info_ich9);
+    type_register_static(&hda_codec_device_type_info);
+    pci_register_soundhw("hda", "Intel HD Audio", intel_hda_and_codec_init);
+}
+
+type_init(intel_hda_register_types)
diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c
index d844e85..3a7285f 100644
--- a/hw/audio/pcspk.c
+++ b/hw/audio/pcspk.c
@@ -25,6 +25,7 @@
 #include "hw/hw.h"
 #include "hw/i386/pc.h"
 #include "hw/isa/isa.h"
+#include "hw/audio/audio.h"
 #include "audio/audio.h"
 #include "qemu/timer.h"
 #include "hw/timer/i8254.h"
@@ -108,7 +109,7 @@ static void pcspk_callback(void *opaque, int free)
     }
 }
 
-int pcspk_audio_init(ISABus *bus)
+static int pcspk_audio_init(ISABus *bus)
 {
     PCSpkState *s = pcspk_state;
     struct audsettings as = {PCSPK_SAMPLE_RATE, 1, AUD_FMT_U8, 0};
@@ -200,5 +201,6 @@ static const TypeInfo pcspk_info = {
 static void pcspk_register(void)
 {
     type_register_static(&pcspk_info);
+    isa_register_soundhw("pcspk", "PC speaker", pcspk_audio_init);
 }
 type_init(pcspk_register)
diff --git a/hw/audio/sb16.c b/hw/audio/sb16.c
index 61583bc..6ddc0ac 100644
--- a/hw/audio/sb16.c
+++ b/hw/audio/sb16.c
@@ -1386,7 +1386,7 @@ static int sb16_initfn (ISADevice *dev)
     return 0;
 }
 
-int SB16_init (ISABus *bus)
+static int SB16_init (ISABus *bus)
 {
     isa_create_simple (bus, TYPE_SB16);
     return 0;
@@ -1421,6 +1421,7 @@ static const TypeInfo sb16_info = {
 static void sb16_register_types (void)
 {
     type_register_static (&sb16_info);
+    isa_register_soundhw("sb16", "Creative Sound Blaster 16", SB16_init);
 }
 
 type_init (sb16_register_types)
diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c
index 44fc43f..04933a9 100644
--- a/hw/usb/dev-audio.c
+++ b/hw/usb/dev-audio.c
@@ -33,7 +33,6 @@
 #include "hw/usb.h"
 #include "hw/usb/desc.h"
 #include "hw/hw.h"
-#include "hw/audio/audio.h"
 #include "audio/audio.h"
 
 #define USBAUDIO_VENDOR_NUM     0x46f4 /* CRC16() of "QEMU" */
diff --git a/include/hw/audio/audio.h b/include/hw/audio/audio.h
index 428274f..b28abdd 100644
--- a/include/hw/audio/audio.h
+++ b/include/hw/audio/audio.h
@@ -1,25 +1,10 @@
 #ifndef HW_AUDIODEV_H
 #define HW_AUDIODEV_H 1
 
-/* es1370.c */
-int es1370_init(PCIBus *bus);
+void isa_register_soundhw(const char *name, const char *descr,
+                          int (*init_isa)(ISABus *bus));
 
-/* sb16.c */
-int SB16_init(ISABus *bus);
-
-/* adlib.c */
-int Adlib_init(ISABus *bus);
-
-/* gus.c */
-int GUS_init(ISABus *bus);
-
-/* ac97.c */
-int ac97_init(PCIBus *bus);
-
-/* cs4231a.c */
-int cs4231a_init(ISABus *bus);
-
-/* intel-hda.c + hda-audio.c */
-int intel_hda_and_codec_init(PCIBus *bus);
+void pci_register_soundhw(const char *name, const char *descr,
+                          int (*init_pci)(PCIBus *bus));
 
 #endif
diff --git a/include/hw/audio/pcspk.h b/include/hw/audio/pcspk.h
index b60c000..7625137 100644
--- a/include/hw/audio/pcspk.h
+++ b/include/hw/audio/pcspk.h
@@ -42,6 +42,4 @@ static inline ISADevice *pcspk_init(ISABus *bus, ISADevice *pit)
     return dev;
 }
 
-int pcspk_audio_init(ISABus *bus);
-
 #endif /* !HW_PCSPK_H */
commit 8c444a1978fd9956c9712572d9ad0b83bbbc0a63
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Apr 18 18:43:57 2013 +0200

    adlib: qdev-ify
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Message-id: 1366303444-24620-2-git-send-email-pbonzini at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/audio/adlib.c b/hw/audio/adlib.c
index 4a58e6e..fb41f9d 100644
--- a/hw/audio/adlib.c
+++ b/hw/audio/adlib.c
@@ -31,6 +31,12 @@
 
 #define ADLIB_KILL_TIMERS 1
 
+#ifdef HAS_YMF262
+#define ADLIB_DESC "Yamaha YMF262 (OPL3)"
+#else
+#define ADLIB_DESC "Yamaha YM3812 (OPL2)"
+#endif
+
 #ifdef DEBUG
 #include "qemu/timer.h"
 #endif
@@ -56,13 +62,15 @@ void YMF262UpdateOneQEMU (int which, INT16 *dst, int length);
 #define IO_WRITE_PROTO(name) \
     void name (void *opaque, uint32_t nport, uint32_t val)
 
-static struct {
-    int port;
-    int freq;
-} conf = {0x220, 44100};
+#define TYPE_ADLIB "adlib"
+#define ADLIB(obj) OBJECT_CHECK(AdlibState, (obj), TYPE_ADLIB)
 
 typedef struct {
+    ISADevice parent_obj;
+
     QEMUSoundCard card;
+    uint32_t freq;
+    uint32_t port;
     int ticking[2];
     int enabled;
     int active;
@@ -80,7 +88,7 @@ typedef struct {
 #endif
 } AdlibState;
 
-static AdlibState glob_adlib;
+static AdlibState *glob_adlib;
 
 static void adlib_stop_opl_timer (AdlibState *s, size_t n)
 {
@@ -150,7 +158,7 @@ static IO_READ_PROTO (adlib_read)
 
 static void timer_handler (int c, double interval_Sec)
 {
-    AdlibState *s = &glob_adlib;
+    AdlibState *s = glob_adlib;
     unsigned n = c & 1;
 #ifdef DEBUG
     double interval;
@@ -275,14 +283,20 @@ static void Adlib_fini (AdlibState *s)
     AUD_remove_card (&s->card);
 }
 
-int Adlib_init (ISABus *bus)
+static int Adlib_initfn (ISADevice *dev)
 {
-    AdlibState *s = &glob_adlib;
+    AdlibState *s = ADLIB(dev);
     struct audsettings as;
 
+    if (glob_adlib) {
+        dolog ("Cannot create more than 1 adlib device\n");
+        return -1;
+    }
+    glob_adlib = s;
+
 #ifdef HAS_YMF262
-    if (YMF262Init (1, 14318180, conf.freq)) {
-        dolog ("YMF262Init %d failed\n", conf.freq);
+    if (YMF262Init (1, 14318180, s->freq)) {
+        dolog ("YMF262Init %d failed\n", s->freq);
         return -1;
     }
     else {
@@ -290,9 +304,9 @@ int Adlib_init (ISABus *bus)
         s->enabled = 1;
     }
 #else
-    s->opl = OPLCreate (OPL_TYPE_YM3812, 3579545, conf.freq);
+    s->opl = OPLCreate (OPL_TYPE_YM3812, 3579545, s->freq);
     if (!s->opl) {
-        dolog ("OPLCreate %d failed\n", conf.freq);
+        dolog ("OPLCreate %d failed\n", s->freq);
         return -1;
     }
     else {
@@ -301,7 +315,7 @@ int Adlib_init (ISABus *bus)
     }
 #endif
 
-    as.freq = conf.freq;
+    as.freq = s->freq;
     as.nchannels = SHIFT;
     as.fmt = AUD_FMT_S16;
     as.endianness = AUDIO_HOST_ENDIANNESS;
@@ -327,11 +341,46 @@ int Adlib_init (ISABus *bus)
     register_ioport_read (0x388, 4, 1, adlib_read, s);
     register_ioport_write (0x388, 4, 1, adlib_write, s);
 
-    register_ioport_read (conf.port, 4, 1, adlib_read, s);
-    register_ioport_write (conf.port, 4, 1, adlib_write, s);
+    register_ioport_read (s->port, 4, 1, adlib_read, s);
+    register_ioport_write (s->port, 4, 1, adlib_write, s);
 
-    register_ioport_read (conf.port + 8, 2, 1, adlib_read, s);
-    register_ioport_write (conf.port + 8, 2, 1, adlib_write, s);
+    register_ioport_read (s->port + 8, 2, 1, adlib_read, s);
+    register_ioport_write (s->port + 8, 2, 1, adlib_write, s);
 
     return 0;
 }
+
+static Property adlib_properties[] = {
+    DEFINE_PROP_HEX32  ("iobase",  AdlibState, port, 0x220),
+    DEFINE_PROP_UINT32 ("freq",    AdlibState, freq,  44100),
+    DEFINE_PROP_END_OF_LIST (),
+};
+
+static void adlib_class_initfn (ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS (klass);
+    ISADeviceClass *ic = ISA_DEVICE_CLASS (klass);
+    ic->init = Adlib_initfn;
+    dc->desc = ADLIB_DESC;
+    dc->props = adlib_properties;
+}
+
+static const TypeInfo adlib_info = {
+    .name          = TYPE_ADLIB,
+    .parent        = TYPE_ISA_DEVICE,
+    .instance_size = sizeof (AdlibState),
+    .class_init    = adlib_class_initfn,
+};
+
+int Adlib_init (ISABus *bus)
+{
+    isa_create_simple (bus, TYPE_ADLIB);
+    return 0;
+}
+
+static void adlib_register_types (void)
+{
+    type_register_static (&adlib_info);
+}
+
+type_init (adlib_register_types)
commit 7504ae690c7320f3852890974708795cf5469895
Author: Lei Li <lilei at linux.vnet.ibm.com>
Date:   Thu Apr 25 13:29:12 2013 +0800

    doc: document the Pseudo-encoding of LED state
    
    Signed-off-by: Lei Li <lilei at linux.vnet.ibm.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1366867752-11578-5-git-send-email-lilei at linux.vnet.ibm.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/docs/vnc-ledstate-Pseudo-encoding.txt b/docs/vnc-ledstate-Pseudo-encoding.txt
new file mode 100644
index 0000000..0f124f6
--- /dev/null
+++ b/docs/vnc-ledstate-Pseudo-encoding.txt
@@ -0,0 +1,50 @@
+VNC LED state Pseudo-encoding
+=============================
+
+Introduction
+------------
+
+This document describes the Pseudo-encoding of LED state for RFB which
+is the protocol used in VNC as reference link below:
+
+http://tigervnc.svn.sourceforge.net/viewvc/tigervnc/rfbproto/rfbproto.rst?content-type=text/plain
+
+When accessing a guest by console through VNC, there might be mismatch
+between the lock keys notification LED on the computer running the VNC
+client session and the current status of the lock keys on the guest
+machine.
+
+To solve this problem it attempts to add LED state Pseudo-encoding
+extension to VNC protocol to deal with setting LED state.
+
+Pseudo-encoding
+---------------
+
+This Pseudo-encoding requested by client declares to server that it supports
+LED state extensions to the protocol.
+
+The Pseudo-encoding number for LED state defined as:
+
+======= ===============================================================
+Number  Name
+======= ===============================================================
+-261    'LED state Pseudo-encoding'
+======= ===============================================================
+
+LED state Pseudo-encoding
+--------------------------
+
+The LED state Pseudo-encoding describes the encoding of LED state which
+consists of 3 bits, from left to right each bit represents the Caps, Num,
+and Scroll lock key respectively. '1' indicates that the LED should be
+on and '0' should be off.
+
+Some example encodings for it as following:
+
+======= ===============================================================
+Code    Description
+======= ===============================================================
+100     CapsLock is on, NumLock and ScrollLock are off
+010     NumLock is on, CapsLock and ScrollLock are off
+111     CapsLock, NumLock and ScrollLock are on
+======= ===============================================================
commit e7b2aaccd94a68c7927cae7ca47ced1bddc4f448
Author: Lei Li <lilei at linux.vnet.ibm.com>
Date:   Thu Apr 25 13:29:11 2013 +0800

    vnc: Adjust lock state sync logic with VNC_FEATURE_LED_STATE
    
    Signed-off-by: Lei Li <lilei at linux.vnet.ibm.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1366867752-11578-4-git-send-email-lilei at linux.vnet.ibm.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/vnc.c b/ui/vnc.c
index 899833a..b90281b 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -1613,7 +1613,11 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym)
         break;
     }
 
+    /* Turn off the lock state sync logic if the client support the led
+       state extension.
+    */
     if (down && vs->vd->lock_key_sync &&
+        !vnc_has_feature(vs, VNC_FEATURE_LED_STATE) &&
         keycode_is_keypad(vs->vd->kbd_layout, keycode)) {
         /* If the numlock state needs to change then simulate an additional
            keypress before sending this one.  This will happen if the user
@@ -1633,6 +1637,7 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym)
     }
 
     if (down && vs->vd->lock_key_sync &&
+        !vnc_has_feature(vs, VNC_FEATURE_LED_STATE) &&
         ((sym >= 'A' && sym <= 'Z') || (sym >= 'a' && sym <= 'z'))) {
         /* If the capslock state needs to change then simulate an additional
            keypress before sending this one.  This will happen if the user
commit ab99e5c1d9f6a3f6fc2ce3b77b712221c647c7a5
Author: Lei Li <lilei at linux.vnet.ibm.com>
Date:   Thu Apr 25 13:29:10 2013 +0800

    vnc: Support for LED state extension
    
    Signed-off-by: Lei Li <lilei at linux.vnet.ibm.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1366867752-11578-3-git-send-email-lilei at linux.vnet.ibm.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/vnc.c b/ui/vnc.c
index 56fd805..899833a 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -1522,6 +1522,42 @@ static void press_key(VncState *vs, int keysym)
     kbd_put_keycode(keycode | SCANCODE_UP);
 }
 
+static int current_led_state(VncState *vs)
+{
+    int ledstate = 0;
+
+    if (vs->modifiers_state[0x46]) {
+        ledstate |= QEMU_SCROLL_LOCK_LED;
+    }
+    if (vs->modifiers_state[0x45]) {
+        ledstate |= QEMU_NUM_LOCK_LED;
+    }
+    if (vs->modifiers_state[0x3a]) {
+        ledstate |= QEMU_CAPS_LOCK_LED;
+    }
+
+    return ledstate;
+}
+
+static void vnc_led_state_change(VncState *vs)
+{
+    int ledstate = 0;
+
+    if (!vnc_has_feature(vs, VNC_FEATURE_LED_STATE)) {
+        return;
+    }
+
+    ledstate = current_led_state(vs);
+    vnc_lock_output(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, 1, 1, VNC_ENCODING_LED_STATE);
+    vnc_write_u8(vs, ledstate);
+    vnc_unlock_output(vs);
+    vnc_flush(vs);
+}
+
 static void kbd_leds(void *opaque, int ledstate)
 {
     VncState *vs = opaque;
@@ -1540,6 +1576,11 @@ static void kbd_leds(void *opaque, int ledstate)
     if (vs->modifiers_state[0x46] != scr) {
         vs->modifiers_state[0x46] = scr;
     }
+
+    /* Sending the current led state message to the client */
+    if (ledstate != current_led_state(vs)) {
+        vnc_led_state_change(vs);
+    }
 }
 
 static void do_key_event(VncState *vs, int down, int keycode, int sym)
@@ -1893,6 +1934,9 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
         case VNC_ENCODING_WMVi:
             vs->features |= VNC_FEATURE_WMVI_MASK;
             break;
+        case VNC_ENCODING_LED_STATE:
+            vs->features |= VNC_FEATURE_LED_STATE_MASK;
+            break;
         case VNC_ENCODING_COMPRESSLEVEL0 ... VNC_ENCODING_COMPRESSLEVEL0 + 9:
             vs->tight.compression = (enc & 0x0F);
             break;
@@ -1908,6 +1952,7 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
     }
     vnc_desktop_resize(vs);
     check_pointer_type_change(&vs->mouse_mode_notifier, NULL);
+    vnc_led_state_change(vs);
 }
 
 static void set_pixel_conversion(VncState *vs)
diff --git a/ui/vnc.h b/ui/vnc.h
index ad1dec2..fea39ad 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -384,6 +384,7 @@ enum {
 #define VNC_ENCODING_EXT_KEY_EVENT        0XFFFFFEFE /* -258 */
 #define VNC_ENCODING_AUDIO                0XFFFFFEFD /* -259 */
 #define VNC_ENCODING_TIGHT_PNG            0xFFFFFEFC /* -260 */
+#define VNC_ENCODING_LED_STATE            0XFFFFFEFB /* -261 */
 #define VNC_ENCODING_WMVi                 0x574D5669
 
 /*****************************************************************************
@@ -422,6 +423,7 @@ enum {
 #define VNC_FEATURE_TIGHT_PNG                8
 #define VNC_FEATURE_ZRLE                     9
 #define VNC_FEATURE_ZYWRLE                  10
+#define VNC_FEATURE_LED_STATE               11
 
 #define VNC_FEATURE_RESIZE_MASK              (1 << VNC_FEATURE_RESIZE)
 #define VNC_FEATURE_HEXTILE_MASK             (1 << VNC_FEATURE_HEXTILE)
@@ -434,6 +436,7 @@ enum {
 #define VNC_FEATURE_TIGHT_PNG_MASK           (1 << VNC_FEATURE_TIGHT_PNG)
 #define VNC_FEATURE_ZRLE_MASK                (1 << VNC_FEATURE_ZRLE)
 #define VNC_FEATURE_ZYWRLE_MASK              (1 << VNC_FEATURE_ZYWRLE)
+#define VNC_FEATURE_LED_STATE_MASK           (1 << VNC_FEATURE_LED_STATE)
 
 
 /* Client -> Server message IDs */
commit 96f3d174bdfcc7d6205fa223ddc2cb01186dcd8f
Author: Lei Li <lilei at linux.vnet.ibm.com>
Date:   Thu Apr 25 13:29:09 2013 +0800

    vnc: Add SCROLL lock key to kbd_leds
    
    Signed-off-by: Lei Li <lilei at linux.vnet.ibm.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1366867752-11578-2-git-send-email-lilei at linux.vnet.ibm.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/vnc.c b/ui/vnc.c
index 86fe1dd..56fd805 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -1525,10 +1525,11 @@ static void press_key(VncState *vs, int keysym)
 static void kbd_leds(void *opaque, int ledstate)
 {
     VncState *vs = opaque;
-    int caps, num;
+    int caps, num, scr;
 
     caps = ledstate & QEMU_CAPS_LOCK_LED ? 1 : 0;
     num  = ledstate & QEMU_NUM_LOCK_LED  ? 1 : 0;
+    scr  = ledstate & QEMU_SCROLL_LOCK_LED ? 1 : 0;
 
     if (vs->modifiers_state[0x3a] != caps) {
         vs->modifiers_state[0x3a] = caps;
@@ -1536,6 +1537,9 @@ static void kbd_leds(void *opaque, int ledstate)
     if (vs->modifiers_state[0x45] != num) {
         vs->modifiers_state[0x45] = num;
     }
+    if (vs->modifiers_state[0x46] != scr) {
+        vs->modifiers_state[0x46] = scr;
+    }
 }
 
 static void do_key_event(VncState *vs, int down, int keycode, int sym)
commit 1a63e059de2f2936d2066532b9f8ca22675cf11c
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Apr 28 18:45:47 2013 +0200

    libqos: Convert fw_cfg values to host endianness
    
    The fw_cfg ABI is Little Endian, so byte-swap the generically read
    byte array to host endianness.
    
    This unbreaks the fw_cfg tests on ppc.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Message-id: 1367167547-19931-1-git-send-email-afaerber at suse.de
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/tests/libqos/fw_cfg.c b/tests/libqos/fw_cfg.c
index 799139e..e386ff7 100644
--- a/tests/libqos/fw_cfg.c
+++ b/tests/libqos/fw_cfg.c
@@ -11,6 +11,7 @@
  */
 
 #include "libqos/fw_cfg.h"
+#include "qemu/bswap.h"
 
 void qfw_cfg_select(QFWCFG *fw_cfg, uint16_t key)
 {
@@ -32,20 +33,20 @@ uint16_t qfw_cfg_get_u16(QFWCFG *fw_cfg, uint16_t key)
 {
     uint16_t value;
     qfw_cfg_get(fw_cfg, key, &value, sizeof(value));
-    return value;
+    return le16_to_cpu(value);
 }
 
 uint32_t qfw_cfg_get_u32(QFWCFG *fw_cfg, uint16_t key)
 {
     uint32_t value;
     qfw_cfg_get(fw_cfg, key, &value, sizeof(value));
-    return value;
+    return le32_to_cpu(value);
 }
 
 uint64_t qfw_cfg_get_u64(QFWCFG *fw_cfg, uint16_t key)
 {
     uint64_t value;
     qfw_cfg_get(fw_cfg, key, &value, sizeof(value));
-    return value;
+    return le64_to_cpu(value);
 }
 
commit 61e477f4c731c4ff3f1a44dbfc55c8a5903c8d52
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Apr 27 22:18:55 2013 +0200

    wdt_ib700: QOM'ify
    
    Introduce type constant and cast macro to obsolete DO_UPCAST().
    
    Prepares for ISA realizefn.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Message-id: 1367093935-29091-21-git-send-email-afaerber at suse.de
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/watchdog/wdt_ib700.c b/hw/watchdog/wdt_ib700.c
index b8c4be8..6b8e33a 100644
--- a/hw/watchdog/wdt_ib700.c
+++ b/hw/watchdog/wdt_ib700.c
@@ -35,8 +35,12 @@
 #define ib700_debug(fs,...)
 #endif
 
+#define TYPE_IB700 "ib700"
+#define IB700(obj) OBJECT_CHECK(IB700State, (obj), TYPE_IB700)
+
 typedef struct IB700state {
-    ISADevice dev;
+    ISADevice parent_obj;
+
     QEMUTimer *timer;
 } IB700State;
 
@@ -95,7 +99,7 @@ static const VMStateDescription vmstate_ib700 = {
 
 static int wdt_ib700_init(ISADevice *dev)
 {
-    IB700State *s = DO_UPCAST(IB700State, dev, dev);
+    IB700State *s = IB700(dev);
 
     ib700_debug("watchdog init\n");
 
@@ -108,7 +112,7 @@ static int wdt_ib700_init(ISADevice *dev)
 
 static void wdt_ib700_reset(DeviceState *dev)
 {
-    IB700State *s = DO_UPCAST(IB700State, dev.qdev, dev);
+    IB700State *s = IB700(dev);
 
     ib700_debug("watchdog reset\n");
 
@@ -130,7 +134,7 @@ static void wdt_ib700_class_init(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo wdt_ib700_info = {
-    .name          = "ib700",
+    .name          = TYPE_IB700,
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(IB700State),
     .class_init    = wdt_ib700_class_init,
commit f02317ad4eca65a9a79b474b6d2d77ba87a57185
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Apr 27 22:18:54 2013 +0200

    vmport: QOM'ify
    
    Introduce type constant and cast macro to obsolete DO_UPCAST().
    Prepares for ISA realizefn.
    
    Drop reserved underscore from struct name while at it.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Message-id: 1367093935-29091-20-git-send-email-afaerber at suse.de
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/misc/vmport.c b/hw/misc/vmport.c
index 0d07ea1..c146129 100644
--- a/hw/misc/vmport.c
+++ b/hw/misc/vmport.c
@@ -35,9 +35,13 @@
 #define VMPORT_ENTRIES 0x2c
 #define VMPORT_MAGIC   0x564D5868
 
-typedef struct _VMPortState
+#define TYPE_VMPORT "vmport"
+#define VMPORT(obj) OBJECT_CHECK(VMPortState, (obj), TYPE_VMPORT)
+
+typedef struct VMPortState
 {
-    ISADevice dev;
+    ISADevice parent_obj;
+
     MemoryRegion io;
     IOPortReadFunc *func[VMPORT_ENTRIES];
     void *opaque[VMPORT_ENTRIES];
@@ -135,7 +139,7 @@ static const MemoryRegionOps vmport_ops = {
 
 static int vmport_initfn(ISADevice *dev)
 {
-    VMPortState *s = DO_UPCAST(VMPortState, dev, dev);
+    VMPortState *s = VMPORT(dev);
 
     memory_region_init_io(&s->io, &vmport_ops, s, "vmport", 1);
     isa_register_ioport(dev, &s->io, 0x5658);
@@ -156,7 +160,7 @@ static void vmport_class_initfn(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo vmport_info = {
-    .name          = "vmport",
+    .name          = TYPE_VMPORT,
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(VMPortState),
     .class_init    = vmport_class_initfn,
commit e3b7fbead827623ce521c8056a80050e8b35c578
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Apr 27 22:18:53 2013 +0200

    vmmouse: QOM'ify
    
    Introduce type constant and cast macro to obsolete DO_UPCAST() and
    container_of(). Prepares for ISA realizefn.
    
    Remove reserved underscore from struct name while at it.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Message-id: 1367093935-29091-19-git-send-email-afaerber at suse.de
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/input/vmmouse.c b/hw/input/vmmouse.c
index f4f9c93..a610738 100644
--- a/hw/input/vmmouse.c
+++ b/hw/input/vmmouse.c
@@ -51,9 +51,13 @@
 #define DPRINTF(fmt, ...) do { } while (0)
 #endif
 
-typedef struct _VMMouseState
+#define TYPE_VMMOUSE "vmmouse"
+#define VMMOUSE(obj) OBJECT_CHECK(VMMouseState, (obj), TYPE_VMMOUSE)
+
+typedef struct VMMouseState
 {
-    ISADevice dev;
+    ISADevice parent_obj;
+
     uint32_t queue[VMMOUSE_QUEUE_SIZE];
     int32_t queue_size;
     uint16_t nb_queue;
@@ -250,7 +254,7 @@ static const VMStateDescription vmstate_vmmouse = {
 
 static void vmmouse_reset(DeviceState *d)
 {
-    VMMouseState *s = container_of(d, VMMouseState, dev.qdev);
+    VMMouseState *s = VMMOUSE(d);
 
     s->queue_size = VMMOUSE_QUEUE_SIZE;
 
@@ -259,7 +263,7 @@ static void vmmouse_reset(DeviceState *d)
 
 static int vmmouse_initfn(ISADevice *dev)
 {
-    VMMouseState *s = DO_UPCAST(VMMouseState, dev, dev);
+    VMMouseState *s = VMMOUSE(dev);
 
     DPRINTF("vmmouse_init\n");
 
@@ -287,7 +291,7 @@ static void vmmouse_class_initfn(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo vmmouse_info = {
-    .name          = "vmmouse",
+    .name          = TYPE_VMMOUSE,
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(VMMouseState),
     .class_init    = vmmouse_class_initfn,
commit a72dc5fc67cd2412be35dc17698a4eb4f7e00a0c
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Apr 27 22:18:52 2013 +0200

    vga-isa: QOM'ify ISA VGA
    
    Introduce type constant and cast macro to obsolete DO_UPCAST() and
    container_of(). Prepares for ISA realizefn.
    
    Unify function naming scheme while at it.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Message-id: 1367093935-29091-18-git-send-email-afaerber at suse.de
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/display/vga-isa.c b/hw/display/vga-isa.c
index 2b3cc9b..9e63b69 100644
--- a/hw/display/vga-isa.c
+++ b/hw/display/vga-isa.c
@@ -31,14 +31,18 @@
 #include "qemu/timer.h"
 #include "hw/loader.h"
 
+#define TYPE_ISA_VGA "isa-vga"
+#define ISA_VGA(obj) OBJECT_CHECK(ISAVGAState, (obj), TYPE_ISA_VGA)
+
 typedef struct ISAVGAState {
-    ISADevice dev;
+    ISADevice parent_obj;
+
     struct VGACommonState state;
 } ISAVGAState;
 
-static void vga_reset_isa(DeviceState *dev)
+static void vga_isa_reset(DeviceState *dev)
 {
-    ISAVGAState *d = container_of(dev, ISAVGAState, dev.qdev);
+    ISAVGAState *d = ISA_VGA(dev);
     VGACommonState *s = &d->state;
 
     vga_common_reset(s);
@@ -46,7 +50,7 @@ static void vga_reset_isa(DeviceState *dev)
 
 static int vga_initfn(ISADevice *dev)
 {
-    ISAVGAState *d = DO_UPCAST(ISAVGAState, dev, dev);
+    ISAVGAState *d = ISA_VGA(dev);
     VGACommonState *s = &d->state;
     MemoryRegion *vga_io_memory;
     const MemoryRegionPortio *vga_ports, *vbe_ports;
@@ -75,26 +79,27 @@ static Property vga_isa_properties[] = {
     DEFINE_PROP_END_OF_LIST(),
 };
 
-static void vga_class_initfn(ObjectClass *klass, void *data)
+static void vga_isa_class_initfn(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
+
     ic->init = vga_initfn;
-    dc->reset = vga_reset_isa;
+    dc->reset = vga_isa_reset;
     dc->vmsd = &vmstate_vga_common;
     dc->props = vga_isa_properties;
 }
 
-static const TypeInfo vga_info = {
-    .name          = "isa-vga",
+static const TypeInfo vga_isa_info = {
+    .name          = TYPE_ISA_VGA,
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(ISAVGAState),
-    .class_init    = vga_class_initfn,
+    .class_init    = vga_isa_class_initfn,
 };
 
-static void vga_register_types(void)
+static void vga_isa_register_types(void)
 {
-    type_register_static(&vga_info);
+    type_register_static(&vga_isa_info);
 }
 
-type_init(vga_register_types)
+type_init(vga_isa_register_types)
commit b582b5a398975d875d7e0b1c8f90817d01a8b20a
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Apr 27 22:18:51 2013 +0200

    sga: QOM'ify
    
    Introduce type constant and cast macro.
    
    Prepares for ISA realizefn.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Message-id: 1367093935-29091-17-git-send-email-afaerber at suse.de
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/misc/sga.c b/hw/misc/sga.c
index 5cf4b86..c842190 100644
--- a/hw/misc/sga.c
+++ b/hw/misc/sga.c
@@ -31,8 +31,11 @@
 
 #define SGABIOS_FILENAME "sgabios.bin"
 
-typedef struct ISAGAState {
-    ISADevice dev;
+#define TYPE_SGA "sga"
+#define SGA(obj) OBJECT_CHECK(ISASGAState, (obj), TYPE_SGA)
+
+typedef struct ISASGAState {
+    ISADevice parent_obj;
 } ISASGAState;
 
 static int sga_initfn(ISADevice *dev)
@@ -40,6 +43,7 @@ static int sga_initfn(ISADevice *dev)
     rom_add_vga(SGABIOS_FILENAME);
     return 0;
 }
+
 static void sga_class_initfn(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
@@ -49,7 +53,7 @@ static void sga_class_initfn(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo sga_info = {
-    .name          = "sga",
+    .name          = TYPE_SGA,
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(ISASGAState),
     .class_init    = sga_class_initfn,
commit eeceb0849de2126185cf71860a449667fac2f0d7
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Apr 27 22:18:50 2013 +0200

    serial: QOM'ify ISA serial
    
    Introduce type constant and cast macro to obsolete DO_UPCAST().
    
    Prepares for ISA realizefn.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Message-id: 1367093935-29091-16-git-send-email-afaerber at suse.de
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/char/serial-isa.c b/hw/char/serial-isa.c
index ed140d0..342b4cc 100644
--- a/hw/char/serial-isa.c
+++ b/hw/char/serial-isa.c
@@ -26,8 +26,11 @@
 #include "hw/char/serial.h"
 #include "hw/isa/isa.h"
 
+#define ISA_SERIAL(obj) OBJECT_CHECK(ISASerialState, (obj), TYPE_ISA_SERIAL)
+
 typedef struct ISASerialState {
-    ISADevice dev;
+    ISADevice parent_obj;
+
     uint32_t index;
     uint32_t iobase;
     uint32_t isairq;
@@ -44,7 +47,7 @@ static const int isa_serial_irq[MAX_SERIAL_PORTS] = {
 static int serial_isa_initfn(ISADevice *dev)
 {
     static int index;
-    ISASerialState *isa = DO_UPCAST(ISASerialState, dev, dev);
+    ISASerialState *isa = ISA_SERIAL(dev);
     SerialState *s = &isa->state;
 
     if (isa->index == -1) {
@@ -100,7 +103,7 @@ static void serial_isa_class_initfn(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo serial_isa_info = {
-    .name          = "isa-serial",
+    .name          = TYPE_ISA_SERIAL,
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(ISASerialState),
     .class_init    = serial_isa_class_initfn,
@@ -117,7 +120,7 @@ bool serial_isa_init(ISABus *bus, int index, CharDriverState *chr)
 {
     ISADevice *dev;
 
-    dev = isa_try_create(bus, "isa-serial");
+    dev = isa_try_create(bus, TYPE_ISA_SERIAL);
     if (!dev) {
         return false;
     }
diff --git a/include/hw/char/serial.h b/include/hw/char/serial.h
index e884499..bca79f1 100644
--- a/include/hw/char/serial.h
+++ b/include/hw/char/serial.h
@@ -96,6 +96,7 @@ SerialState *serial_mm_init(MemoryRegion *address_space,
                             CharDriverState *chr, enum device_endian end);
 
 /* serial-isa.c */
+#define TYPE_ISA_SERIAL "isa-serial"
 bool serial_isa_init(ISABus *bus, int index, CharDriverState *chr);
 
 #endif
commit 399f05a6e181c07611a93ac73025605cf24c4a6c
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Apr 27 22:18:49 2013 +0200

    sb16: QOM'ify
    
    Introduce type constant and cast macro to obsolete DO_UPCAST().
    
    Prepares for ISA realizefn.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Message-id: 1367093935-29091-15-git-send-email-afaerber at suse.de
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/audio/sb16.c b/hw/audio/sb16.c
index 783b6b4..61583bc 100644
--- a/hw/audio/sb16.c
+++ b/hw/audio/sb16.c
@@ -47,8 +47,12 @@
 
 static const char e3[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
 
+#define TYPE_SB16 "sb16"
+#define SB16(obj) OBJECT_CHECK (SB16State, (obj), TYPE_SB16)
+
 typedef struct SB16State {
-    ISADevice dev;
+    ISADevice parent_obj;
+
     QEMUSoundCard card;
     qemu_irq pic;
     uint32_t irq;
@@ -1354,9 +1358,7 @@ static const MemoryRegionPortio sb16_ioport_list[] = {
 
 static int sb16_initfn (ISADevice *dev)
 {
-    SB16State *s;
-
-    s = DO_UPCAST (SB16State, dev, dev);
+    SB16State *s = SB16 (dev);
 
     s->cmd = -1;
     isa_init_irq (dev, &s->pic, s->irq);
@@ -1386,7 +1388,7 @@ static int sb16_initfn (ISADevice *dev)
 
 int SB16_init (ISABus *bus)
 {
-    isa_create_simple (bus, "sb16");
+    isa_create_simple (bus, TYPE_SB16);
     return 0;
 }
 
@@ -1410,7 +1412,7 @@ static void sb16_class_initfn (ObjectClass *klass, void *data)
 }
 
 static const TypeInfo sb16_info = {
-    .name          = "sb16",
+    .name          = TYPE_SB16,
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof (SB16State),
     .class_init    = sb16_class_initfn,
commit d367ece5e51d4f48687813eb5fe8d2a0e2e728d2
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Apr 27 22:18:48 2013 +0200

    pcspk: QOM'ify
    
    Introduce type constant and cast macro to obsolete DO_UPCAST().
    
    Prepares for ISA realizefn.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Message-id: 1367093935-29091-14-git-send-email-afaerber at suse.de
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c
index 34e0df7..d844e85 100644
--- a/hw/audio/pcspk.c
+++ b/hw/audio/pcspk.c
@@ -35,8 +35,11 @@
 #define PCSPK_MAX_FREQ (PCSPK_SAMPLE_RATE >> 1)
 #define PCSPK_MIN_COUNT ((PIT_FREQ + PCSPK_MAX_FREQ - 1) / PCSPK_MAX_FREQ)
 
+#define PC_SPEAKER(obj) OBJECT_CHECK(PCSpkState, (obj), TYPE_PC_SPEAKER)
+
 typedef struct {
-    ISADevice dev;
+    ISADevice parent_obj;
+
     MemoryRegion ioport;
     uint32_t iobase;
     uint8_t sample_buf[PCSPK_BUF_LEN];
@@ -161,7 +164,7 @@ static const MemoryRegionOps pcspk_io_ops = {
 
 static int pcspk_initfn(ISADevice *dev)
 {
-    PCSpkState *s = DO_UPCAST(PCSpkState, dev, dev);
+    PCSpkState *s = PC_SPEAKER(dev);
 
     memory_region_init_io(&s->ioport, &pcspk_io_ops, s, "elcr", 1);
     isa_register_ioport(dev, &s->ioport, s->iobase);
@@ -188,7 +191,7 @@ static void pcspk_class_initfn(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo pcspk_info = {
-    .name           = "isa-pcspk",
+    .name           = TYPE_PC_SPEAKER,
     .parent         = TYPE_ISA_DEVICE,
     .instance_size  = sizeof(PCSpkState),
     .class_init     = pcspk_class_initfn,
diff --git a/include/hw/audio/pcspk.h b/include/hw/audio/pcspk.h
index ce8ef4f..b60c000 100644
--- a/include/hw/audio/pcspk.h
+++ b/include/hw/audio/pcspk.h
@@ -28,11 +28,13 @@
 #include "hw/hw.h"
 #include "hw/isa/isa.h"
 
+#define TYPE_PC_SPEAKER "isa-pcspk"
+
 static inline ISADevice *pcspk_init(ISABus *bus, ISADevice *pit)
 {
     ISADevice *dev;
 
-    dev = isa_create(bus, "isa-pcspk");
+    dev = isa_create(bus, TYPE_PC_SPEAKER);
     qdev_prop_set_uint32(&dev->qdev, "iobase", 0x61);
     qdev_prop_set_ptr(&dev->qdev, "pit", pit);
     qdev_init_nofail(&dev->qdev);
commit a2e0b863ebec1c9ceea9b7aab022a6378ea74136
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Apr 27 22:18:47 2013 +0200

    pckbd: QOM'ify
    
    Introduce type constant and cast macro to obsolete DO_UPCAST().
    
    Prepares for ISA realizefn.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Message-id: 1367093935-29091-13-git-send-email-afaerber at suse.de
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/input/pckbd.c b/hw/input/pckbd.c
index 08ceb9f..17a5614 100644
--- a/hw/input/pckbd.c
+++ b/hw/input/pckbd.c
@@ -431,8 +431,12 @@ void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq,
     qemu_register_reset(kbd_reset, s);
 }
 
+#define TYPE_I8042 "i8042"
+#define I8042(obj) OBJECT_CHECK(ISAKBDState, (obj), TYPE_I8042)
+
 typedef struct ISAKBDState {
-    ISADevice dev;
+    ISADevice parent_obj;
+
     KBDState kbd;
     MemoryRegion io[2];
 } ISAKBDState;
@@ -440,14 +444,16 @@ typedef struct ISAKBDState {
 void i8042_isa_mouse_fake_event(void *opaque)
 {
     ISADevice *dev = opaque;
-    KBDState *s = &(DO_UPCAST(ISAKBDState, dev, dev)->kbd);
+    ISAKBDState *isa = I8042(dev);
+    KBDState *s = &isa->kbd;
 
     ps2_mouse_fake_event(s->mouse);
 }
 
 void i8042_setup_a20_line(ISADevice *dev, qemu_irq *a20_out)
 {
-    KBDState *s = &(DO_UPCAST(ISAKBDState, dev, dev)->kbd);
+    ISAKBDState *isa = I8042(dev);
+    KBDState *s = &isa->kbd;
 
     s->a20_out = a20_out;
 }
@@ -485,7 +491,7 @@ static const MemoryRegionOps i8042_cmd_ops = {
 
 static int i8042_initfn(ISADevice *dev)
 {
-    ISAKBDState *isa_s = DO_UPCAST(ISAKBDState, dev, dev);
+    ISAKBDState *isa_s = I8042(dev);
     KBDState *s = &isa_s->kbd;
 
     isa_init_irq(dev, &s->irq_kbd, 1);
@@ -513,7 +519,7 @@ static void i8042_class_initfn(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo i8042_info = {
-    .name          = "i8042",
+    .name          = TYPE_I8042,
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(ISAKBDState),
     .class_init    = i8042_class_initfn,
commit a0881c64081f750be2e44a9b7000e18e4cea065e
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Apr 27 22:18:46 2013 +0200

    pc: QOM'ify port 92
    
    Introduce type constant and cast macro to obsolete DO_UPCAST().
    
    Prepares for ISA realizefn.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Message-id: 1367093935-29091-12-git-send-email-afaerber at suse.de
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 0d6e72b..29d2703 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -429,9 +429,13 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
     qemu_register_reset(pc_cmos_init_late, &arg);
 }
 
+#define TYPE_PORT92 "port92"
+#define PORT92(obj) OBJECT_CHECK(Port92State, (obj), TYPE_PORT92)
+
 /* port 92 stuff: could be split off */
 typedef struct Port92State {
-    ISADevice dev;
+    ISADevice parent_obj;
+
     MemoryRegion io;
     uint8_t outport;
     qemu_irq *a20_out;
@@ -463,7 +467,7 @@ static uint64_t port92_read(void *opaque, hwaddr addr,
 
 static void port92_init(ISADevice *dev, qemu_irq *a20_out)
 {
-    Port92State *s = DO_UPCAST(Port92State, dev, dev);
+    Port92State *s = PORT92(dev);
 
     s->a20_out = a20_out;
 }
@@ -481,7 +485,7 @@ static const VMStateDescription vmstate_port92_isa = {
 
 static void port92_reset(DeviceState *d)
 {
-    Port92State *s = container_of(d, Port92State, dev.qdev);
+    Port92State *s = PORT92(d);
 
     s->outport &= ~1;
 }
@@ -498,7 +502,7 @@ static const MemoryRegionOps port92_ops = {
 
 static int port92_initfn(ISADevice *dev)
 {
-    Port92State *s = DO_UPCAST(Port92State, dev, dev);
+    Port92State *s = PORT92(dev);
 
     memory_region_init_io(&s->io, &port92_ops, s, "port92", 1);
     isa_register_ioport(dev, &s->io, 0x92);
@@ -518,7 +522,7 @@ static void port92_class_initfn(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo port92_info = {
-    .name          = "port92",
+    .name          = TYPE_PORT92,
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(Port92State),
     .class_init    = port92_class_initfn,
commit b0dc5ee6bd0b16986a0f45ca778f3ead2398b2ee
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Apr 27 22:18:45 2013 +0200

    parallel: QOM'ify
    
    Introduce type constant and cast macro to obsolete DO_UPCAST().
    
    Prepares for ISA realizefn.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Message-id: 1367093935-29091-11-git-send-email-afaerber at suse.de
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/char/parallel.c b/hw/char/parallel.c
index b5e867f..8e48284 100644
--- a/hw/char/parallel.c
+++ b/hw/char/parallel.c
@@ -80,8 +80,13 @@ typedef struct ParallelState {
     int it_shift;
 } ParallelState;
 
+#define TYPE_ISA_PARALLEL "isa-parallel"
+#define ISA_PARALLEL(obj) \
+    OBJECT_CHECK(ISAParallelState, (obj), TYPE_ISA_PARALLEL)
+
 typedef struct ISAParallelState {
-    ISADevice dev;
+    ISADevice parent_obj;
+
     uint32_t index;
     uint32_t iobase;
     uint32_t isairq;
@@ -475,7 +480,7 @@ static const MemoryRegionPortio isa_parallel_portio_sw_list[] = {
 static int parallel_isa_initfn(ISADevice *dev)
 {
     static int index;
-    ISAParallelState *isa = DO_UPCAST(ISAParallelState, dev, dev);
+    ISAParallelState *isa = ISA_PARALLEL(dev);
     ParallelState *s = &isa->state;
     int base;
     uint8_t dummy;
@@ -600,7 +605,7 @@ static void parallel_isa_class_initfn(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo parallel_isa_info = {
-    .name          = "isa-parallel",
+    .name          = TYPE_ISA_PARALLEL,
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(ISAParallelState),
     .class_init    = parallel_isa_class_initfn,
commit fe6f5deb6611c512abcb4cb46a275756295b3e79
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Apr 27 22:18:44 2013 +0200

    ne2000-isa: QOM'ify
    
    Introduce type constant and cast macro to obsolete DO_UPCAST().
    
    Prepares for ISA realizefn.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Message-id: 1367093935-29091-10-git-send-email-afaerber at suse.de
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/net/ne2000-isa.c b/hw/net/ne2000-isa.c
index a093aa8..f8e610c 100644
--- a/hw/net/ne2000-isa.c
+++ b/hw/net/ne2000-isa.c
@@ -29,8 +29,12 @@
 #include "ne2000.h"
 #include "exec/address-spaces.h"
 
+#define TYPE_ISA_NE2000 "ne2k_isa"
+#define ISA_NE2000(obj) OBJECT_CHECK(ISANE2000State, (obj), TYPE_ISA_NE2000)
+
 typedef struct ISANE2000State {
-    ISADevice dev;
+    ISADevice parent_obj;
+
     uint32_t iobase;
     uint32_t isairq;
     NE2000State ne2000;
@@ -64,7 +68,7 @@ static const VMStateDescription vmstate_isa_ne2000 = {
 
 static int isa_ne2000_initfn(ISADevice *dev)
 {
-    ISANE2000State *isa = DO_UPCAST(ISANE2000State, dev, dev);
+    ISANE2000State *isa = ISA_NE2000(dev);
     NE2000State *s = &isa->ne2000;
 
     ne2000_setup_io(s, 0x20);
@@ -98,7 +102,7 @@ static void isa_ne2000_class_initfn(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo ne2000_isa_info = {
-    .name          = "ne2k_isa",
+    .name          = TYPE_ISA_NE2000,
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(ISANE2000State),
     .class_init    = isa_ne2000_class_initfn,
commit 0e41271ec4944ea5b63c98b8e497618709e954c3
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Apr 27 22:18:43 2013 +0200

    mc146818rtc: QOM'ify
    
    Introduce type constant and cast macro to obsolete DO_UPCAST().
    
    Prepares for ISA realizefn.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Reviewed-by: Igor Mammedov <imammedo at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Message-id: 1367093935-29091-9-git-send-email-afaerber at suse.de
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index 69e6844..afbd0db 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -57,8 +57,11 @@
 #define RTC_CLOCK_RATE            32768
 #define UIP_HOLD_LENGTH           (8 * NSEC_PER_SEC / 32768)
 
+#define MC146818_RTC(obj) OBJECT_CHECK(RTCState, (obj), TYPE_MC146818_RTC)
+
 typedef struct RTCState {
-    ISADevice dev;
+    ISADevice parent_obj;
+
     MemoryRegion io;
     uint8_t cmos_data[128];
     uint8_t cmos_index;
@@ -672,14 +675,14 @@ static uint64_t cmos_ioport_read(void *opaque, hwaddr addr,
 
 void rtc_set_memory(ISADevice *dev, int addr, int val)
 {
-    RTCState *s = DO_UPCAST(RTCState, dev, dev);
+    RTCState *s = MC146818_RTC(dev);
     if (addr >= 0 && addr <= 127)
         s->cmos_data[addr] = val;
 }
 
 static void rtc_set_date_from_host(ISADevice *dev)
 {
-    RTCState *s = DO_UPCAST(RTCState, dev, dev);
+    RTCState *s = MC146818_RTC(dev);
     struct tm tm;
 
     qemu_get_timedate(&tm, 0);
@@ -741,7 +744,7 @@ static void rtc_notify_clock_reset(Notifier *notifier, void *data)
     RTCState *s = container_of(notifier, RTCState, clock_reset_notifier);
     int64_t now = *(int64_t *)data;
 
-    rtc_set_date_from_host(&s->dev);
+    rtc_set_date_from_host(ISA_DEVICE(s));
     periodic_timer_update(s, now);
     check_update_timer(s);
 #ifdef TARGET_I386
@@ -756,7 +759,7 @@ static void rtc_notify_clock_reset(Notifier *notifier, void *data)
 static void rtc_notify_suspend(Notifier *notifier, void *data)
 {
     RTCState *s = container_of(notifier, RTCState, suspend_notifier);
-    rtc_set_memory(&s->dev, 0xF, 0xFE);
+    rtc_set_memory(ISA_DEVICE(s), 0xF, 0xFE);
 }
 
 static void rtc_reset(void *opaque)
@@ -789,8 +792,7 @@ static const MemoryRegionOps cmos_ops = {
 static void rtc_get_date(Object *obj, Visitor *v, void *opaque,
                          const char *name, Error **errp)
 {
-    ISADevice *isa = ISA_DEVICE(obj);
-    RTCState *s = DO_UPCAST(RTCState, dev, isa);
+    RTCState *s = MC146818_RTC(obj);
     struct tm current_tm;
 
     rtc_update_time(s);
@@ -807,7 +809,7 @@ static void rtc_get_date(Object *obj, Visitor *v, void *opaque,
 
 static int rtc_initfn(ISADevice *dev)
 {
-    RTCState *s = DO_UPCAST(RTCState, dev, dev);
+    RTCState *s = MC146818_RTC(dev);
     int base = 0x70;
 
     s->cmos_data[RTC_REG_A] = 0x26;
@@ -866,19 +868,21 @@ static int rtc_initfn(ISADevice *dev)
 
 ISADevice *rtc_init(ISABus *bus, int base_year, qemu_irq intercept_irq)
 {
-    ISADevice *dev;
+    DeviceState *dev;
+    ISADevice *isadev;
     RTCState *s;
 
-    dev = isa_create(bus, "mc146818rtc");
-    s = DO_UPCAST(RTCState, dev, dev);
-    qdev_prop_set_int32(&dev->qdev, "base_year", base_year);
-    qdev_init_nofail(&dev->qdev);
+    isadev = isa_create(bus, TYPE_MC146818_RTC);
+    dev = DEVICE(isadev);
+    s = MC146818_RTC(isadev);
+    qdev_prop_set_int32(dev, "base_year", base_year);
+    qdev_init_nofail(dev);
     if (intercept_irq) {
         s->irq = intercept_irq;
     } else {
-        isa_init_irq(dev, &s->irq, RTC_ISA_IRQ);
+        isa_init_irq(isadev, &s->irq, RTC_ISA_IRQ);
     }
-    return dev;
+    return isadev;
 }
 
 static Property mc146818rtc_properties[] = {
@@ -899,7 +903,7 @@ static void rtc_class_initfn(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo mc146818rtc_info = {
-    .name          = "mc146818rtc",
+    .name          = TYPE_MC146818_RTC,
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(RTCState),
     .class_init    = rtc_class_initfn,
diff --git a/include/hw/timer/mc146818rtc.h b/include/hw/timer/mc146818rtc.h
index 854ea3f..425bd17 100644
--- a/include/hw/timer/mc146818rtc.h
+++ b/include/hw/timer/mc146818rtc.h
@@ -4,6 +4,8 @@
 #include "hw/isa/isa.h"
 #include "hw/timer/mc146818rtc_regs.h"
 
+#define TYPE_MC146818_RTC "mc146818rtc"
+
 ISADevice *rtc_init(ISABus *bus, int base_year, qemu_irq intercept_irq);
 void rtc_set_memory(ISADevice *dev, int addr, int val);
 void rtc_set_date(ISADevice *dev, const struct tm *tm);
commit a2772c70a9617c73875c5ee915b32ccb50f0bf90
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Apr 27 22:18:42 2013 +0200

    m48t59: QOM'ify ISA M48T59 NVRAM
    
    Introduce type constant and cast macro to obsolete DO_UPCAST() and
    container_of().
    
    Prepares for ISA realizefn.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Message-id: 1367093935-29091-8-git-send-email-afaerber at suse.de
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/timer/m48t59.c b/hw/timer/m48t59.c
index 5019e06..45753d8 100644
--- a/hw/timer/m48t59.c
+++ b/hw/timer/m48t59.c
@@ -72,8 +72,13 @@ struct M48t59State {
     uint8_t  lock;
 };
 
+#define TYPE_ISA_M48T59 "m48t59_isa"
+#define ISA_M48T59(obj) \
+    OBJECT_CHECK(M48t59ISAState, (obj), TYPE_ISA_M48T59)
+
 typedef struct M48t59ISAState {
-    ISADevice busdev;
+    ISADevice parent_obj;
+
     M48t59State state;
     MemoryRegion io;
 } M48t59ISAState;
@@ -608,7 +613,7 @@ static void m48t59_reset_common(M48t59State *NVRAM)
 
 static void m48t59_reset_isa(DeviceState *d)
 {
-    M48t59ISAState *isa = container_of(d, M48t59ISAState, busdev.qdev);
+    M48t59ISAState *isa = ISA_M48T59(d);
     M48t59State *NVRAM = &isa->state;
 
     m48t59_reset_common(NVRAM);
@@ -665,20 +670,22 @@ M48t59State *m48t59_init_isa(ISABus *bus, uint32_t io_base, uint16_t size,
                              int model)
 {
     M48t59ISAState *d;
-    ISADevice *dev;
+    ISADevice *isadev;
+    DeviceState *dev;
     M48t59State *s;
 
-    dev = isa_create(bus, "m48t59_isa");
-    qdev_prop_set_uint32(&dev->qdev, "model", model);
-    qdev_prop_set_uint32(&dev->qdev, "size", size);
-    qdev_prop_set_uint32(&dev->qdev, "io_base", io_base);
-    qdev_init_nofail(&dev->qdev);
-    d = DO_UPCAST(M48t59ISAState, busdev, dev);
+    isadev = isa_create(bus, TYPE_ISA_M48T59);
+    dev = DEVICE(isadev);
+    qdev_prop_set_uint32(dev, "model", model);
+    qdev_prop_set_uint32(dev, "size", size);
+    qdev_prop_set_uint32(dev, "io_base", io_base);
+    qdev_init_nofail(dev);
+    d = ISA_M48T59(isadev);
     s = &d->state;
 
     memory_region_init_io(&d->io, &m48t59_io_ops, s, "m48t59", 4);
     if (io_base != 0) {
-        isa_register_ioport(dev, &d->io, io_base);
+        isa_register_ioport(isadev, &d->io, io_base);
     }
 
     return s;
@@ -698,7 +705,7 @@ static void m48t59_init_common(M48t59State *s)
 
 static int m48t59_init_isa1(ISADevice *dev)
 {
-    M48t59ISAState *d = DO_UPCAST(M48t59ISAState, busdev, dev);
+    M48t59ISAState *d = ISA_M48T59(dev);
     M48t59State *s = &d->state;
 
     isa_init_irq(dev, &s->IRQ, 8);
@@ -728,7 +735,7 @@ static Property m48t59_isa_properties[] = {
     DEFINE_PROP_END_OF_LIST(),
 };
 
-static void m48t59_init_class_isa1(ObjectClass *klass, void *data)
+static void m48t59_isa_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
@@ -739,10 +746,10 @@ static void m48t59_init_class_isa1(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo m48t59_isa_info = {
-    .name          = "m48t59_isa",
+    .name          = TYPE_ISA_M48T59,
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(M48t59ISAState),
-    .class_init    = m48t59_init_class_isa1,
+    .class_init    = m48t59_isa_class_init,
 };
 
 static Property m48t59_properties[] = {
commit 2f12688b9310a0001330df71d22ad6dc9f39dd29
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Apr 27 22:18:41 2013 +0200

    ide: QOM'ify ISA IDE
    
    Introduce type constant and cast macro to obsolete DO_UPCAST().
    Add missing braces.
    
    Prepares for ISA realizefn.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Message-id: 1367093935-29091-7-git-send-email-afaerber at suse.de
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/ide/isa.c b/hw/ide/isa.c
index e0d47bf..5e7422f 100644
--- a/hw/ide/isa.c
+++ b/hw/ide/isa.c
@@ -33,8 +33,12 @@
 /***********************************************************/
 /* ISA IDE definitions */
 
+#define TYPE_ISA_IDE "isa-ide"
+#define ISA_IDE(obj) OBJECT_CHECK(ISAIDEState, (obj), TYPE_ISA_IDE)
+
 typedef struct ISAIDEState {
-    ISADevice dev;
+    ISADevice parent_obj;
+
     IDEBus    bus;
     uint32_t  iobase;
     uint32_t  iobase2;
@@ -44,7 +48,7 @@ typedef struct ISAIDEState {
 
 static void isa_ide_reset(DeviceState *d)
 {
-    ISAIDEState *s = container_of(d, ISAIDEState, dev.qdev);
+    ISAIDEState *s = ISA_IDE(d);
 
     ide_bus_reset(&s->bus);
 }
@@ -63,9 +67,9 @@ static const VMStateDescription vmstate_ide_isa = {
 
 static int isa_ide_initfn(ISADevice *dev)
 {
-    ISAIDEState *s = DO_UPCAST(ISAIDEState, dev, dev);
+    ISAIDEState *s = ISA_IDE(dev);
 
-    ide_bus_new(&s->bus, &s->dev.qdev, 0);
+    ide_bus_new(&s->bus, DEVICE(dev), 0);
     ide_init_ioport(&s->bus, dev, s->iobase, s->iobase2);
     isa_init_irq(dev, &s->irq, s->isairq);
     ide_init2(&s->bus, s->irq);
@@ -76,22 +80,27 @@ static int isa_ide_initfn(ISADevice *dev)
 ISADevice *isa_ide_init(ISABus *bus, int iobase, int iobase2, int isairq,
                         DriveInfo *hd0, DriveInfo *hd1)
 {
-    ISADevice *dev;
+    DeviceState *dev;
+    ISADevice *isadev;
     ISAIDEState *s;
 
-    dev = isa_create(bus, "isa-ide");
-    qdev_prop_set_uint32(&dev->qdev, "iobase",  iobase);
-    qdev_prop_set_uint32(&dev->qdev, "iobase2", iobase2);
-    qdev_prop_set_uint32(&dev->qdev, "irq",     isairq);
-    if (qdev_init(&dev->qdev) < 0)
+    isadev = isa_create(bus, TYPE_ISA_IDE);
+    dev = DEVICE(isadev);
+    qdev_prop_set_uint32(dev, "iobase",  iobase);
+    qdev_prop_set_uint32(dev, "iobase2", iobase2);
+    qdev_prop_set_uint32(dev, "irq",     isairq);
+    if (qdev_init(dev) < 0) {
         return NULL;
+    }
 
-    s = DO_UPCAST(ISAIDEState, dev, dev);
-    if (hd0)
+    s = ISA_IDE(dev);
+    if (hd0) {
         ide_create_drive(&s->bus, 0, hd0);
-    if (hd1)
+    }
+    if (hd1) {
         ide_create_drive(&s->bus, 1, hd1);
-    return dev;
+    }
+    return isadev;
 }
 
 static Property isa_ide_properties[] = {
@@ -112,7 +121,7 @@ static void isa_ide_class_initfn(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo isa_ide_info = {
-    .name          = "isa-ide",
+    .name          = TYPE_ISA_IDE,
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(ISAIDEState),
     .class_init    = isa_ide_class_initfn,
commit 29bb5317cb7b23422b2612025d56055bbf0bbd02
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Apr 27 22:18:40 2013 +0200

    i8259: QOM cleanups
    
    Eliminate DO_UPCAST() for PICCommonState. Prepares for ISA realizefn.
    
    Also give the i8259_common type registration functions unique names
    while at it.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Message-id: 1367093935-29091-6-git-send-email-afaerber at suse.de
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/i386/kvm/i8259.c b/hw/i386/kvm/i8259.c
index ea77be8..d961eca 100644
--- a/hw/i386/kvm/i8259.c
+++ b/hw/i386/kvm/i8259.c
@@ -82,7 +82,7 @@ static void kvm_pic_put(PICCommonState *s)
 
 static void kvm_pic_reset(DeviceState *dev)
 {
-    PICCommonState *s = DO_UPCAST(PICCommonState, dev.qdev, dev);
+    PICCommonState *s = PIC_COMMON(dev);
 
     s->elcr = 0;
     pic_reset_common(s);
diff --git a/hw/intc/i8259.c b/hw/intc/i8259.c
index ce14bd0..fef00fc 100644
--- a/hw/intc/i8259.c
+++ b/hw/intc/i8259.c
@@ -182,7 +182,7 @@ static void pic_intack(PICCommonState *s, int irq)
 
 int pic_read_irq(DeviceState *d)
 {
-    PICCommonState *s = DO_UPCAST(PICCommonState, dev.qdev, d);
+    PICCommonState *s = PIC_COMMON(d);
     int irq, irq2, intno;
 
     irq = pic_get_irq(s);
@@ -229,7 +229,7 @@ static void pic_init_reset(PICCommonState *s)
 
 static void pic_reset(DeviceState *dev)
 {
-    PICCommonState *s = DO_UPCAST(PICCommonState, dev.qdev, dev);
+    PICCommonState *s = PIC_COMMON(dev);
 
     s->elcr = 0;
     pic_init_reset(s);
@@ -361,7 +361,7 @@ static uint64_t pic_ioport_read(void *opaque, hwaddr addr,
 
 int pic_get_output(DeviceState *d)
 {
-    PICCommonState *s = DO_UPCAST(PICCommonState, dev.qdev, d);
+    PICCommonState *s = PIC_COMMON(d);
 
     return (pic_get_irq(s) >= 0);
 }
@@ -400,11 +400,13 @@ static const MemoryRegionOps pic_elcr_ioport_ops = {
 
 static void pic_init(PICCommonState *s)
 {
+    DeviceState *dev = DEVICE(s);
+
     memory_region_init_io(&s->base_io, &pic_base_ioport_ops, s, "pic", 2);
     memory_region_init_io(&s->elcr_io, &pic_elcr_ioport_ops, s, "elcr", 1);
 
-    qdev_init_gpio_out(&s->dev.qdev, s->int_out, ARRAY_SIZE(s->int_out));
-    qdev_init_gpio_in(&s->dev.qdev, pic_set_irq, 8);
+    qdev_init_gpio_out(dev, s->int_out, ARRAY_SIZE(s->int_out));
+    qdev_init_gpio_in(dev, pic_set_irq, 8);
 }
 
 void pic_info(Monitor *mon, const QDict *qdict)
@@ -416,7 +418,7 @@ void pic_info(Monitor *mon, const QDict *qdict)
         return;
     }
     for (i = 0; i < 2; i++) {
-        s = i == 0 ? DO_UPCAST(PICCommonState, dev.qdev, isa_pic) : slave_pic;
+        s = i == 0 ? PIC_COMMON(isa_pic) : slave_pic;
         monitor_printf(mon, "pic%d: irr=%02x imr=%02x isr=%02x hprio=%d "
                        "irq_base=%02x rr_sel=%d elcr=%02x fnm=%d\n",
                        i, s->irr, s->imr, s->isr, s->priority_add,
@@ -467,7 +469,7 @@ qemu_irq *i8259_init(ISABus *bus, qemu_irq parent_irq)
         irq_set[i + 8] = qdev_get_gpio_in(&dev->qdev, i);
     }
 
-    slave_pic = DO_UPCAST(PICCommonState, dev, dev);
+    slave_pic = PIC_COMMON(dev);
 
     return irq_set;
 }
diff --git a/hw/intc/i8259_common.c b/hw/intc/i8259_common.c
index 996ba9d..c2ba6a5 100644
--- a/hw/intc/i8259_common.c
+++ b/hw/intc/i8259_common.c
@@ -68,7 +68,7 @@ static int pic_dispatch_post_load(void *opaque, int version_id)
 
 static int pic_init_common(ISADevice *dev)
 {
-    PICCommonState *s = DO_UPCAST(PICCommonState, dev, dev);
+    PICCommonState *s = PIC_COMMON(dev);
     PICCommonClass *info = PIC_COMMON_GET_CLASS(s);
 
     info->init(s);
@@ -78,7 +78,7 @@ static int pic_init_common(ISADevice *dev)
         isa_register_ioport(NULL, &s->elcr_io, s->elcr_addr);
     }
 
-    qdev_set_legacy_instance_id(&s->dev.qdev, s->iobase, 1);
+    qdev_set_legacy_instance_id(DEVICE(dev), s->iobase, 1);
 
     return 0;
 }
@@ -153,9 +153,9 @@ static const TypeInfo pic_common_type = {
     .abstract = true,
 };
 
-static void register_types(void)
+static void pic_common_register_types(void)
 {
     type_register_static(&pic_common_type);
 }
 
-type_init(register_types);
+type_init(pic_common_register_types)
diff --git a/include/hw/isa/i8259_internal.h b/include/hw/isa/i8259_internal.h
index d3ddb27..b4e757a 100644
--- a/include/hw/isa/i8259_internal.h
+++ b/include/hw/isa/i8259_internal.h
@@ -48,7 +48,8 @@ typedef struct PICCommonClass
 } PICCommonClass;
 
 struct PICCommonState {
-    ISADevice dev;
+    ISADevice parent_obj;
+
     uint8_t last_irr; /* edge detection */
     uint8_t irr; /* interrupt request register */
     uint8_t imr; /* interrupt mask register */
commit eb1440e7ec522784f4351bb5e88436cc3cd9abd7
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Apr 27 22:18:39 2013 +0200

    i82374: QOM'ify
    
    Introduce type constant and cast macro to obsolete DO_UPCAST().
    
    Prepares for ISA realizefn.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Message-id: 1367093935-29091-5-git-send-email-afaerber at suse.de
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/dma/i82374.c b/hw/dma/i82374.c
index 835639d..f3d1924 100644
--- a/hw/dma/i82374.c
+++ b/hw/dma/i82374.c
@@ -104,8 +104,12 @@ static void i82374_init(I82374State *s)
     memset(s->commands, 0, sizeof(s->commands));
 }
 
+#define TYPE_I82374 "i82374"
+#define I82374(obj) OBJECT_CHECK(ISAi82374State, (obj), TYPE_I82374)
+
 typedef struct ISAi82374State {
-    ISADevice dev;
+    ISADevice parent_obj;
+
     uint32_t iobase;
     I82374State state;
 } ISAi82374State;
@@ -122,7 +126,7 @@ static const VMStateDescription vmstate_isa_i82374 = {
 
 static int i82374_isa_init(ISADevice *dev)
 {
-    ISAi82374State *isa = DO_UPCAST(ISAi82374State, dev, dev);
+    ISAi82374State *isa = I82374(dev);
     I82374State *s = &isa->state;
 
     register_ioport_read(isa->iobase + 0x0A, 1, 1, i82374_read_isr, s);
@@ -154,7 +158,7 @@ static void i82374_class_init(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo i82374_isa_info = {
-    .name  = "i82374",
+    .name  = TYPE_I82374,
     .parent = TYPE_ISA_DEVICE,
     .instance_size  = sizeof(ISAi82374State),
     .class_init = i82374_class_init,
commit 020c8e7602fc6bf6a6ce62d99fb0a0882877ccd1
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Apr 27 22:18:38 2013 +0200

    fdc: QOM'ify ISA floppy controller
    
    Introduce type constant and cast macro to obsolete DO_UPCAST().
    Reuse type constant for PC machine compatibility settings.
    
    Prepares for ISA realizefn.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Message-id: 1367093935-29091-4-git-send-email-afaerber at suse.de
    Cc: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/block/fdc.c b/hw/block/fdc.c
index f1f1fd7..0888652 100644
--- a/hw/block/fdc.c
+++ b/hw/block/fdc.c
@@ -549,8 +549,11 @@ typedef struct FDCtrlSysBus {
     struct FDCtrl state;
 } FDCtrlSysBus;
 
+#define ISA_FDC(obj) OBJECT_CHECK(FDCtrlISABus, (obj), TYPE_ISA_FDC)
+
 typedef struct FDCtrlISABus {
-    ISADevice busdev;
+    ISADevice parent_obj;
+
     uint32_t iobase;
     uint32_t irq;
     uint32_t dma;
@@ -778,7 +781,7 @@ static void fdctrl_external_reset_sysbus(DeviceState *d)
 
 static void fdctrl_external_reset_isa(DeviceState *d)
 {
-    FDCtrlISABus *isa = container_of(d, FDCtrlISABus, busdev.qdev);
+    FDCtrlISABus *isa = ISA_FDC(d);
     FDCtrl *s = &isa->state;
 
     fdctrl_reset(s, 0);
@@ -2021,7 +2024,7 @@ ISADevice *fdctrl_init_isa(ISABus *bus, DriveInfo **fds)
 {
     ISADevice *dev;
 
-    dev = isa_try_create(bus, "isa-fdc");
+    dev = isa_try_create(bus, TYPE_ISA_FDC);
     if (!dev) {
         return NULL;
     }
@@ -2116,13 +2119,13 @@ static const MemoryRegionPortio fdc_portio_list[] = {
 
 static int isabus_fdc_init1(ISADevice *dev)
 {
-    FDCtrlISABus *isa = DO_UPCAST(FDCtrlISABus, busdev, dev);
+    FDCtrlISABus *isa = ISA_FDC(dev);
     FDCtrl *fdctrl = &isa->state;
     int ret;
 
     isa_register_portio_list(dev, isa->iobase, fdc_portio_list, fdctrl, "fdc");
 
-    isa_init_irq(&isa->busdev, &fdctrl->irq, isa->irq);
+    isa_init_irq(dev, &fdctrl->irq, isa->irq);
     fdctrl->dma_chann = isa->dma;
 
     qdev_set_legacy_instance_id(&dev->qdev, isa->iobase, 2);
@@ -2169,7 +2172,7 @@ static int sun4m_fdc_init1(SysBusDevice *dev)
 
 FDriveType isa_fdc_get_drive_type(ISADevice *fdc, int i)
 {
-    FDCtrlISABus *isa = DO_UPCAST(FDCtrlISABus, busdev, fdc);
+    FDCtrlISABus *isa = ISA_FDC(fdc);
 
     return isa->state.drives[i].drive;
 }
@@ -2197,7 +2200,7 @@ static Property isa_fdc_properties[] = {
     DEFINE_PROP_END_OF_LIST(),
 };
 
-static void isabus_fdc_class_init1(ObjectClass *klass, void *data)
+static void isabus_fdc_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
@@ -2210,10 +2213,10 @@ static void isabus_fdc_class_init1(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo isa_fdc_info = {
-    .name          = "isa-fdc",
+    .name          = TYPE_ISA_FDC,
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(FDCtrlISABus),
-    .class_init    = isabus_fdc_class_init1,
+    .class_init    = isabus_fdc_class_init,
 };
 
 static const VMStateDescription vmstate_sysbus_fdc ={
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 89b4cb4..08dd61d 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -458,7 +458,7 @@ static QEMUMachine pc_machine_v1_1 = {
             .property = "rom_only",\
             .value    = stringify(1),\
         }, {\
-            .driver   = "isa-fdc",\
+            .driver   = TYPE_ISA_FDC,\
             .property = "check_media_rate",\
             .value    = "off",\
         }, {\
diff --git a/include/hw/block/fdc.h b/include/hw/block/fdc.h
index a8f6f7c..d48b2f8 100644
--- a/include/hw/block/fdc.h
+++ b/include/hw/block/fdc.h
@@ -13,6 +13,8 @@ typedef enum FDriveType {
     FDRIVE_DRV_NONE = 0x03,   /* No drive connected     */
 } FDriveType;
 
+#define TYPE_ISA_FDC "isa-fdc"
+
 ISADevice *fdctrl_init_isa(ISABus *bus, DriveInfo **fds);
 void fdctrl_init_sysbus(qemu_irq irq, int dma_chann,
                         hwaddr mmio_base, DriveInfo **fds);
commit 6d4c2f175510a447f1aa6641e1a2337958a7c6af
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Apr 27 22:18:37 2013 +0200

    cirrus_vga: QOM'ify ISA Cirrus VGA
    
    Introduce type constant and cast macro to obsolete DO_UPCAST().
    
    Prepares for ISA realizefn.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Message-id: 1367093935-29091-3-git-send-email-afaerber at suse.de
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
index 6e47956..64bfe2b 100644
--- a/hw/display/cirrus_vga.c
+++ b/hw/display/cirrus_vga.c
@@ -250,8 +250,13 @@ typedef struct PCICirrusVGAState {
     CirrusVGAState cirrus_vga;
 } PCICirrusVGAState;
 
+#define TYPE_ISA_CIRRUS_VGA "isa-cirrus-vga"
+#define ISA_CIRRUS_VGA(obj) \
+    OBJECT_CHECK(ISACirrusVGAState, (obj), TYPE_ISA_CIRRUS_VGA)
+
 typedef struct ISACirrusVGAState {
-    ISADevice dev;
+    ISADevice parent_obj;
+
     CirrusVGAState cirrus_vga;
 } ISACirrusVGAState;
 
@@ -2904,7 +2909,7 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci,
 
 static int vga_initfn(ISADevice *dev)
 {
-    ISACirrusVGAState *d = DO_UPCAST(ISACirrusVGAState, dev, dev);
+    ISACirrusVGAState *d = ISA_CIRRUS_VGA(dev);
     VGACommonState *s = &d->cirrus_vga.vga;
 
     vga_common_init(s);
@@ -2917,7 +2922,7 @@ static int vga_initfn(ISADevice *dev)
     return 0;
 }
 
-static Property isa_vga_cirrus_properties[] = {
+static Property isa_cirrus_vga_properties[] = {
     DEFINE_PROP_UINT32("vgamem_mb", struct ISACirrusVGAState,
                        cirrus_vga.vga.vram_size_mb, 8),
     DEFINE_PROP_END_OF_LIST(),
@@ -2930,11 +2935,11 @@ static void isa_cirrus_vga_class_init(ObjectClass *klass, void *data)
 
     dc->vmsd  = &vmstate_cirrus_vga;
     k->init   = vga_initfn;
-    dc->props = isa_vga_cirrus_properties;
+    dc->props = isa_cirrus_vga_properties;
 }
 
 static const TypeInfo isa_cirrus_vga_info = {
-    .name          = "isa-cirrus-vga",
+    .name          = TYPE_ISA_CIRRUS_VGA,
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(ISACirrusVGAState),
     .class_init = isa_cirrus_vga_class_init,
commit 82407b6c347db5298e18a716e386d12569479e3d
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Apr 27 22:18:36 2013 +0200

    applesmc: QOM'ify
    
    Add a typedef for the state struct and rename from Status to State.
    Add type constant and cast macro to obsolete DO_UPCAST().
    
    Prepares for ISA realizefn.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Message-id: 1367093935-29091-2-git-send-email-afaerber at suse.de
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/misc/applesmc.c b/hw/misc/applesmc.c
index c29558b..78904a8 100644
--- a/hw/misc/applesmc.c
+++ b/hw/misc/applesmc.c
@@ -66,8 +66,13 @@ struct AppleSMCData {
     QLIST_ENTRY(AppleSMCData) node;
 };
 
-struct AppleSMCStatus {
-    ISADevice dev;
+#define TYPE_APPLE_SMC "isa-applesmc"
+#define APPLE_SMC(obj) OBJECT_CHECK(AppleSMCState, (obj), TYPE_APPLE_SMC)
+
+typedef struct AppleSMCState AppleSMCState;
+struct AppleSMCState {
+    ISADevice parent_obj;
+
     uint32_t iobase;
     uint8_t cmd;
     uint8_t status;
@@ -83,7 +88,7 @@ struct AppleSMCStatus {
 
 static void applesmc_io_cmd_writeb(void *opaque, uint32_t addr, uint32_t val)
 {
-    struct AppleSMCStatus *s = opaque;
+    AppleSMCState *s = opaque;
 
     smc_debug("CMD Write B: %#x = %#x\n", addr, val);
     switch(val) {
@@ -96,7 +101,7 @@ static void applesmc_io_cmd_writeb(void *opaque, uint32_t addr, uint32_t val)
     s->data_pos = 0;
 }
 
-static void applesmc_fill_data(struct AppleSMCStatus *s)
+static void applesmc_fill_data(AppleSMCState *s)
 {
     struct AppleSMCData *d;
 
@@ -112,7 +117,7 @@ static void applesmc_fill_data(struct AppleSMCStatus *s)
 
 static void applesmc_io_data_writeb(void *opaque, uint32_t addr, uint32_t val)
 {
-    struct AppleSMCStatus *s = opaque;
+    AppleSMCState *s = opaque;
 
     smc_debug("DATA Write B: %#x = %#x\n", addr, val);
     switch(s->cmd) {
@@ -135,7 +140,7 @@ static void applesmc_io_data_writeb(void *opaque, uint32_t addr, uint32_t val)
 
 static uint32_t applesmc_io_data_readb(void *opaque, uint32_t addr1)
 {
-    struct AppleSMCStatus *s = opaque;
+    AppleSMCState *s = opaque;
     uint8_t retval = 0;
 
     switch(s->cmd) {
@@ -159,13 +164,13 @@ static uint32_t applesmc_io_data_readb(void *opaque, uint32_t addr1)
 
 static uint32_t applesmc_io_cmd_readb(void *opaque, uint32_t addr1)
 {
-    struct AppleSMCStatus *s = opaque;
+    AppleSMCState *s = opaque;
 
     smc_debug("CMD Read B: %#x\n", addr1);
     return s->status;
 }
 
-static void applesmc_add_key(struct AppleSMCStatus *s, const char *key,
+static void applesmc_add_key(AppleSMCState *s, const char *key,
                              int len, const char *data)
 {
     struct AppleSMCData *def;
@@ -180,7 +185,7 @@ static void applesmc_add_key(struct AppleSMCStatus *s, const char *key,
 
 static void qdev_applesmc_isa_reset(DeviceState *dev)
 {
-    struct AppleSMCStatus *s = DO_UPCAST(struct AppleSMCStatus, dev.qdev, dev);
+    AppleSMCState *s = APPLE_SMC(dev);
     struct AppleSMCData *d, *next;
 
     /* Remove existing entries */
@@ -198,7 +203,7 @@ static void qdev_applesmc_isa_reset(DeviceState *dev)
 
 static int applesmc_isa_init(ISADevice *dev)
 {
-    struct AppleSMCStatus *s = DO_UPCAST(struct AppleSMCStatus, dev, dev);
+    AppleSMCState *s = APPLE_SMC(dev);
 
     register_ioport_read(s->iobase + APPLESMC_DATA_PORT, 4, 1,
                          applesmc_io_data_readb, s);
@@ -221,9 +226,9 @@ static int applesmc_isa_init(ISADevice *dev)
 }
 
 static Property applesmc_isa_properties[] = {
-    DEFINE_PROP_HEX32("iobase", struct AppleSMCStatus, iobase,
+    DEFINE_PROP_HEX32("iobase", AppleSMCState, iobase,
                       APPLESMC_DEFAULT_IOBASE),
-    DEFINE_PROP_STRING("osk", struct AppleSMCStatus, osk),
+    DEFINE_PROP_STRING("osk", AppleSMCState, osk),
     DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -237,9 +242,9 @@ static void qdev_applesmc_class_init(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo applesmc_isa_info = {
-    .name          = "isa-applesmc",
+    .name          = TYPE_APPLE_SMC,
     .parent        = TYPE_ISA_DEVICE,
-    .instance_size = sizeof(struct AppleSMCStatus),
+    .instance_size = sizeof(AppleSMCState),
     .class_init    = qdev_applesmc_class_init,
 };
 
commit ec57db1630f9cdcd13c8c55acbc8daf5237aabf1
Author: Jason Wang <jasowang at redhat.com>
Date:   Thu Apr 25 15:24:23 2013 +0800

    virtio-net: unbreak the minix guest
    
    Multiqueue patchset conditionally add control vq only when guest negotiate the
    feature. Though the spec is not clear on this but it breaks the minix guest
    since it will identify the ctrl vq even if it does not support it. Though this
    behavior seems a violation on the spec "If the VIRTIO_NET_F_CTRL_VQ feature bit
    is negotiated, identify the control virtqueue.", to keep the backward
    compatibility, always add the ctrl vq at end of the queues.
    
    Reported-by: Aurelien Jarno <aurelien at aurel32.net>
    Acked-by: Michael S. Tsirkin <mst at redhat.com>
    Tested-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Jason Wang <jasowang at redhat.com>
    Message-id: 1366874663-2566-1-git-send-email-jasowang at redhat.com
    Cc: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Jason Wang <jasowang at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 2aea5a1..b2d99f9 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -309,7 +309,7 @@ static void virtio_net_set_queues(VirtIONet *n)
     }
 }
 
-static void virtio_net_set_multiqueue(VirtIONet *n, int multiqueue, int ctrl);
+static void virtio_net_set_multiqueue(VirtIONet *n, int multiqueue);
 
 static uint32_t virtio_net_get_features(VirtIODevice *vdev, uint32_t features)
 {
@@ -364,8 +364,7 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features)
     VirtIONet *n = VIRTIO_NET(vdev);
     int i;
 
-    virtio_net_set_multiqueue(n, !!(features & (1 << VIRTIO_NET_F_MQ)),
-                              !!(features & (1 << VIRTIO_NET_F_CTRL_VQ)));
+    virtio_net_set_multiqueue(n, !!(features & (1 << VIRTIO_NET_F_MQ)));
 
     virtio_net_set_mrg_rx_bufs(n, !!(features & (1 << VIRTIO_NET_F_MRG_RXBUF)));
 
@@ -1038,7 +1037,7 @@ static void virtio_net_tx_bh(void *opaque)
     }
 }
 
-static void virtio_net_set_multiqueue(VirtIONet *n, int multiqueue, int ctrl)
+static void virtio_net_set_multiqueue(VirtIONet *n, int multiqueue)
 {
     VirtIODevice *vdev = VIRTIO_DEVICE(n);
     int i, max = multiqueue ? n->max_queues : 1;
@@ -1067,9 +1066,11 @@ static void virtio_net_set_multiqueue(VirtIONet *n, int multiqueue, int ctrl)
         n->vqs[i].n = n;
     }
 
-    if (ctrl) {
-        n->ctrl_vq = virtio_add_queue(vdev, 64, virtio_net_handle_ctrl);
-    }
+    /* Note: Minux Guests (version 3.2.1) use ctrl vq but don't ack
+     * VIRTIO_NET_F_CTRL_VQ. Create ctrl vq unconditionally to avoid
+     * breaking them.
+     */
+    n->ctrl_vq = virtio_add_queue(vdev, 64, virtio_net_handle_ctrl);
 
     virtio_net_set_queues(n);
 }
commit b48df71c916478ff658d143d0742e85c78348fad
Merge: 45dddd9 9adea5f
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Apr 29 08:26:47 2013 -0500

    Merge remote-tracking branch 'bonzini/migration-writev' into staging
    
    # By Paolo Bonzini
    # Via Paolo Bonzini
    * bonzini/migration-writev:
      win32: add readv/writev emulation
      win32: generate console executable again
      win32: move Makefile dependencies on version-obj-y to rules.mak
      win32: add generic RC rules to rules.mak
    
    Message-id: 1367230284-24612-1-git-send-email-pbonzini at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

commit 45dddd90c339254d1ebc34ef719d84f3495c151b
Merge: 903ce9f ae12e3a
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Apr 29 08:26:39 2013 -0500

    Merge remote-tracking branch 'alon/libcacard_ccid.2' into staging
    
    # By Cole Robinson
    # Via Alon Levy
    * alon/libcacard_ccid.2:
      ccid: Fix crash when backend isn't specified
    
    Message-id: 20130426234357.GA12457 at garlic.tami
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

commit 9adea5f7f7a23ef4a1231289a36a94c52347b142
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sun Apr 21 12:01:06 2013 +0200

    win32: add readv/writev emulation
    
    Commit e9d8fbf (qemu-file: do not use stdio for qemu_fdopen, 2013-03-27)
    introduced a usage of writev, which mingw32 does not have.  Even though
    qemu_fdopen itself is not used on mingw32, the future-proof solution is
    to add an implementation of it.  This is simple and similar to how we
    emulate sendmsg/recvmsg in util/iov.c.
    
    Some files include osdep.h without qemu-common.h, so move the definition
    of iovec to osdep.h too, and include osdep.h from qemu-common.h
    unconditionally (protection against including files when NEED_CPU_H is
    defined is not needed since the removal of AREG0).
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/include/qemu-common.h b/include/qemu-common.h
index a39cdba..b399d85 100644
--- a/include/qemu-common.h
+++ b/include/qemu-common.h
@@ -84,20 +84,6 @@
 # error Unknown pointer size
 #endif
 
-#ifndef CONFIG_IOVEC
-#define CONFIG_IOVEC
-struct iovec {
-    void *iov_base;
-    size_t iov_len;
-};
-/*
- * Use the same value as Linux for now.
- */
-#define IOV_MAX		1024
-#else
-#include <sys/uio.h>
-#endif
-
 typedef int (*fprintf_function)(FILE *f, const char *fmt, ...)
     GCC_FMT_ATTR(2, 3);
 
@@ -122,16 +108,12 @@ static inline char *realpath(const char *path, char *resolved_path)
 void configure_icount(const char *option);
 extern int use_icount;
 
-/* FIXME: Remove NEED_CPU_H.  */
-#ifndef NEED_CPU_H
-
 #include "qemu/osdep.h"
 #include "qemu/bswap.h"
 
-#else
-
+/* FIXME: Remove NEED_CPU_H.  */
+#ifdef NEED_CPU_H
 #include "cpu.h"
-
 #endif /* !defined(NEED_CPU_H) */
 
 /* main function, renamed */
diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
index 8b465fd..42545bc 100644
--- a/include/qemu/osdep.h
+++ b/include/qemu/osdep.h
@@ -1,6 +1,7 @@
 #ifndef QEMU_OSDEP_H
 #define QEMU_OSDEP_H
 
+#include "config-host.h"
 #include <stdarg.h>
 #include <stddef.h>
 #include <stdbool.h>
@@ -161,6 +162,22 @@ int qemu_close(int fd);
 int qemu_create_pidfile(const char *filename);
 int qemu_get_thread_id(void);
 
+#ifndef CONFIG_IOVEC
+struct iovec {
+    void *iov_base;
+    size_t iov_len;
+};
+/*
+ * Use the same value as Linux for now.
+ */
+#define IOV_MAX 1024
+
+ssize_t readv(int fd, const struct iovec *iov, int iov_cnt);
+ssize_t writev(int fd, const struct iovec *iov, int iov_cnt);
+#else
+#include <sys/uio.h>
+#endif
+
 #ifdef _WIN32
 static inline void qemu_timersub(const struct timeval *val1,
                                  const struct timeval *val2,
diff --git a/util/iov.c b/util/iov.c
index d32226d..78bbbe1 100644
--- a/util/iov.c
+++ b/util/iov.c
@@ -99,7 +99,7 @@ size_t iov_size(const struct iovec *iov, const unsigned int iov_cnt)
 static ssize_t
 do_send_recv(int sockfd, struct iovec *iov, unsigned iov_cnt, bool do_send)
 {
-#if defined CONFIG_IOVEC && defined CONFIG_POSIX
+#ifdef CONFIG_POSIX
     ssize_t ret;
     struct msghdr msg;
     memset(&msg, 0, sizeof(msg));
diff --git a/util/osdep.c b/util/osdep.c
index 6ae5aaf..685c8ae 100644
--- a/util/osdep.c
+++ b/util/osdep.c
@@ -429,3 +429,46 @@ int socket_init(void)
 #endif
     return 0;
 }
+
+#ifndef CONFIG_IOVEC
+/* helper function for iov_send_recv() */
+static ssize_t
+readv_writev(int fd, const struct iovec *iov, int iov_cnt, bool do_write)
+{
+    unsigned i = 0;
+    ssize_t ret = 0;
+    while (i < iov_cnt) {
+        ssize_t r = do_write
+            ? write(fd, iov[i].iov_base, iov[i].iov_len)
+            : read(fd, iov[i].iov_base, iov[i].iov_len);
+        if (r > 0) {
+            ret += r;
+        } else if (!r) {
+            break;
+        } else if (errno == EINTR) {
+            continue;
+        } else {
+            /* else it is some "other" error,
+             * only return if there was no data processed. */
+            if (ret == 0) {
+                ret = -1;
+            }
+            break;
+        }
+        i++;
+    }
+    return ret;
+}
+
+ssize_t
+readv(int fd, const struct iovec *iov, int iov_cnt)
+{
+    return readv_writev(fd, iov, iov_cnt, false);
+}
+
+ssize_t
+writev(int fd, const struct iovec *iov, int iov_cnt)
+{
+    return readv_writev(fd, iov, iov_cnt, true);
+}
+#endif
commit 903ce9fefacd828bbcadd656ddaed8984139be29
Author: Artyom Tarasenko <atar4qemu at gmail.com>
Date:   Sat Apr 27 07:55:13 2013 +0200

    sparc64: use direct interrupt mapping for PCI devices
    
    Every PCI Slot in PBM has 4 directly mapped IRQ lines.
    Use the IRQ routing schema 0bssnn (Bus, Slot, interrupt Number)
    described in Section 19.3.3 of UltraSPARCâ„¢-IIi User's Manual.
    
    Please note that this patch requires the OpenBIOS counterpart patch.
    
    Signed-off-by: Artyom Tarasenko <atar4qemu at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
index ccd38d0..e099655 100644
--- a/hw/pci-host/apb.c
+++ b/hw/pci-host/apb.c
@@ -365,7 +365,7 @@ static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num)
         bus_offset = 16;
     else
         bus_offset = 0;
-    return bus_offset + irq_num;
+    return (bus_offset + (PCI_SLOT(pci_dev->devfn) << 2) + irq_num) & 0x1f;
 }
 
 static void pci_apb_set_irq(void *opaque, int irq_num, int level)
commit 9625036d14bdcc908fa06cd45599115258452c46
Author: Artyom Tarasenko <atar4qemu at gmail.com>
Date:   Sat Apr 27 07:55:12 2013 +0200

    sparc64: fix loosing interrupts
    
    - clear interrupts only on writing to the interrupt clear registers
    - don't overwrite a currently active interrupt request
    - use the correct addresses for the interrupt clear registers
      (section 19.3.3.3 of the UltraSPARC™-IIi User’s Manual)
    
    Signed-off-by: Artyom Tarasenko <atar4qemu at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
index 3bc0d10..ccd38d0 100644
--- a/hw/pci-host/apb.c
+++ b/hw/pci-host/apb.c
@@ -2,6 +2,7 @@
  * QEMU Ultrasparc APB PCI host
  *
  * Copyright (c) 2006 Fabrice Bellard
+ * Copyright (c) 2012,2013 Artyom Tarasenko
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -67,6 +68,7 @@ do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
 #define RESET_WMASK  0x60000000
 
 #define MAX_IVEC 0x40
+#define NO_IRQ_REQUEST (MAX_IVEC + 1)
 
 typedef struct APBState {
     SysBusDevice busdev;
@@ -75,17 +77,64 @@ typedef struct APBState {
     MemoryRegion pci_config;
     MemoryRegion pci_mmio;
     MemoryRegion pci_ioport;
+    uint64_t pci_irq_in;
     uint32_t iommu[4];
     uint32_t pci_control[16];
     uint32_t pci_irq_map[8];
     uint32_t obio_irq_map[32];
     qemu_irq *pbm_irqs;
     qemu_irq *ivec_irqs;
+    unsigned int irq_request;
     uint32_t reset_control;
     unsigned int nr_resets;
 } APBState;
 
-static void pci_apb_set_irq(void *opaque, int irq_num, int level);
+static inline void pbm_set_request(APBState *s, unsigned int irq_num)
+{
+    APB_DPRINTF("%s: request irq %d\n", __func__, irq_num);
+
+    s->irq_request = irq_num;
+    qemu_set_irq(s->ivec_irqs[irq_num], 1);
+}
+
+static inline void pbm_check_irqs(APBState *s)
+{
+
+    unsigned int i;
+
+    /* Previous request is not acknowledged, resubmit */
+    if (s->irq_request != NO_IRQ_REQUEST) {
+        pbm_set_request(s, s->irq_request);
+        return;
+    }
+    /* no request pending */
+    if (s->pci_irq_in == 0ULL) {
+        return;
+    }
+    for (i = 0; i < 32; i++) {
+        if (s->pci_irq_in & (1ULL << i)) {
+            if (s->pci_irq_map[i >> 2] & PBM_PCI_IMR_ENABLED) {
+                pbm_set_request(s, i);
+                return;
+            }
+        }
+    }
+    for (i = 32; i < 64; i++) {
+        if (s->pci_irq_in & (1ULL << i)) {
+            if (s->obio_irq_map[i - 32] & PBM_PCI_IMR_ENABLED) {
+                pbm_set_request(s, i);
+                break;
+            }
+        }
+    }
+}
+
+static inline void pbm_clear_request(APBState *s, unsigned int irq_num)
+{
+    APB_DPRINTF("%s: clear request irq %d\n", __func__, irq_num);
+    qemu_set_irq(s->ivec_irqs[irq_num], 0);
+    s->irq_request = NO_IRQ_REQUEST;
+}
 
 static void apb_config_writel (void *opaque, hwaddr addr,
                                uint64_t val, unsigned size)
@@ -105,24 +154,43 @@ static void apb_config_writel (void *opaque, hwaddr addr,
         break;
     case 0xc00 ... 0xc3f: /* PCI interrupt control */
         if (addr & 4) {
-            s->pci_irq_map[(addr & 0x3f) >> 3] &= PBM_PCI_IMR_MASK;
-            s->pci_irq_map[(addr & 0x3f) >> 3] |= val & ~PBM_PCI_IMR_MASK;
+            unsigned int ino = (addr & 0x3f) >> 3;
+            s->pci_irq_map[ino] &= PBM_PCI_IMR_MASK;
+            s->pci_irq_map[ino] |= val & ~PBM_PCI_IMR_MASK;
+            if ((s->irq_request == ino) && !(val & ~PBM_PCI_IMR_MASK)) {
+                pbm_clear_request(s, ino);
+            }
+            pbm_check_irqs(s);
         }
         break;
     case 0x1000 ... 0x1080: /* OBIO interrupt control */
         if (addr & 4) {
-            s->obio_irq_map[(addr & 0xff) >> 3] &= PBM_PCI_IMR_MASK;
-            s->obio_irq_map[(addr & 0xff) >> 3] |= val & ~PBM_PCI_IMR_MASK;
+            unsigned int ino = ((addr & 0xff) >> 3);
+            s->obio_irq_map[ino] &= PBM_PCI_IMR_MASK;
+            s->obio_irq_map[ino] |= val & ~PBM_PCI_IMR_MASK;
+            if ((s->irq_request == (ino | 0x20))
+                 && !(val & ~PBM_PCI_IMR_MASK)) {
+                pbm_clear_request(s, ino | 0x20);
+            }
+            pbm_check_irqs(s);
         }
         break;
-    case 0x1400 ... 0x143f: /* PCI interrupt clear */
+    case 0x1400 ... 0x14ff: /* PCI interrupt clear */
         if (addr & 4) {
-            pci_apb_set_irq(s, (addr & 0x3f) >> 3, 0);
+            unsigned int ino = (addr & 0xff) >> 5;
+            if ((s->irq_request / 4)  == ino) {
+                pbm_clear_request(s, s->irq_request);
+                pbm_check_irqs(s);
+            }
         }
         break;
     case 0x1800 ... 0x1860: /* OBIO interrupt clear */
         if (addr & 4) {
-            pci_apb_set_irq(s, 0x20 | ((addr & 0xff) >> 3), 0);
+            unsigned int ino = ((addr & 0xff) >> 3) | 0x20;
+            if (s->irq_request == ino) {
+                pbm_clear_request(s, ino);
+                pbm_check_irqs(s);
+            }
         }
         break;
     case 0x2000 ... 0x202f: /* PCI control */
@@ -304,23 +372,28 @@ static void pci_apb_set_irq(void *opaque, int irq_num, int level)
 {
     APBState *s = opaque;
 
+    APB_DPRINTF("%s: set irq_in %d level %d\n", __func__, irq_num, level);
     /* PCI IRQ map onto the first 32 INO.  */
     if (irq_num < 32) {
-        if (s->pci_irq_map[irq_num >> 2] & PBM_PCI_IMR_ENABLED) {
-            APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level);
-            qemu_set_irq(s->ivec_irqs[irq_num], level);
+        if (level) {
+            s->pci_irq_in |= 1ULL << irq_num;
+            if (s->pci_irq_map[irq_num >> 2] & PBM_PCI_IMR_ENABLED) {
+                pbm_set_request(s, irq_num);
+            }
         } else {
-            APB_DPRINTF("%s: not enabled: lower irq %d\n", __func__, irq_num);
-            qemu_irq_lower(s->ivec_irqs[irq_num]);
+            s->pci_irq_in &= ~(1ULL << irq_num);
         }
     } else {
-        /* OBIO IRQ map onto the next 16 INO.  */
-        if (s->obio_irq_map[irq_num - 32] & PBM_PCI_IMR_ENABLED) {
+        /* OBIO IRQ map onto the next 32 INO.  */
+        if (level) {
             APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level);
-            qemu_set_irq(s->ivec_irqs[irq_num], level);
+            s->pci_irq_in |= 1ULL << irq_num;
+            if ((s->irq_request == NO_IRQ_REQUEST)
+                && (s->obio_irq_map[irq_num - 32] & PBM_PCI_IMR_ENABLED)) {
+                pbm_set_request(s, irq_num);
+            }
         } else {
-            APB_DPRINTF("%s: not enabled: lower irq %d\n", __func__, irq_num);
-            qemu_irq_lower(s->ivec_irqs[irq_num]);
+            s->pci_irq_in &= ~(1ULL << irq_num);
         }
     }
 }
@@ -420,6 +493,9 @@ static void pci_pbm_reset(DeviceState *d)
         s->obio_irq_map[i] &= PBM_PCI_IMR_MASK;
     }
 
+    s->irq_request = NO_IRQ_REQUEST;
+    s->pci_irq_in = 0ULL;
+
     if (s->nr_resets++ == 0) {
         /* Power on reset */
         s->reset_control = POR;
@@ -445,6 +521,8 @@ static int pci_pbm_init_device(SysBusDevice *dev)
         s->obio_irq_map[i] = ((0x1f << 6) | 0x20) + i;
     }
     s->pbm_irqs = qemu_allocate_irqs(pci_apb_set_irq, s, MAX_IVEC);
+    s->irq_request = NO_IRQ_REQUEST;
+    s->pci_irq_in = 0ULL;
 
     /* apb_config */
     memory_region_init_io(&s->apb_config, &apb_config_ops, s, "apb-config",
commit 852e82f303884139ba59f7f26e761d937a25fa55
Author: Artyom Tarasenko <atar4qemu at gmail.com>
Date:   Sat Apr 27 07:55:11 2013 +0200

    sparc64: allow 64 IRQ lines
    
    According to UltraSPARC™-IIi User’s Manual, PBM has 64 IRQ lines.
    
    Signed-off-by: Artyom Tarasenko <atar4qemu at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
index b4981d7..3bc0d10 100644
--- a/hw/pci-host/apb.c
+++ b/hw/pci-host/apb.c
@@ -66,7 +66,7 @@ do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
 #define RESET_WCMASK 0x98000000
 #define RESET_WMASK  0x60000000
 
-#define MAX_IVEC 0x30
+#define MAX_IVEC 0x40
 
 typedef struct APBState {
     SysBusDevice busdev;
diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
index 0d29620..5c2bbd4 100644
--- a/hw/sparc64/sun4u.c
+++ b/hw/sparc64/sun4u.c
@@ -81,7 +81,7 @@
 #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 IVEC_MAX             0x40
 
 #define TICK_MAX             0x7fffffffffffffffULL
 
commit 96fbd7de3656583d647c204c4138bbdcc3e35d2b
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Apr 23 13:07:40 2013 -0700

    tcg-arm: Remove long jump from tcg_out_goto_label
    
    Branches within a TB will always be within 16MB.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index d6afa2f..7216f7a 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -1055,14 +1055,9 @@ static inline void tcg_out_goto_label(TCGContext *s, int cond, int label_index)
 {
     TCGLabel *l = &s->labels[label_index];
 
-    if (l->has_value)
+    if (l->has_value) {
         tcg_out_goto(s, cond, l->u.value);
-    else if (cond == COND_AL) {
-        tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
-        tcg_out_reloc(s, s->code_ptr, R_ARM_ABS32, label_index, 31337);
-        s->code_ptr += 4;
     } else {
-        /* Probably this should be preferred even for COND_AL... */
         tcg_out_reloc(s, s->code_ptr, R_ARM_PC24, label_index, 31337);
         tcg_out_b_noaddr(s, cond);
     }
commit df5e0ef711cdd2ebfd4bdf420bfde17aa28df8b1
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Mar 13 15:24:33 2013 -0700

    tcg-arm: Convert to CONFIG_QEMU_LDST_OPTIMIZATION
    
    Move the slow path out of line, as the TODO's mention.
    This allows the fast path to be unconditional, which can
    speed up the fast path as well, depending on the core.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/configure b/configure
index a07abc4..21438d4 100755
--- a/configure
+++ b/configure
@@ -3609,7 +3609,7 @@ echo "libs_softmmu=$libs_softmmu" >> $config_host_mak
 echo "ARCH=$ARCH" >> $config_host_mak
 
 case "$cpu" in
-  i386|x86_64|ppc)
+  arm|i386|x86_64|ppc)
     # The TCG interpreter currently does not support ld/st optimization.
     if test "$tcg_interpreter" = "no" ; then
         echo "CONFIG_QEMU_LDST_OPTIMIZATION=y" >> $config_host_mak
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index e856191..6362074 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -338,6 +338,23 @@ extern uintptr_t tci_tb_ptr;
 # elif defined (_ARCH_PPC) && !defined (_ARCH_PPC64)
 #  define GETRA() ((uintptr_t)__builtin_return_address(0))
 #  define GETPC_LDST() ((uintptr_t) ((*(int32_t *)(GETRA() - 4)) - 1))
+# elif defined(__arm__)
+/* We define two insns between the return address and the branch back to
+   straight-line.  Find and decode that branch insn.  */
+#  define GETRA()       ((uintptr_t)__builtin_return_address(0))
+#  define GETPC_LDST()  tcg_getpc_ldst(GETRA())
+static inline uintptr_t tcg_getpc_ldst(uintptr_t ra)
+{
+    int32_t b;
+    ra += 8;                    /* skip the two insns */
+    b = *(int32_t *)ra;         /* load the branch insn */
+    b = (b << 8) >> (8 - 2);    /* extract the displacement */
+    ra += 8;                    /* branches are relative to pc+8 */
+    ra += b;                    /* apply the displacement */
+    ra -= 4;                    /* return a pointer into the current opcode,
+                                   not the start of the next opcode  */
+    return ra;
+}
 # else
 #  error "CONFIG_QEMU_LDST_OPTIMIZATION needs GETPC_LDST() implementation!"
 # endif
diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index eb697f2..d6afa2f 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -419,6 +419,20 @@ static inline void tcg_out_dat_reg(TCGContext *s,
                     (rn << 16) | (rd << 12) | shift | rm);
 }
 
+static inline void tcg_out_nop(TCGContext *s)
+{
+    if (use_armv7_instructions) {
+        /* Architected nop introduced in v6k.  */
+        /* ??? This is an MSR (imm) 0,0,0 insn.  Anyone know if this
+           also Just So Happened to do nothing on pre-v6k so that we
+           don't need to conditionalize it?  */
+        tcg_out32(s, 0xe320f000);
+    } else {
+        /* Prior to that the assembler uses mov r0, r0.  */
+        tcg_out_dat_reg(s, COND_AL, ARITH_MOV, 0, 0, 0, SHIFT_IMM_LSL(0));
+    }
+}
+
 static inline void tcg_out_mov_reg(TCGContext *s, int cond, int rd, int rm)
 {
     /* Simple reg-reg move, optimising out the 'do nothing' case */
@@ -1200,6 +1214,134 @@ static void tcg_out_tlb_read(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
                         TCG_REG_R1, addrhi, SHIFT_IMM_LSL(0));
     }
 }
+
+/* Record the context of a call to the out of line helper code for the slow
+   path for a load or store, so that we can later generate the correct
+   helper code.  */
+static void add_qemu_ldst_label(TCGContext *s, int is_ld, int opc,
+                                int data_reg, int data_reg2, int addrlo_reg,
+                                int addrhi_reg, int mem_index,
+                                uint8_t *raddr, uint8_t *label_ptr)
+{
+    int idx;
+    TCGLabelQemuLdst *label;
+
+    if (s->nb_qemu_ldst_labels >= TCG_MAX_QEMU_LDST) {
+        tcg_abort();
+    }
+
+    idx = s->nb_qemu_ldst_labels++;
+    label = (TCGLabelQemuLdst *)&s->qemu_ldst_labels[idx];
+    label->is_ld = is_ld;
+    label->opc = opc;
+    label->datalo_reg = data_reg;
+    label->datahi_reg = data_reg2;
+    label->addrlo_reg = addrlo_reg;
+    label->addrhi_reg = addrhi_reg;
+    label->mem_index = mem_index;
+    label->raddr = raddr;
+    label->label_ptr[0] = label_ptr;
+}
+
+static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
+{
+    TCGReg argreg, data_reg, data_reg2;
+    uint8_t *start;
+
+    reloc_pc24(lb->label_ptr[0], (tcg_target_long)s->code_ptr);
+
+    argreg = tcg_out_arg_reg32(s, TCG_REG_R0, TCG_AREG0);
+    if (TARGET_LONG_BITS == 64) {
+        argreg = tcg_out_arg_reg64(s, argreg, lb->addrlo_reg, lb->addrhi_reg);
+    } else {
+        argreg = tcg_out_arg_reg32(s, argreg, lb->addrlo_reg);
+    }
+    argreg = tcg_out_arg_imm32(s, argreg, lb->mem_index);
+    tcg_out_call(s, (tcg_target_long) qemu_ld_helpers[lb->opc & 3]);
+
+    data_reg = lb->datalo_reg;
+    data_reg2 = lb->datahi_reg;
+
+    start = s->code_ptr;
+    switch (lb->opc) {
+    case 0 | 4:
+        tcg_out_ext8s(s, COND_AL, data_reg, TCG_REG_R0);
+        break;
+    case 1 | 4:
+        tcg_out_ext16s(s, COND_AL, data_reg, TCG_REG_R0);
+        break;
+    case 0:
+    case 1:
+    case 2:
+    default:
+        tcg_out_mov_reg(s, COND_AL, data_reg, TCG_REG_R0);
+        break;
+    case 3:
+        tcg_out_mov_reg(s, COND_AL, data_reg, TCG_REG_R0);
+        tcg_out_mov_reg(s, COND_AL, data_reg2, TCG_REG_R1);
+        break;
+    }
+
+    /* For GETPC_LDST in exec-all.h, we architect exactly 2 insns between
+       the call and the branch back to straight-line code.  Note that the
+       moves above could be elided by register allocation, nor do we know
+       which code alternative we chose for extension.  */
+    switch (s->code_ptr - start) {
+    case 0:
+        tcg_out_nop(s);
+        /* FALLTHRU */
+    case 4:
+        tcg_out_nop(s);
+        /* FALLTHRU */
+    case 8:
+        break;
+    default:
+        abort();
+    }
+
+    tcg_out_goto(s, COND_AL, (tcg_target_long)lb->raddr);
+}
+
+static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
+{
+    TCGReg argreg, data_reg, data_reg2;
+
+    reloc_pc24(lb->label_ptr[0], (tcg_target_long)s->code_ptr);
+
+    argreg = TCG_REG_R0;
+    argreg = tcg_out_arg_reg32(s, argreg, TCG_AREG0);
+    if (TARGET_LONG_BITS == 64) {
+        argreg = tcg_out_arg_reg64(s, argreg, lb->addrlo_reg, lb->addrhi_reg);
+    } else {
+        argreg = tcg_out_arg_reg32(s, argreg, lb->addrlo_reg);
+    }
+
+    data_reg = lb->datalo_reg;
+    data_reg2 = lb->datahi_reg;
+    switch (lb->opc) {
+    case 0:
+        argreg = tcg_out_arg_reg8(s, argreg, data_reg);
+        break;
+    case 1:
+        argreg = tcg_out_arg_reg16(s, argreg, data_reg);
+        break;
+    case 2:
+        argreg = tcg_out_arg_reg32(s, argreg, data_reg);
+        break;
+    case 3:
+        argreg = tcg_out_arg_reg64(s, argreg, data_reg, data_reg2);
+        break;
+    }
+
+    argreg = tcg_out_arg_imm32(s, argreg, lb->mem_index);
+    tcg_out_call(s, (tcg_target_long) qemu_st_helpers[lb->opc & 3]);
+
+    /* For GETPC_LDST in exec-all.h, we architect exactly 2 insns between
+       the call and the branch back to straight-line code.  */
+    tcg_out_nop(s);
+    tcg_out_nop(s);
+    tcg_out_goto(s, COND_AL, (tcg_target_long)lb->raddr);
+}
 #endif /* SOFTMMU */
 
 static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
@@ -1208,8 +1350,8 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
     bool bswap;
 #ifdef CONFIG_SOFTMMU
     int mem_index, s_bits;
-    TCGReg argreg, addr_reg2;
-    uint32_t *label_ptr;
+    TCGReg addr_reg2;
+    uint8_t *label_ptr;
 #endif
 #ifdef TARGET_WORDS_BIGENDIAN
     bswap = 1;
@@ -1228,89 +1370,56 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
     tcg_out_tlb_read(s, addr_reg, addr_reg2, s_bits,
                      offsetof(CPUArchState, tlb_table[mem_index][0].addr_read));
 
-    tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R2,
+    label_ptr = s->code_ptr;
+    tcg_out_b_noaddr(s, COND_NE);
+
+    tcg_out_ld32_12(s, COND_AL, TCG_REG_R1, TCG_REG_R2,
                     offsetof(CPUTLBEntry, addend)
                     - offsetof(CPUTLBEntry, addr_read));
 
     switch (opc) {
     case 0:
-        tcg_out_ld8_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
+        tcg_out_ld8_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1);
         break;
     case 0 | 4:
-        tcg_out_ld8s_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
+        tcg_out_ld8s_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1);
         break;
     case 1:
-        tcg_out_ld16u_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
+        tcg_out_ld16u_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1);
         if (bswap) {
-            tcg_out_bswap16(s, COND_EQ, data_reg, data_reg);
+            tcg_out_bswap16(s, COND_AL, data_reg, data_reg);
         }
         break;
     case 1 | 4:
         if (bswap) {
-            tcg_out_ld16u_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
-            tcg_out_bswap16s(s, COND_EQ, data_reg, data_reg);
+            tcg_out_ld16u_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1);
+            tcg_out_bswap16s(s, COND_AL, data_reg, data_reg);
         } else {
-            tcg_out_ld16s_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
+            tcg_out_ld16s_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1);
         }
         break;
     case 2:
     default:
-        tcg_out_ld32_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
+        tcg_out_ld32_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1);
         if (bswap) {
-            tcg_out_bswap32(s, COND_EQ, data_reg, data_reg);
+            tcg_out_bswap32(s, COND_AL, data_reg, data_reg);
         }
         break;
     case 3:
         if (bswap) {
-            tcg_out_ld32_rwb(s, COND_EQ, data_reg2, TCG_REG_R1, addr_reg);
-            tcg_out_ld32_12(s, COND_EQ, data_reg, TCG_REG_R1, 4);
-            tcg_out_bswap32(s, COND_EQ, data_reg2, data_reg2);
-            tcg_out_bswap32(s, COND_EQ, data_reg, data_reg);
+            tcg_out_ld32_rwb(s, COND_AL, data_reg2, TCG_REG_R1, addr_reg);
+            tcg_out_ld32_12(s, COND_AL, data_reg, TCG_REG_R1, 4);
+            tcg_out_bswap32(s, COND_AL, data_reg2, data_reg2);
+            tcg_out_bswap32(s, COND_AL, data_reg, data_reg);
         } else {
-            tcg_out_ld32_rwb(s, COND_EQ, data_reg, TCG_REG_R1, addr_reg);
-            tcg_out_ld32_12(s, COND_EQ, data_reg2, TCG_REG_R1, 4);
+            tcg_out_ld32_rwb(s, COND_AL, data_reg, TCG_REG_R1, addr_reg);
+            tcg_out_ld32_12(s, COND_AL, data_reg2, TCG_REG_R1, 4);
         }
         break;
     }
 
-    label_ptr = (void *) s->code_ptr;
-    tcg_out_b_noaddr(s, COND_EQ);
-
-    /* TODO: move this code to where the constants pool will be */
-    /* Note that this code relies on the constraints we set in arm_op_defs[]
-     * to ensure that later arguments are not passed to us in registers we
-     * trash by moving the earlier arguments into them.
-     */
-    argreg = TCG_REG_R0;
-    argreg = tcg_out_arg_reg32(s, argreg, TCG_AREG0);
-    if (TARGET_LONG_BITS == 64) {
-        argreg = tcg_out_arg_reg64(s, argreg, addr_reg, addr_reg2);
-    } else {
-        argreg = tcg_out_arg_reg32(s, argreg, addr_reg);
-    }
-    argreg = tcg_out_arg_imm32(s, argreg, mem_index);
-    tcg_out_call(s, (tcg_target_long) qemu_ld_helpers[s_bits]);
-
-    switch (opc) {
-    case 0 | 4:
-        tcg_out_ext8s(s, COND_AL, data_reg, TCG_REG_R0);
-        break;
-    case 1 | 4:
-        tcg_out_ext16s(s, COND_AL, data_reg, TCG_REG_R0);
-        break;
-    case 0:
-    case 1:
-    case 2:
-    default:
-        tcg_out_mov_reg(s, COND_AL, data_reg, TCG_REG_R0);
-        break;
-    case 3:
-        tcg_out_mov_reg(s, COND_AL, data_reg, TCG_REG_R0);
-        tcg_out_mov_reg(s, COND_AL, data_reg2, TCG_REG_R1);
-        break;
-    }
-
-    reloc_pc24(label_ptr, (tcg_target_long)s->code_ptr);
+    add_qemu_ldst_label(s, 1, opc, data_reg, data_reg2, addr_reg, addr_reg2,
+                        mem_index, s->code_ptr, label_ptr);
 #else /* !CONFIG_SOFTMMU */
     if (GUEST_BASE) {
         uint32_t offset = GUEST_BASE;
@@ -1379,8 +1488,8 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
     bool bswap;
 #ifdef CONFIG_SOFTMMU
     int mem_index, s_bits;
-    TCGReg argreg, addr_reg2;
-    uint32_t *label_ptr;
+    TCGReg addr_reg2;
+    uint8_t *label_ptr;
 #endif
 #ifdef TARGET_WORDS_BIGENDIAN
     bswap = 1;
@@ -1400,79 +1509,49 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
                      offsetof(CPUArchState,
                               tlb_table[mem_index][0].addr_write));
 
-    tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R2,
+    label_ptr = s->code_ptr;
+    tcg_out_b_noaddr(s, COND_NE);
+
+    tcg_out_ld32_12(s, COND_AL, TCG_REG_R1, TCG_REG_R2,
                     offsetof(CPUTLBEntry, addend)
                     - offsetof(CPUTLBEntry, addr_write));
 
     switch (opc) {
     case 0:
-        tcg_out_st8_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
+        tcg_out_st8_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1);
         break;
     case 1:
         if (bswap) {
-            tcg_out_bswap16st(s, COND_EQ, TCG_REG_R0, data_reg);
-            tcg_out_st16_r(s, COND_EQ, TCG_REG_R0, addr_reg, TCG_REG_R1);
+            tcg_out_bswap16st(s, COND_AL, TCG_REG_R0, data_reg);
+            tcg_out_st16_r(s, COND_AL, TCG_REG_R0, addr_reg, TCG_REG_R1);
         } else {
-            tcg_out_st16_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
+            tcg_out_st16_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1);
         }
         break;
     case 2:
     default:
         if (bswap) {
-            tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg);
-            tcg_out_st32_r(s, COND_EQ, TCG_REG_R0, addr_reg, TCG_REG_R1);
+            tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg);
+            tcg_out_st32_r(s, COND_AL, TCG_REG_R0, addr_reg, TCG_REG_R1);
         } else {
-            tcg_out_st32_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
+            tcg_out_st32_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1);
         }
         break;
     case 3:
         if (bswap) {
-            tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg2);
-            tcg_out_st32_rwb(s, COND_EQ, TCG_REG_R0, TCG_REG_R1, addr_reg);
-            tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg);
-            tcg_out_st32_12(s, COND_EQ, TCG_REG_R0, TCG_REG_R1, 4);
+            tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg2);
+            tcg_out_st32_rwb(s, COND_AL, TCG_REG_R0, TCG_REG_R1, addr_reg);
+            tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg);
+            tcg_out_st32_12(s, COND_AL, TCG_REG_R0, TCG_REG_R1, 4);
         } else {
-            tcg_out_st32_rwb(s, COND_EQ, data_reg, TCG_REG_R1, addr_reg);
-            tcg_out_st32_12(s, COND_EQ, data_reg2, TCG_REG_R1, 4);
+            tcg_out_st32_rwb(s, COND_AL, data_reg, TCG_REG_R1, addr_reg);
+            tcg_out_st32_12(s, COND_AL, data_reg2, TCG_REG_R1, 4);
         }
         break;
     }
 
-    label_ptr = (void *) s->code_ptr;
-    tcg_out_b_noaddr(s, COND_EQ);
-
-    /* TODO: move this code to where the constants pool will be */
-    /* Note that this code relies on the constraints we set in arm_op_defs[]
-     * to ensure that later arguments are not passed to us in registers we
-     * trash by moving the earlier arguments into them.
-     */
-    argreg = TCG_REG_R0;
-    argreg = tcg_out_arg_reg32(s, argreg, TCG_AREG0);
-    if (TARGET_LONG_BITS == 64) {
-        argreg = tcg_out_arg_reg64(s, argreg, addr_reg, addr_reg2);
-    } else {
-        argreg = tcg_out_arg_reg32(s, argreg, addr_reg);
-    }
-
-    switch (opc) {
-    case 0:
-        argreg = tcg_out_arg_reg8(s, argreg, data_reg);
-        break;
-    case 1:
-        argreg = tcg_out_arg_reg16(s, argreg, data_reg);
-        break;
-    case 2:
-        argreg = tcg_out_arg_reg32(s, argreg, data_reg);
-        break;
-    case 3:
-        argreg = tcg_out_arg_reg64(s, argreg, data_reg, data_reg2);
-        break;
-    }
-
-    argreg = tcg_out_arg_imm32(s, argreg, mem_index);
-    tcg_out_call(s, (tcg_target_long) qemu_st_helpers[s_bits]);
-
-    reloc_pc24(label_ptr, (tcg_target_long)s->code_ptr);
+    add_qemu_ldst_label(s, 0, opc, data_reg, data_reg2, addr_reg, addr_reg2,
+                        mem_index, s->code_ptr, label_ptr);
 #else /* !CONFIG_SOFTMMU */
     if (GUEST_BASE) {
         uint32_t offset = GUEST_BASE;
@@ -1872,6 +1951,22 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
     }
 }
 
+#ifdef CONFIG_SOFTMMU
+/* Generate TB finalization at the end of block.  */
+void tcg_out_tb_finalize(TCGContext *s)
+{
+    int i;
+    for (i = 0; i < s->nb_qemu_ldst_labels; i++) {
+        TCGLabelQemuLdst *label = &s->qemu_ldst_labels[i];
+        if (label->is_ld) {
+            tcg_out_qemu_ld_slow_path(s, label);
+        } else {
+            tcg_out_qemu_st_slow_path(s, label);
+        }
+    }
+}
+#endif /* SOFTMMU */
+
 static const TCGTargetOpDef arm_op_defs[] = {
     { INDEX_op_exit_tb, { } },
     { INDEX_op_goto_tb, { } },
commit 302fdde73f88fd958acfa18b670eed092eab21a0
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Mar 13 13:40:43 2013 -0700

    tcg-arm: Use movi32 + blx for calls on v7
    
    Work better with branch predition when we have movw+movt,
    as the size of the code is the same.  Perhaps re-evaluate
    when we have a proper constant pool.
    
    Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 5fa3cb1..eb697f2 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -1016,6 +1016,9 @@ static inline void tcg_out_call(TCGContext *s, uint32_t addr)
         } else {
             tcg_out_bl(s, COND_AL, val);
         }
+    } else if (use_armv7_instructions) {
+        tcg_out_movi32(s, COND_AL, TCG_REG_TMP, addr);
+        tcg_out_blx(s, COND_AL, TCG_REG_TMP);
     } else {
         tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R14, TCG_REG_PC, 4);
         tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
commit 595b5397cc589d694ec3af660b21f483e8142f69
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Apr 23 08:38:50 2013 -0700

    tcg-arm: Delete the 'S' constraint
    
    After the previous patch, 's' and 'S' are the same.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 375c1e1..5fa3cb1 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -201,8 +201,6 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
 
     /* qemu_st address & data_reg */
     case 's':
-    /* qemu_st64 data_reg2 */
-    case 'S':
         ct->ct |= TCG_CT_REG;
         tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
         /* r0-r2 will be overwritten when reading the tlb entry (softmmu only)
@@ -1928,7 +1926,7 @@ static const TCGTargetOpDef arm_op_defs[] = {
     { INDEX_op_qemu_st8, { "s", "s" } },
     { INDEX_op_qemu_st16, { "s", "s" } },
     { INDEX_op_qemu_st32, { "s", "s" } },
-    { INDEX_op_qemu_st64, { "S", "S", "s" } },
+    { INDEX_op_qemu_st64, { "s", "s", "s" } },
 #else
     { INDEX_op_qemu_ld8u, { "r", "l", "l" } },
     { INDEX_op_qemu_ld8s, { "r", "l", "l" } },
@@ -1940,7 +1938,7 @@ static const TCGTargetOpDef arm_op_defs[] = {
     { INDEX_op_qemu_st8, { "s", "s", "s" } },
     { INDEX_op_qemu_st16, { "s", "s", "s" } },
     { INDEX_op_qemu_st32, { "s", "s", "s" } },
-    { INDEX_op_qemu_st64, { "S", "S", "s", "s" } },
+    { INDEX_op_qemu_st64, { "s", "s", "s", "s" } },
 #endif
 
     { INDEX_op_bswap16_i32, { "r", "r" } },
commit 702b33b1d5f8fee7e5799af450375671264a9ebd
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Mar 12 23:18:30 2013 -0700

    tcg-arm: Improve scheduling of tcg_out_tlb_read
    
    The schedule was fully serial, with no possibility for dual issue.
    The old schedule had a minimal issue of 7 cycles; the new schedule
    has a minimal issue of 5 cycles.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index a96471c..375c1e1 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -182,18 +182,12 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
         ct->ct |= TCG_CT_REG;
         tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
 #ifdef CONFIG_SOFTMMU
-        /* r0 and r1 will be overwritten when reading the tlb entry,
+        /* r0-r2 will be overwritten when reading the tlb entry,
            so don't use these. */
         tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
         tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
-#if TARGET_LONG_BITS == 64
-        /* If we're passing env to the helper as r0 and need a regpair
-         * for the address then r2 will be overwritten as we're setting
-         * up the args to the helper.
-         */
         tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2);
 #endif
-#endif
         break;
     case 'L':
         ct->ct |= TCG_CT_REG;
@@ -207,30 +201,16 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
 
     /* qemu_st address & data_reg */
     case 's':
-        ct->ct |= TCG_CT_REG;
-        tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
-        /* r0 and r1 will be overwritten when reading the tlb entry
-           (softmmu only) and doing the byte swapping, so don't
-           use these. */
-        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
-        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
-#if defined(CONFIG_SOFTMMU) && (TARGET_LONG_BITS == 64)
-        /* Avoid clashes with registers being used for helper args */
-        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2);
-        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
-#endif
-        break;
     /* qemu_st64 data_reg2 */
     case 'S':
         ct->ct |= TCG_CT_REG;
         tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
-        /* r0 and r1 will be overwritten when reading the tlb entry
-            (softmmu only) and doing the byte swapping, so don't
-            use these. */
+        /* r0-r2 will be overwritten when reading the tlb entry (softmmu only)
+           and r0-r1 doing the byte swapping, so don't use these. */
         tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
         tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
-#ifdef CONFIG_SOFTMMU
-        /* r2 is still needed to load data_reg, so don't use it. */
+#if defined(CONFIG_SOFTMMU)
+        /* Avoid clashes with registers being used for helper args */
         tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2);
 #if TARGET_LONG_BITS == 64
         /* Avoid clashes with registers being used for helper args */
@@ -347,6 +327,8 @@ typedef enum {
     INSN_LDRSB_REG = 0x001000d0,
     INSN_STRB_IMM  = 0x04400000,
     INSN_STRB_REG  = 0x06400000,
+
+    INSN_LDRD_IMM  = 0x004000d0,
 } ARMInsn;
 
 #define SHIFT_IMM_LSL(im)	(((im) << 7) | 0x00)
@@ -805,15 +787,6 @@ static inline void tcg_out_ld32_12(TCGContext *s, int cond, TCGReg rt,
     tcg_out_memop_12(s, cond, INSN_LDR_IMM, rt, rn, imm12, 1, 0);
 }
 
-/* Offset pre-increment with base writeback.  */
-static inline void tcg_out_ld32_12wb(TCGContext *s, int cond, TCGReg rt,
-                                     TCGReg rn, int imm12)
-{
-    /* ldr with writeback and both register equals is UNPREDICTABLE */
-    assert(rd != rn);
-    tcg_out_memop_12(s, cond, INSN_LDR_IMM, rt, rn, imm12, 1, 1);
-}
-
 static inline void tcg_out_st32_12(TCGContext *s, int cond, TCGReg rt,
                                    TCGReg rn, int imm12)
 {
@@ -1150,47 +1123,78 @@ static TCGReg tcg_out_arg_reg64(TCGContext *s, TCGReg argreg,
 
 #define TLB_SHIFT	(CPU_TLB_ENTRY_BITS + CPU_TLB_BITS)
 
-/* Load and compare a TLB entry, leaving the flags set.  Leaves R0 pointing
+/* Load and compare a TLB entry, leaving the flags set.  Leaves R2 pointing
    to the tlb entry.  Clobbers R1 and TMP.  */
 
 static void tcg_out_tlb_read(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
                              int s_bits, int tlb_offset)
 {
+    TCGReg base = TCG_AREG0;
+
     /* Should generate something like the following:
-     *  shr r8, addr_reg, #TARGET_PAGE_BITS
-     *  and r0, r8, #(CPU_TLB_SIZE - 1)   @ Assumption: CPU_TLB_BITS <= 8
-     *  add r0, env, r0 lsl #CPU_TLB_ENTRY_BITS
+     * pre-v7:
+     *   shr    tmp, addr_reg, #TARGET_PAGE_BITS                  (1)
+     *   add    r2, env, #off & 0xff00
+     *   and    r0, tmp, #(CPU_TLB_SIZE - 1)                      (2)
+     *   add    r2, r2, r0, lsl #CPU_TLB_ENTRY_BITS               (3)
+     *   ldr    r0, [r2, #off & 0xff]!                            (4)
+     *   tst    addr_reg, #s_mask
+     *   cmpeq  r0, tmp, lsl #TARGET_PAGE_BITS                    (5)
+     *
+     * v7 (not implemented yet):
+     *   ubfx   r2, addr_reg, #TARGET_PAGE_BITS, #CPU_TLB_BITS    (1)
+     *   movw   tmp, #~TARGET_PAGE_MASK & ~s_mask
+     *   movw   r0, #off
+     *   add    r2, env, r2, lsl #CPU_TLB_ENTRY_BITS              (2)
+     *   bic    tmp, addr_reg, tmp
+     *   ldr    r0, [r2, r0]!                                     (3)
+     *   cmp    r0, tmp                                           (4)
      */
 #  if CPU_TLB_BITS > 8
 #   error
 #  endif
     tcg_out_dat_reg(s, COND_AL, ARITH_MOV, TCG_REG_TMP,
                     0, addrlo, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
+
+    /* We assume that the offset is contained within 16 bits.  */
+    assert((tlb_offset & ~0xffff) == 0);
+    if (tlb_offset > 0xff) {
+        tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R2, base,
+                        (24 << 7) | (tlb_offset >> 8));
+        tlb_offset &= 0xff;
+        base = TCG_REG_R2;
+    }
+
     tcg_out_dat_imm(s, COND_AL, ARITH_AND,
                     TCG_REG_R0, TCG_REG_TMP, CPU_TLB_SIZE - 1);
-    tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_R0, TCG_AREG0,
+    tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_R2, base,
                     TCG_REG_R0, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS));
 
-    /* We assume that the offset is contained within 20 bits.  */
-    assert((tlb_offset & ~0xfffff) == 0);
-    if (tlb_offset > 0xfff) {
-        tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R0, TCG_REG_R0,
-                        0xa00 | (tlb_offset >> 12));
-        tlb_offset &= 0xfff;
+    /* Load the tlb comparator.  Use ldrd if needed and available,
+       but due to how the pointer needs setting up, ldm isn't useful.
+       Base arm5 doesn't have ldrd, but armv5te does.  */
+    if (use_armv6_instructions && TARGET_LONG_BITS == 64) {
+        tcg_out_memop_8(s, COND_AL, INSN_LDRD_IMM, TCG_REG_R0,
+                        TCG_REG_R2, tlb_offset, 1, 1);
+    } else {
+        tcg_out_memop_12(s, COND_AL, INSN_LDR_IMM, TCG_REG_R0,
+                         TCG_REG_R2, tlb_offset, 1, 1);
+        if (TARGET_LONG_BITS == 64) {
+            tcg_out_memop_12(s, COND_AL, INSN_LDR_IMM, TCG_REG_R0,
+                             TCG_REG_R2, 4, 1, 0);
+        }
     }
-    tcg_out_ld32_12wb(s, COND_AL, TCG_REG_R1, TCG_REG_R0, tlb_offset);
-    tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0, TCG_REG_R1,
-                    TCG_REG_TMP, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
 
     /* Check alignment.  */
     if (s_bits) {
-        tcg_out_dat_imm(s, COND_EQ, ARITH_TST,
+        tcg_out_dat_imm(s, COND_AL, ARITH_TST,
                         0, addrlo, (1 << s_bits) - 1);
     }
 
+    tcg_out_dat_reg(s, (s_bits ? COND_EQ : COND_AL), ARITH_CMP, 0,
+                    TCG_REG_R0, TCG_REG_TMP, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
+
     if (TARGET_LONG_BITS == 64) {
-        /* XXX: possibly we could use a block data load in the first access. */
-        tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0, 4);
         tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
                         TCG_REG_R1, addrhi, SHIFT_IMM_LSL(0));
     }
@@ -1223,7 +1227,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
     tcg_out_tlb_read(s, addr_reg, addr_reg2, s_bits,
                      offsetof(CPUArchState, tlb_table[mem_index][0].addr_read));
 
-    tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0,
+    tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R2,
                     offsetof(CPUTLBEntry, addend)
                     - offsetof(CPUTLBEntry, addr_read));
 
@@ -1395,7 +1399,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
                      offsetof(CPUArchState,
                               tlb_table[mem_index][0].addr_write));
 
-    tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0,
+    tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R2,
                     offsetof(CPUTLBEntry, addend)
                     - offsetof(CPUTLBEntry, addr_write));
 
commit cee87be80a6e9cc853e07a4d3afc694604c9ac8d
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Mar 12 18:18:07 2013 -0700

    tcg-arm: Split out tcg_out_tlb_read
    
    Share code between qemu_ld and qemu_st to process the tlb.
    
    Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 92d7cee..a96471c 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -1147,40 +1147,15 @@ static TCGReg tcg_out_arg_reg64(TCGContext *s, TCGReg argreg,
     argreg = tcg_out_arg_reg32(s, argreg, arghi);
     return argreg;
 }
-#endif /* SOFTMMU */
 
 #define TLB_SHIFT	(CPU_TLB_ENTRY_BITS + CPU_TLB_BITS)
 
-static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
-{
-    int addr_reg, data_reg, data_reg2, bswap;
-#ifdef CONFIG_SOFTMMU
-    int mem_index, s_bits, tlb_offset;
-    TCGReg argreg;
-# if TARGET_LONG_BITS == 64
-    int addr_reg2;
-# endif
-    uint32_t *label_ptr;
-#endif
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    bswap = 1;
-#else
-    bswap = 0;
-#endif
-    data_reg = *args++;
-    if (opc == 3)
-        data_reg2 = *args++;
-    else
-        data_reg2 = 0; /* suppress warning */
-    addr_reg = *args++;
-#ifdef CONFIG_SOFTMMU
-# if TARGET_LONG_BITS == 64
-    addr_reg2 = *args++;
-# endif
-    mem_index = *args;
-    s_bits = opc & 3;
+/* Load and compare a TLB entry, leaving the flags set.  Leaves R0 pointing
+   to the tlb entry.  Clobbers R1 and TMP.  */
 
+static void tcg_out_tlb_read(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
+                             int s_bits, int tlb_offset)
+{
     /* Should generate something like the following:
      *  shr r8, addr_reg, #TARGET_PAGE_BITS
      *  and r0, r8, #(CPU_TLB_SIZE - 1)   @ Assumption: CPU_TLB_BITS <= 8
@@ -1190,13 +1165,13 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
 #   error
 #  endif
     tcg_out_dat_reg(s, COND_AL, ARITH_MOV, TCG_REG_TMP,
-                    0, addr_reg, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
+                    0, addrlo, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
     tcg_out_dat_imm(s, COND_AL, ARITH_AND,
                     TCG_REG_R0, TCG_REG_TMP, CPU_TLB_SIZE - 1);
     tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_R0, TCG_AREG0,
                     TCG_REG_R0, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS));
+
     /* We assume that the offset is contained within 20 bits.  */
-    tlb_offset = offsetof(CPUArchState, tlb_table[mem_index][0].addr_read);
     assert((tlb_offset & ~0xfffff) == 0);
     if (tlb_offset > 0xfff) {
         tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R0, TCG_REG_R0,
@@ -1206,16 +1181,48 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
     tcg_out_ld32_12wb(s, COND_AL, TCG_REG_R1, TCG_REG_R0, tlb_offset);
     tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0, TCG_REG_R1,
                     TCG_REG_TMP, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
+
     /* Check alignment.  */
-    if (s_bits)
+    if (s_bits) {
         tcg_out_dat_imm(s, COND_EQ, ARITH_TST,
-                        0, addr_reg, (1 << s_bits) - 1);
-#  if TARGET_LONG_BITS == 64
-    /* XXX: possibly we could use a block data load in the first access.  */
-    tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0, 4);
-    tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
-                    TCG_REG_R1, addr_reg2, SHIFT_IMM_LSL(0));
-#  endif
+                        0, addrlo, (1 << s_bits) - 1);
+    }
+
+    if (TARGET_LONG_BITS == 64) {
+        /* XXX: possibly we could use a block data load in the first access. */
+        tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0, 4);
+        tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
+                        TCG_REG_R1, addrhi, SHIFT_IMM_LSL(0));
+    }
+}
+#endif /* SOFTMMU */
+
+static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
+{
+    TCGReg addr_reg, data_reg, data_reg2;
+    bool bswap;
+#ifdef CONFIG_SOFTMMU
+    int mem_index, s_bits;
+    TCGReg argreg, addr_reg2;
+    uint32_t *label_ptr;
+#endif
+#ifdef TARGET_WORDS_BIGENDIAN
+    bswap = 1;
+#else
+    bswap = 0;
+#endif
+
+    data_reg = *args++;
+    data_reg2 = (opc == 3 ? *args++ : 0);
+    addr_reg = *args++;
+#ifdef CONFIG_SOFTMMU
+    addr_reg2 = (TARGET_LONG_BITS == 64 ? *args++ : 0);
+    mem_index = *args;
+    s_bits = opc & 3;
+
+    tcg_out_tlb_read(s, addr_reg, addr_reg2, s_bits,
+                     offsetof(CPUArchState, tlb_table[mem_index][0].addr_read));
+
     tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0,
                     offsetof(CPUTLBEntry, addend)
                     - offsetof(CPUTLBEntry, addr_read));
@@ -1271,11 +1278,11 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
      */
     argreg = TCG_REG_R0;
     argreg = tcg_out_arg_reg32(s, argreg, TCG_AREG0);
-#if TARGET_LONG_BITS == 64
-    argreg = tcg_out_arg_reg64(s, argreg, addr_reg, addr_reg2);
-#else
-    argreg = tcg_out_arg_reg32(s, argreg, addr_reg);
-#endif
+    if (TARGET_LONG_BITS == 64) {
+        argreg = tcg_out_arg_reg64(s, argreg, addr_reg, addr_reg2);
+    } else {
+        argreg = tcg_out_arg_reg32(s, argreg, addr_reg);
+    }
     argreg = tcg_out_arg_imm32(s, argreg, mem_index);
     tcg_out_call(s, (tcg_target_long) qemu_ld_helpers[s_bits]);
 
@@ -1302,8 +1309,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
 #else /* !CONFIG_SOFTMMU */
     if (GUEST_BASE) {
         uint32_t offset = GUEST_BASE;
-        int i;
-        int rot;
+        int i, rot;
 
         while (offset) {
             i = ctz32(offset) & ~1;
@@ -1362,68 +1368,33 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
 #endif
 }
 
-static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
+static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
 {
-    int addr_reg, data_reg, data_reg2, bswap;
+    TCGReg addr_reg, data_reg, data_reg2;
+    bool bswap;
 #ifdef CONFIG_SOFTMMU
-    int mem_index, s_bits, tlb_offset;
-    TCGReg argreg;
-# if TARGET_LONG_BITS == 64
-    int addr_reg2;
-# endif
+    int mem_index, s_bits;
+    TCGReg argreg, addr_reg2;
     uint32_t *label_ptr;
 #endif
-
 #ifdef TARGET_WORDS_BIGENDIAN
     bswap = 1;
 #else
     bswap = 0;
 #endif
+
     data_reg = *args++;
-    if (opc == 3)
-        data_reg2 = *args++;
-    else
-        data_reg2 = 0; /* suppress warning */
+    data_reg2 = (opc == 3 ? *args++ : 0);
     addr_reg = *args++;
 #ifdef CONFIG_SOFTMMU
-# if TARGET_LONG_BITS == 64
-    addr_reg2 = *args++;
-# endif
+    addr_reg2 = (TARGET_LONG_BITS == 64 ? *args++ : 0);
     mem_index = *args;
     s_bits = opc & 3;
 
-    /* Should generate something like the following:
-     *  shr r8, addr_reg, #TARGET_PAGE_BITS
-     *  and r0, r8, #(CPU_TLB_SIZE - 1)   @ Assumption: CPU_TLB_BITS <= 8
-     *  add r0, env, r0 lsl #CPU_TLB_ENTRY_BITS
-     */
-    tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
-                    TCG_REG_TMP, 0, addr_reg, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
-    tcg_out_dat_imm(s, COND_AL, ARITH_AND,
-                    TCG_REG_R0, TCG_REG_TMP, CPU_TLB_SIZE - 1);
-    tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_R0,
-                    TCG_AREG0, TCG_REG_R0, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS));
-    /* We assume that the offset is contained within 20 bits.  */
-    tlb_offset = offsetof(CPUArchState, tlb_table[mem_index][0].addr_write);
-    assert((tlb_offset & ~0xfffff) == 0);
-    if (tlb_offset > 0xfff) {
-        tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R0, TCG_REG_R0,
-                        0xa00 | (tlb_offset >> 12));
-        tlb_offset &= 0xfff;
-    }
-    tcg_out_ld32_12wb(s, COND_AL, TCG_REG_R1, TCG_REG_R0, tlb_offset);
-    tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0, TCG_REG_R1,
-                    TCG_REG_TMP, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
-    /* Check alignment.  */
-    if (s_bits)
-        tcg_out_dat_imm(s, COND_EQ, ARITH_TST,
-                        0, addr_reg, (1 << s_bits) - 1);
-#  if TARGET_LONG_BITS == 64
-    /* XXX: possibly we could use a block data load in the first access.  */
-    tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0, 4);
-    tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
-                    TCG_REG_R1, addr_reg2, SHIFT_IMM_LSL(0));
-#  endif
+    tcg_out_tlb_read(s, addr_reg, addr_reg2, s_bits,
+                     offsetof(CPUArchState,
+                              tlb_table[mem_index][0].addr_write));
+
     tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0,
                     offsetof(CPUTLBEntry, addend)
                     - offsetof(CPUTLBEntry, addr_write));
@@ -1472,11 +1443,11 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
      */
     argreg = TCG_REG_R0;
     argreg = tcg_out_arg_reg32(s, argreg, TCG_AREG0);
-#if TARGET_LONG_BITS == 64
-    argreg = tcg_out_arg_reg64(s, argreg, addr_reg, addr_reg2);
-#else
-    argreg = tcg_out_arg_reg32(s, argreg, addr_reg);
-#endif
+    if (TARGET_LONG_BITS == 64) {
+        argreg = tcg_out_arg_reg64(s, argreg, addr_reg, addr_reg2);
+    } else {
+        argreg = tcg_out_arg_reg32(s, argreg, addr_reg);
+    }
 
     switch (opc) {
     case 0:
commit 9feac1d77010b371501728256be96bf91b641985
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Mar 12 15:06:53 2013 -0700

    tcg-arm: Cleanup most primitive load store subroutines
    
    Use even more primitive helper functions to avoid lots of duplicated code.
    
    Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 4c9a9dc..92d7cee 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -312,7 +312,7 @@ static inline int tcg_target_const_match(tcg_target_long val,
 
 #define TO_CPSR (1 << 20)
 
-enum arm_data_opc_e {
+typedef enum {
     ARITH_AND = 0x0 << 21,
     ARITH_EOR = 0x1 << 21,
     ARITH_SUB = 0x2 << 21,
@@ -328,7 +328,26 @@ enum arm_data_opc_e {
     ARITH_MOV = 0xd << 21,
     ARITH_BIC = 0xe << 21,
     ARITH_MVN = 0xf << 21,
-};
+
+    INSN_LDR_IMM   = 0x04100000,
+    INSN_LDR_REG   = 0x06100000,
+    INSN_STR_IMM   = 0x04000000,
+    INSN_STR_REG   = 0x06000000,
+
+    INSN_LDRH_IMM  = 0x005000b0,
+    INSN_LDRH_REG  = 0x001000b0,
+    INSN_LDRSH_IMM = 0x005000f0,
+    INSN_LDRSH_REG = 0x001000f0,
+    INSN_STRH_IMM  = 0x004000b0,
+    INSN_STRH_REG  = 0x000000b0,
+
+    INSN_LDRB_IMM  = 0x04500000,
+    INSN_LDRB_REG  = 0x06500000,
+    INSN_LDRSB_IMM = 0x005000d0,
+    INSN_LDRSB_REG = 0x001000d0,
+    INSN_STRB_IMM  = 0x04400000,
+    INSN_STRB_REG  = 0x06400000,
+} ARMInsn;
 
 #define SHIFT_IMM_LSL(im)	(((im) << 7) | 0x00)
 #define SHIFT_IMM_LSR(im)	(((im) << 7) | 0x20)
@@ -747,187 +766,155 @@ static inline void tcg_out_deposit(TCGContext *s, int cond, TCGReg rd,
               | (ofs << 7) | ((ofs + len - 1) << 16));
 }
 
-static inline void tcg_out_ld32_12(TCGContext *s, int cond,
-                int rd, int rn, tcg_target_long im)
+/* Note that this routine is used for both LDR and LDRH formats, so we do
+   not wish to include an immediate shift at this point.  */
+static void tcg_out_memop_r(TCGContext *s, int cond, ARMInsn opc, TCGReg rt,
+                            TCGReg rn, TCGReg rm, bool u, bool p, bool w)
 {
-    if (im >= 0)
-        tcg_out32(s, (cond << 28) | 0x05900000 |
-                        (rn << 16) | (rd << 12) | (im & 0xfff));
-    else
-        tcg_out32(s, (cond << 28) | 0x05100000 |
-                        (rn << 16) | (rd << 12) | ((-im) & 0xfff));
+    tcg_out32(s, (cond << 28) | opc | (u << 23) | (p << 24)
+              | (w << 21) | (rn << 16) | (rt << 12) | rm);
+}
+
+static void tcg_out_memop_8(TCGContext *s, int cond, ARMInsn opc, TCGReg rt,
+                            TCGReg rn, int imm8, bool p, bool w)
+{
+    bool u = 1;
+    if (imm8 < 0) {
+        imm8 = -imm8;
+        u = 0;
+    }
+    tcg_out32(s, (cond << 28) | opc | (u << 23) | (p << 24) | (w << 21) |
+              (rn << 16) | (rt << 12) | ((imm8 & 0xf0) << 4) | (imm8 & 0xf));
+}
+
+static void tcg_out_memop_12(TCGContext *s, int cond, ARMInsn opc, TCGReg rt,
+                             TCGReg rn, int imm12, bool p, bool w)
+{
+    bool u = 1;
+    if (imm12 < 0) {
+        imm12 = -imm12;
+        u = 0;
+    }
+    tcg_out32(s, (cond << 28) | opc | (u << 23) | (p << 24) | (w << 21) |
+              (rn << 16) | (rt << 12) | imm12);
+}
+
+static inline void tcg_out_ld32_12(TCGContext *s, int cond, TCGReg rt,
+                                   TCGReg rn, int imm12)
+{
+    tcg_out_memop_12(s, cond, INSN_LDR_IMM, rt, rn, imm12, 1, 0);
 }
 
 /* Offset pre-increment with base writeback.  */
-static inline void tcg_out_ld32_12wb(TCGContext *s, int cond,
-                                     int rd, int rn, tcg_target_long im)
+static inline void tcg_out_ld32_12wb(TCGContext *s, int cond, TCGReg rt,
+                                     TCGReg rn, int imm12)
 {
     /* ldr with writeback and both register equals is UNPREDICTABLE */
     assert(rd != rn);
-
-    if (im >= 0) {
-        tcg_out32(s, (cond << 28) | 0x05b00000 |
-                        (rn << 16) | (rd << 12) | (im & 0xfff));
-    } else {
-        tcg_out32(s, (cond << 28) | 0x05300000 |
-                        (rn << 16) | (rd << 12) | ((-im) & 0xfff));
-    }
+    tcg_out_memop_12(s, cond, INSN_LDR_IMM, rt, rn, imm12, 1, 1);
 }
 
-static inline void tcg_out_st32_12(TCGContext *s, int cond,
-                int rd, int rn, tcg_target_long im)
+static inline void tcg_out_st32_12(TCGContext *s, int cond, TCGReg rt,
+                                   TCGReg rn, int imm12)
 {
-    if (im >= 0)
-        tcg_out32(s, (cond << 28) | 0x05800000 |
-                        (rn << 16) | (rd << 12) | (im & 0xfff));
-    else
-        tcg_out32(s, (cond << 28) | 0x05000000 |
-                        (rn << 16) | (rd << 12) | ((-im) & 0xfff));
+    tcg_out_memop_12(s, cond, INSN_STR_IMM, rt, rn, imm12, 1, 0);
 }
 
-static inline void tcg_out_ld32_r(TCGContext *s, int cond,
-                int rd, int rn, int rm)
+static inline void tcg_out_ld32_r(TCGContext *s, int cond, TCGReg rt,
+                                  TCGReg rn, TCGReg rm)
 {
-    tcg_out32(s, (cond << 28) | 0x07900000 |
-                    (rn << 16) | (rd << 12) | rm);
+    tcg_out_memop_r(s, cond, INSN_LDR_REG, rt, rn, rm, 1, 1, 0);
 }
 
-static inline void tcg_out_st32_r(TCGContext *s, int cond,
-                int rd, int rn, int rm)
+static inline void tcg_out_st32_r(TCGContext *s, int cond, TCGReg rt,
+                                  TCGReg rn, TCGReg rm)
 {
-    tcg_out32(s, (cond << 28) | 0x07800000 |
-                    (rn << 16) | (rd << 12) | rm);
+    tcg_out_memop_r(s, cond, INSN_STR_REG, rt, rn, rm, 1, 1, 0);
 }
 
 /* Register pre-increment with base writeback.  */
-static inline void tcg_out_ld32_rwb(TCGContext *s, int cond,
-                int rd, int rn, int rm)
+static inline void tcg_out_ld32_rwb(TCGContext *s, int cond, TCGReg rt,
+                                    TCGReg rn, TCGReg rm)
 {
-    tcg_out32(s, (cond << 28) | 0x07b00000 |
-                    (rn << 16) | (rd << 12) | rm);
+    tcg_out_memop_r(s, cond, INSN_LDR_REG, rt, rn, rm, 1, 1, 1);
 }
 
-static inline void tcg_out_st32_rwb(TCGContext *s, int cond,
-                int rd, int rn, int rm)
+static inline void tcg_out_st32_rwb(TCGContext *s, int cond, TCGReg rt,
+                                    TCGReg rn, TCGReg rm)
 {
-    tcg_out32(s, (cond << 28) | 0x07a00000 |
-                    (rn << 16) | (rd << 12) | rm);
+    tcg_out_memop_r(s, cond, INSN_STR_REG, rt, rn, rm, 1, 1, 1);
 }
 
-static inline void tcg_out_ld16u_8(TCGContext *s, int cond,
-                int rd, int rn, tcg_target_long im)
+static inline void tcg_out_ld16u_8(TCGContext *s, int cond, TCGReg rt,
+                                   TCGReg rn, int imm8)
 {
-    if (im >= 0)
-        tcg_out32(s, (cond << 28) | 0x01d000b0 |
-                        (rn << 16) | (rd << 12) |
-                        ((im & 0xf0) << 4) | (im & 0xf));
-    else
-        tcg_out32(s, (cond << 28) | 0x015000b0 |
-                        (rn << 16) | (rd << 12) |
-                        (((-im) & 0xf0) << 4) | ((-im) & 0xf));
+    tcg_out_memop_8(s, cond, INSN_LDRH_IMM, rt, rn, imm8, 1, 0);
 }
 
-static inline void tcg_out_st16_8(TCGContext *s, int cond,
-                int rd, int rn, tcg_target_long im)
+static inline void tcg_out_st16_8(TCGContext *s, int cond, TCGReg rt,
+                                  TCGReg rn, int imm8)
 {
-    if (im >= 0)
-        tcg_out32(s, (cond << 28) | 0x01c000b0 |
-                        (rn << 16) | (rd << 12) |
-                        ((im & 0xf0) << 4) | (im & 0xf));
-    else
-        tcg_out32(s, (cond << 28) | 0x014000b0 |
-                        (rn << 16) | (rd << 12) |
-                        (((-im) & 0xf0) << 4) | ((-im) & 0xf));
+    tcg_out_memop_8(s, cond, INSN_STRH_IMM, rt, rn, imm8, 1, 0);
 }
 
-static inline void tcg_out_ld16u_r(TCGContext *s, int cond,
-                int rd, int rn, int rm)
+static inline void tcg_out_ld16u_r(TCGContext *s, int cond, TCGReg rt,
+                                   TCGReg rn, TCGReg rm)
 {
-    tcg_out32(s, (cond << 28) | 0x019000b0 |
-                    (rn << 16) | (rd << 12) | rm);
+    tcg_out_memop_r(s, cond, INSN_LDRH_REG, rt, rn, rm, 1, 1, 0);
 }
 
-static inline void tcg_out_st16_r(TCGContext *s, int cond,
-                int rd, int rn, int rm)
+static inline void tcg_out_st16_r(TCGContext *s, int cond, TCGReg rt,
+                                  TCGReg rn, TCGReg rm)
 {
-    tcg_out32(s, (cond << 28) | 0x018000b0 |
-                    (rn << 16) | (rd << 12) | rm);
+    tcg_out_memop_r(s, cond, INSN_STRH_REG, rt, rn, rm, 1, 1, 0);
 }
 
-static inline void tcg_out_ld16s_8(TCGContext *s, int cond,
-                int rd, int rn, tcg_target_long im)
+static inline void tcg_out_ld16s_8(TCGContext *s, int cond, TCGReg rt,
+                                   TCGReg rn, int imm8)
 {
-    if (im >= 0)
-        tcg_out32(s, (cond << 28) | 0x01d000f0 |
-                        (rn << 16) | (rd << 12) |
-                        ((im & 0xf0) << 4) | (im & 0xf));
-    else
-        tcg_out32(s, (cond << 28) | 0x015000f0 |
-                        (rn << 16) | (rd << 12) |
-                        (((-im) & 0xf0) << 4) | ((-im) & 0xf));
+    tcg_out_memop_8(s, cond, INSN_LDRSH_IMM, rt, rn, imm8, 1, 0);
 }
 
-static inline void tcg_out_ld16s_r(TCGContext *s, int cond,
-                int rd, int rn, int rm)
+static inline void tcg_out_ld16s_r(TCGContext *s, int cond, TCGReg rt,
+                                   TCGReg rn, TCGReg rm)
 {
-    tcg_out32(s, (cond << 28) | 0x019000f0 |
-                    (rn << 16) | (rd << 12) | rm);
+    tcg_out_memop_r(s, cond, INSN_LDRSH_REG, rt, rn, rm, 1, 1, 0);
 }
 
-static inline void tcg_out_ld8_12(TCGContext *s, int cond,
-                int rd, int rn, tcg_target_long im)
+static inline void tcg_out_ld8_12(TCGContext *s, int cond, TCGReg rt,
+                                  TCGReg rn, int imm12)
 {
-    if (im >= 0)
-        tcg_out32(s, (cond << 28) | 0x05d00000 |
-                        (rn << 16) | (rd << 12) | (im & 0xfff));
-    else
-        tcg_out32(s, (cond << 28) | 0x05500000 |
-                        (rn << 16) | (rd << 12) | ((-im) & 0xfff));
+    tcg_out_memop_12(s, cond, INSN_LDRB_IMM, rt, rn, imm12, 1, 0);
 }
 
-static inline void tcg_out_st8_12(TCGContext *s, int cond,
-                int rd, int rn, tcg_target_long im)
+static inline void tcg_out_st8_12(TCGContext *s, int cond, TCGReg rt,
+                                  TCGReg rn, int imm12)
 {
-    if (im >= 0)
-        tcg_out32(s, (cond << 28) | 0x05c00000 |
-                        (rn << 16) | (rd << 12) | (im & 0xfff));
-    else
-        tcg_out32(s, (cond << 28) | 0x05400000 |
-                        (rn << 16) | (rd << 12) | ((-im) & 0xfff));
+    tcg_out_memop_12(s, cond, INSN_STRB_IMM, rt, rn, imm12, 1, 0);
 }
 
-static inline void tcg_out_ld8_r(TCGContext *s, int cond,
-                int rd, int rn, int rm)
+static inline void tcg_out_ld8_r(TCGContext *s, int cond, TCGReg rt,
+                                 TCGReg rn, TCGReg rm)
 {
-    tcg_out32(s, (cond << 28) | 0x07d00000 |
-                    (rn << 16) | (rd << 12) | rm);
+    tcg_out_memop_r(s, cond, INSN_LDRB_REG, rt, rn, rm, 1, 1, 0);
 }
 
-static inline void tcg_out_st8_r(TCGContext *s, int cond,
-                int rd, int rn, int rm)
+static inline void tcg_out_st8_r(TCGContext *s, int cond, TCGReg rt,
+                                 TCGReg rn, TCGReg rm)
 {
-    tcg_out32(s, (cond << 28) | 0x07c00000 |
-                    (rn << 16) | (rd << 12) | rm);
+    tcg_out_memop_r(s, cond, INSN_STRB_REG, rt, rn, rm, 1, 1, 0);
 }
 
-static inline void tcg_out_ld8s_8(TCGContext *s, int cond,
-                int rd, int rn, tcg_target_long im)
+static inline void tcg_out_ld8s_8(TCGContext *s, int cond, TCGReg rt,
+                                  TCGReg rn, int imm8)
 {
-    if (im >= 0)
-        tcg_out32(s, (cond << 28) | 0x01d000d0 |
-                        (rn << 16) | (rd << 12) |
-                        ((im & 0xf0) << 4) | (im & 0xf));
-    else
-        tcg_out32(s, (cond << 28) | 0x015000d0 |
-                        (rn << 16) | (rd << 12) |
-                        (((-im) & 0xf0) << 4) | ((-im) & 0xf));
+    tcg_out_memop_8(s, cond, INSN_LDRSB_IMM, rt, rn, imm8, 1, 0);
 }
 
-static inline void tcg_out_ld8s_r(TCGContext *s, int cond,
-                int rd, int rn, int rm)
+static inline void tcg_out_ld8s_r(TCGContext *s, int cond, TCGReg rt,
+                                  TCGReg rn, TCGReg rm)
 {
-    tcg_out32(s, (cond << 28) | 0x019000d0 |
-                    (rn << 16) | (rd << 12) | rm);
+    tcg_out_memop_r(s, cond, INSN_LDRSB_REG, rt, rn, rm, 1, 1, 0);
 }
 
 static inline void tcg_out_ld32u(TCGContext *s, int cond,
commit 34358a12c8a8f2f85a1420fa0a1112de1c6a55af
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Mar 12 10:34:18 2013 -0700

    tcg-arm: Cleanup multiply subroutines
    
    Make the code more readable by only having one copy of the magic
    numbers, swapping registers as needed prior to that.  Speed the
    compiler by not applying the rd == rn avoidance for v6 or later.
    
    Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index ff75379..4c9a9dc 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -548,55 +548,60 @@ static void tcg_out_dat_rIN(TCGContext *s, int cond, int opc, int opneg,
     }
 }
 
-static inline void tcg_out_mul32(TCGContext *s,
-                int cond, int rd, int rs, int rm)
-{
-    if (rd != rm)
-        tcg_out32(s, (cond << 28) | (rd << 16) | (0 << 12) |
-                        (rs << 8) | 0x90 | rm);
-    else if (rd != rs)
-        tcg_out32(s, (cond << 28) | (rd << 16) | (0 << 12) |
-                        (rm << 8) | 0x90 | rs);
-    else {
-        tcg_out32(s, (cond << 28) | (TCG_REG_TMP << 16) | (0 << 12) |
-                        (rs << 8) | 0x90 | rm);
-        tcg_out_dat_reg(s, cond, ARITH_MOV,
-                        rd, 0, TCG_REG_TMP, SHIFT_IMM_LSL(0));
+static inline void tcg_out_mul32(TCGContext *s, int cond, TCGReg rd,
+                                 TCGReg rn, TCGReg rm)
+{
+    /* if ArchVersion() < 6 && d == n then UNPREDICTABLE;  */
+    if (!use_armv6_instructions && rd == rn) {
+        if (rd == rm) {
+            /* rd == rn == rm; copy an input to tmp first.  */
+            tcg_out_mov_reg(s, cond, TCG_REG_TMP, rn);
+            rm = rn = TCG_REG_TMP;
+        } else {
+            rn = rm;
+            rm = rd;
+        }
     }
+    /* mul */
+    tcg_out32(s, (cond << 28) | 0x90 | (rd << 16) | (rm << 8) | rn);
 }
 
-static inline void tcg_out_umull32(TCGContext *s,
-                int cond, int rd0, int rd1, int rs, int rm)
+static inline void tcg_out_umull32(TCGContext *s, int cond, TCGReg rd0,
+                                   TCGReg rd1, TCGReg rn, TCGReg rm)
 {
-    if (rd0 != rm && rd1 != rm)
-        tcg_out32(s, (cond << 28) | 0x800090 |
-                        (rd1 << 16) | (rd0 << 12) | (rs << 8) | rm);
-    else if (rd0 != rs && rd1 != rs)
-        tcg_out32(s, (cond << 28) | 0x800090 |
-                        (rd1 << 16) | (rd0 << 12) | (rm << 8) | rs);
-    else {
-        tcg_out_dat_reg(s, cond, ARITH_MOV,
-                        TCG_REG_TMP, 0, rm, SHIFT_IMM_LSL(0));
-        tcg_out32(s, (cond << 28) | 0x800090 | TCG_REG_TMP |
-                        (rd1 << 16) | (rd0 << 12) | (rs << 8));
+    /* if ArchVersion() < 6 && (dHi == n || dLo == n) then UNPREDICTABLE;  */
+    if (!use_armv6_instructions && (rd0 == rn || rd1 == rn)) {
+        if (rd0 == rm || rd1 == rm) {
+            tcg_out_mov_reg(s, cond, TCG_REG_TMP, rn);
+            rn = TCG_REG_TMP;
+        } else {
+            TCGReg t = rn;
+            rn = rm;
+            rm = t;
+        }
     }
+    /* umull */
+    tcg_out32(s, (cond << 28) | 0x00800090 |
+              (rd1 << 16) | (rd0 << 12) | (rm << 8) | rn);
 }
 
-static inline void tcg_out_smull32(TCGContext *s,
-                int cond, int rd0, int rd1, int rs, int rm)
+static inline void tcg_out_smull32(TCGContext *s, int cond, TCGReg rd0,
+                                   TCGReg rd1, TCGReg rn, TCGReg rm)
 {
-    if (rd0 != rm && rd1 != rm)
-        tcg_out32(s, (cond << 28) | 0xc00090 |
-                        (rd1 << 16) | (rd0 << 12) | (rs << 8) | rm);
-    else if (rd0 != rs && rd1 != rs)
-        tcg_out32(s, (cond << 28) | 0xc00090 |
-                        (rd1 << 16) | (rd0 << 12) | (rm << 8) | rs);
-    else {
-        tcg_out_dat_reg(s, cond, ARITH_MOV,
-                        TCG_REG_TMP, 0, rm, SHIFT_IMM_LSL(0));
-        tcg_out32(s, (cond << 28) | 0xc00090 | TCG_REG_TMP |
-                        (rd1 << 16) | (rd0 << 12) | (rs << 8));
+    /* if ArchVersion() < 6 && (dHi == n || dLo == n) then UNPREDICTABLE;  */
+    if (!use_armv6_instructions && (rd0 == rn || rd1 == rn)) {
+        if (rd0 == rm || rd1 == rm) {
+            tcg_out_mov_reg(s, cond, TCG_REG_TMP, rn);
+            rn = TCG_REG_TMP;
+        } else {
+            TCGReg t = rn;
+            rn = rm;
+            rm = t;
+        }
     }
+    /* smull */
+    tcg_out32(s, (cond << 28) | 0x00c00090 |
+              (rd1 << 16) | (rd0 << 12) | (rm << 8) | rn);
 }
 
 static inline void tcg_out_sdiv(TCGContext *s, int cond, int rd, int rn, int rm)
commit 13dd6fb962930a4b1d74f9b22342d1eb15e9194e
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Mar 12 09:50:25 2013 -0700

    tcg-arm: Use R12 for the tcg temporary
    
    R12 is call clobbered, while R8 is call saved.  This change
    gives tcg one more call saved register for real data.
    
    Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index cc442b6..ff75379 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -113,7 +113,7 @@ static const int tcg_target_call_oarg_regs[2] = {
     TCG_REG_R0, TCG_REG_R1
 };
 
-#define TCG_REG_TMP  TCG_REG_R8
+#define TCG_REG_TMP  TCG_REG_R12
 
 static inline void reloc_abs32(void *code_ptr, tcg_target_long target)
 {
commit 4346457a47732cc0bd3a8f36d743624dc277ea55
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Mar 12 09:49:04 2013 -0700

    tcg-arm: Use TCG_REG_TMP name for the tcg temporary
    
    Don't hard-code R8.
    
    Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index b0e73d2..cc442b6 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -113,6 +113,8 @@ static const int tcg_target_call_oarg_regs[2] = {
     TCG_REG_R0, TCG_REG_R1
 };
 
+#define TCG_REG_TMP  TCG_REG_R8
+
 static inline void reloc_abs32(void *code_ptr, tcg_target_long target)
 {
     *(uint32_t *) code_ptr = target;
@@ -556,10 +558,10 @@ static inline void tcg_out_mul32(TCGContext *s,
         tcg_out32(s, (cond << 28) | (rd << 16) | (0 << 12) |
                         (rm << 8) | 0x90 | rs);
     else {
-        tcg_out32(s, (cond << 28) | ( 8 << 16) | (0 << 12) |
+        tcg_out32(s, (cond << 28) | (TCG_REG_TMP << 16) | (0 << 12) |
                         (rs << 8) | 0x90 | rm);
         tcg_out_dat_reg(s, cond, ARITH_MOV,
-                        rd, 0, TCG_REG_R8, SHIFT_IMM_LSL(0));
+                        rd, 0, TCG_REG_TMP, SHIFT_IMM_LSL(0));
     }
 }
 
@@ -574,8 +576,8 @@ static inline void tcg_out_umull32(TCGContext *s,
                         (rd1 << 16) | (rd0 << 12) | (rm << 8) | rs);
     else {
         tcg_out_dat_reg(s, cond, ARITH_MOV,
-                        TCG_REG_R8, 0, rm, SHIFT_IMM_LSL(0));
-        tcg_out32(s, (cond << 28) | 0x800098 |
+                        TCG_REG_TMP, 0, rm, SHIFT_IMM_LSL(0));
+        tcg_out32(s, (cond << 28) | 0x800090 | TCG_REG_TMP |
                         (rd1 << 16) | (rd0 << 12) | (rs << 8));
     }
 }
@@ -591,8 +593,8 @@ static inline void tcg_out_smull32(TCGContext *s,
                         (rd1 << 16) | (rd0 << 12) | (rm << 8) | rs);
     else {
         tcg_out_dat_reg(s, cond, ARITH_MOV,
-                        TCG_REG_R8, 0, rm, SHIFT_IMM_LSL(0));
-        tcg_out32(s, (cond << 28) | 0xc00098 |
+                        TCG_REG_TMP, 0, rm, SHIFT_IMM_LSL(0));
+        tcg_out32(s, (cond << 28) | 0xc00090 | TCG_REG_TMP |
                         (rd1 << 16) | (rd0 << 12) | (rs << 8));
     }
 }
@@ -662,11 +664,11 @@ static inline void tcg_out_bswap16s(TCGContext *s, int cond, int rd, int rn)
         tcg_out32(s, 0x06ff0fb0 | (cond << 28) | (rd << 12) | rn);
     } else {
         tcg_out_dat_reg(s, cond, ARITH_MOV,
-                        TCG_REG_R8, 0, rn, SHIFT_IMM_LSL(24));
+                        TCG_REG_TMP, 0, rn, SHIFT_IMM_LSL(24));
         tcg_out_dat_reg(s, cond, ARITH_MOV,
-                        TCG_REG_R8, 0, TCG_REG_R8, SHIFT_IMM_ASR(16));
+                        TCG_REG_TMP, 0, TCG_REG_TMP, SHIFT_IMM_ASR(16));
         tcg_out_dat_reg(s, cond, ARITH_ORR,
-                        rd, TCG_REG_R8, rn, SHIFT_IMM_LSR(8));
+                        rd, TCG_REG_TMP, rn, SHIFT_IMM_LSR(8));
     }
 }
 
@@ -677,11 +679,11 @@ static inline void tcg_out_bswap16(TCGContext *s, int cond, int rd, int rn)
         tcg_out32(s, 0x06bf0fb0 | (cond << 28) | (rd << 12) | rn);
     } else {
         tcg_out_dat_reg(s, cond, ARITH_MOV,
-                        TCG_REG_R8, 0, rn, SHIFT_IMM_LSL(24));
+                        TCG_REG_TMP, 0, rn, SHIFT_IMM_LSL(24));
         tcg_out_dat_reg(s, cond, ARITH_MOV,
-                        TCG_REG_R8, 0, TCG_REG_R8, SHIFT_IMM_LSR(16));
+                        TCG_REG_TMP, 0, TCG_REG_TMP, SHIFT_IMM_LSR(16));
         tcg_out_dat_reg(s, cond, ARITH_ORR,
-                        rd, TCG_REG_R8, rn, SHIFT_IMM_LSR(8));
+                        rd, TCG_REG_TMP, rn, SHIFT_IMM_LSR(8));
     }
 }
 
@@ -694,10 +696,10 @@ static inline void tcg_out_bswap16st(TCGContext *s, int cond, int rd, int rn)
         tcg_out32(s, 0x06bf0fb0 | (cond << 28) | (rd << 12) | rn);
     } else {
         tcg_out_dat_reg(s, cond, ARITH_MOV,
-                        TCG_REG_R8, 0, rn, SHIFT_IMM_LSR(8));
-        tcg_out_dat_imm(s, cond, ARITH_AND, TCG_REG_R8, TCG_REG_R8, 0xff);
+                        TCG_REG_TMP, 0, rn, SHIFT_IMM_LSR(8));
+        tcg_out_dat_imm(s, cond, ARITH_AND, TCG_REG_TMP, TCG_REG_TMP, 0xff);
         tcg_out_dat_reg(s, cond, ARITH_ORR,
-                        rd, TCG_REG_R8, rn, SHIFT_IMM_LSL(8));
+                        rd, TCG_REG_TMP, rn, SHIFT_IMM_LSL(8));
     }
 }
 
@@ -708,13 +710,13 @@ static inline void tcg_out_bswap32(TCGContext *s, int cond, int rd, int rn)
         tcg_out32(s, 0x06bf0f30 | (cond << 28) | (rd << 12) | rn);
     } else {
         tcg_out_dat_reg(s, cond, ARITH_EOR,
-                        TCG_REG_R8, rn, rn, SHIFT_IMM_ROR(16));
+                        TCG_REG_TMP, rn, rn, SHIFT_IMM_ROR(16));
         tcg_out_dat_imm(s, cond, ARITH_BIC,
-                        TCG_REG_R8, TCG_REG_R8, 0xff | 0x800);
+                        TCG_REG_TMP, TCG_REG_TMP, 0xff | 0x800);
         tcg_out_dat_reg(s, cond, ARITH_MOV,
                         rd, 0, rn, SHIFT_IMM_ROR(8));
         tcg_out_dat_reg(s, cond, ARITH_EOR,
-                        rd, rd, TCG_REG_R8, SHIFT_IMM_LSR(8));
+                        rd, rd, TCG_REG_TMP, SHIFT_IMM_LSR(8));
     }
 }
 
@@ -927,8 +929,8 @@ static inline void tcg_out_ld32u(TCGContext *s, int cond,
                 int rd, int rn, int32_t offset)
 {
     if (offset > 0xfff || offset < -0xfff) {
-        tcg_out_movi32(s, cond, TCG_REG_R8, offset);
-        tcg_out_ld32_r(s, cond, rd, rn, TCG_REG_R8);
+        tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
+        tcg_out_ld32_r(s, cond, rd, rn, TCG_REG_TMP);
     } else
         tcg_out_ld32_12(s, cond, rd, rn, offset);
 }
@@ -937,8 +939,8 @@ static inline void tcg_out_st32(TCGContext *s, int cond,
                 int rd, int rn, int32_t offset)
 {
     if (offset > 0xfff || offset < -0xfff) {
-        tcg_out_movi32(s, cond, TCG_REG_R8, offset);
-        tcg_out_st32_r(s, cond, rd, rn, TCG_REG_R8);
+        tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
+        tcg_out_st32_r(s, cond, rd, rn, TCG_REG_TMP);
     } else
         tcg_out_st32_12(s, cond, rd, rn, offset);
 }
@@ -947,8 +949,8 @@ static inline void tcg_out_ld16u(TCGContext *s, int cond,
                 int rd, int rn, int32_t offset)
 {
     if (offset > 0xff || offset < -0xff) {
-        tcg_out_movi32(s, cond, TCG_REG_R8, offset);
-        tcg_out_ld16u_r(s, cond, rd, rn, TCG_REG_R8);
+        tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
+        tcg_out_ld16u_r(s, cond, rd, rn, TCG_REG_TMP);
     } else
         tcg_out_ld16u_8(s, cond, rd, rn, offset);
 }
@@ -957,8 +959,8 @@ static inline void tcg_out_ld16s(TCGContext *s, int cond,
                 int rd, int rn, int32_t offset)
 {
     if (offset > 0xff || offset < -0xff) {
-        tcg_out_movi32(s, cond, TCG_REG_R8, offset);
-        tcg_out_ld16s_r(s, cond, rd, rn, TCG_REG_R8);
+        tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
+        tcg_out_ld16s_r(s, cond, rd, rn, TCG_REG_TMP);
     } else
         tcg_out_ld16s_8(s, cond, rd, rn, offset);
 }
@@ -967,8 +969,8 @@ static inline void tcg_out_st16(TCGContext *s, int cond,
                 int rd, int rn, int32_t offset)
 {
     if (offset > 0xff || offset < -0xff) {
-        tcg_out_movi32(s, cond, TCG_REG_R8, offset);
-        tcg_out_st16_r(s, cond, rd, rn, TCG_REG_R8);
+        tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
+        tcg_out_st16_r(s, cond, rd, rn, TCG_REG_TMP);
     } else
         tcg_out_st16_8(s, cond, rd, rn, offset);
 }
@@ -977,8 +979,8 @@ static inline void tcg_out_ld8u(TCGContext *s, int cond,
                 int rd, int rn, int32_t offset)
 {
     if (offset > 0xfff || offset < -0xfff) {
-        tcg_out_movi32(s, cond, TCG_REG_R8, offset);
-        tcg_out_ld8_r(s, cond, rd, rn, TCG_REG_R8);
+        tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
+        tcg_out_ld8_r(s, cond, rd, rn, TCG_REG_TMP);
     } else
         tcg_out_ld8_12(s, cond, rd, rn, offset);
 }
@@ -987,8 +989,8 @@ static inline void tcg_out_ld8s(TCGContext *s, int cond,
                 int rd, int rn, int32_t offset)
 {
     if (offset > 0xff || offset < -0xff) {
-        tcg_out_movi32(s, cond, TCG_REG_R8, offset);
-        tcg_out_ld8s_r(s, cond, rd, rn, TCG_REG_R8);
+        tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
+        tcg_out_ld8s_r(s, cond, rd, rn, TCG_REG_TMP);
     } else
         tcg_out_ld8s_8(s, cond, rd, rn, offset);
 }
@@ -997,8 +999,8 @@ static inline void tcg_out_st8(TCGContext *s, int cond,
                 int rd, int rn, int32_t offset)
 {
     if (offset > 0xfff || offset < -0xfff) {
-        tcg_out_movi32(s, cond, TCG_REG_R8, offset);
-        tcg_out_st8_r(s, cond, rd, rn, TCG_REG_R8);
+        tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
+        tcg_out_st8_r(s, cond, rd, rn, TCG_REG_TMP);
     } else
         tcg_out_st8_12(s, cond, rd, rn, offset);
 }
@@ -1026,10 +1028,10 @@ static inline void tcg_out_goto(TCGContext *s, int cond, uint32_t addr)
             tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
             tcg_out32(s, addr);
         } else {
-            tcg_out_movi32(s, cond, TCG_REG_R8, val - 8);
+            tcg_out_movi32(s, cond, TCG_REG_TMP, val - 8);
             tcg_out_dat_reg(s, cond, ARITH_ADD,
                             TCG_REG_PC, TCG_REG_PC,
-                            TCG_REG_R8, SHIFT_IMM_LSL(0));
+                            TCG_REG_TMP, SHIFT_IMM_LSL(0));
         }
     }
 }
@@ -1133,11 +1135,11 @@ static TCGReg NAME(TCGContext *s, TCGReg argreg, ARGTYPE arg)              \
 }
 
 DEFINE_TCG_OUT_ARG(tcg_out_arg_imm32, uint32_t, tcg_out_movi32,
-    (tcg_out_movi32(s, COND_AL, TCG_REG_R8, arg), arg = TCG_REG_R8))
+    (tcg_out_movi32(s, COND_AL, TCG_REG_TMP, arg), arg = TCG_REG_TMP))
 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg8, TCGReg, tcg_out_ext8u,
-    (tcg_out_ext8u(s, COND_AL, TCG_REG_R8, arg), arg = TCG_REG_R8))
+    (tcg_out_ext8u(s, COND_AL, TCG_REG_TMP, arg), arg = TCG_REG_TMP))
 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg16, TCGReg, tcg_out_ext16u,
-    (tcg_out_ext16u(s, COND_AL, TCG_REG_R8, arg), arg = TCG_REG_R8))
+    (tcg_out_ext16u(s, COND_AL, TCG_REG_TMP, arg), arg = TCG_REG_TMP))
 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg32, TCGReg, tcg_out_mov_reg, )
 
 static TCGReg tcg_out_arg_reg64(TCGContext *s, TCGReg argreg,
@@ -1195,10 +1197,10 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
 #  if CPU_TLB_BITS > 8
 #   error
 #  endif
-    tcg_out_dat_reg(s, COND_AL, ARITH_MOV, TCG_REG_R8,
+    tcg_out_dat_reg(s, COND_AL, ARITH_MOV, TCG_REG_TMP,
                     0, addr_reg, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
     tcg_out_dat_imm(s, COND_AL, ARITH_AND,
-                    TCG_REG_R0, TCG_REG_R8, CPU_TLB_SIZE - 1);
+                    TCG_REG_R0, TCG_REG_TMP, CPU_TLB_SIZE - 1);
     tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_R0, TCG_AREG0,
                     TCG_REG_R0, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS));
     /* We assume that the offset is contained within 20 bits.  */
@@ -1211,7 +1213,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
     }
     tcg_out_ld32_12wb(s, COND_AL, TCG_REG_R1, TCG_REG_R0, tlb_offset);
     tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0, TCG_REG_R1,
-                    TCG_REG_R8, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
+                    TCG_REG_TMP, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
     /* Check alignment.  */
     if (s_bits)
         tcg_out_dat_imm(s, COND_EQ, ARITH_TST,
@@ -1315,9 +1317,9 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
             i = ctz32(offset) & ~1;
             rot = ((32 - i) << 7) & 0xf00;
 
-            tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R8, addr_reg,
+            tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_TMP, addr_reg,
                             ((offset >> i) & 0xff) | rot);
-            addr_reg = TCG_REG_R8;
+            addr_reg = TCG_REG_TMP;
             offset &= ~(0xff << i);
         }
     }
@@ -1404,9 +1406,9 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
      *  add r0, env, r0 lsl #CPU_TLB_ENTRY_BITS
      */
     tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
-                    TCG_REG_R8, 0, addr_reg, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
+                    TCG_REG_TMP, 0, addr_reg, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
     tcg_out_dat_imm(s, COND_AL, ARITH_AND,
-                    TCG_REG_R0, TCG_REG_R8, CPU_TLB_SIZE - 1);
+                    TCG_REG_R0, TCG_REG_TMP, CPU_TLB_SIZE - 1);
     tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_R0,
                     TCG_AREG0, TCG_REG_R0, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS));
     /* We assume that the offset is contained within 20 bits.  */
@@ -1419,7 +1421,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
     }
     tcg_out_ld32_12wb(s, COND_AL, TCG_REG_R1, TCG_REG_R0, tlb_offset);
     tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0, TCG_REG_R1,
-                    TCG_REG_R8, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
+                    TCG_REG_TMP, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
     /* Check alignment.  */
     if (s_bits)
         tcg_out_dat_imm(s, COND_EQ, ARITH_TST,
@@ -1698,7 +1700,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         a0 = args[0], a1 = args[1], a2 = args[2];
         a3 = args[3], a4 = args[4], a5 = args[5];
         if (a0 == a3 || (a0 == a5 && !const_args[5])) {
-            a0 = TCG_REG_R8;
+            a0 = TCG_REG_TMP;
         }
         tcg_out_dat_rIN(s, COND_AL, ARITH_ADD | TO_CPSR, ARITH_SUB | TO_CPSR,
                         a0, a2, a4, const_args[4]);
@@ -1710,7 +1712,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         a0 = args[0], a1 = args[1], a2 = args[2];
         a3 = args[3], a4 = args[4], a5 = args[5];
         if ((a0 == a3 && !const_args[3]) || (a0 == a5 && !const_args[5])) {
-            a0 = TCG_REG_R8;
+            a0 = TCG_REG_TMP;
         }
         if (const_args[2]) {
             if (const_args[4]) {
@@ -1778,9 +1780,9 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
                             SHIFT_IMM_ROR((0x20 - args[2]) & 0x1f) :
                             SHIFT_IMM_LSL(0));
         } else {
-            tcg_out_dat_imm(s, COND_AL, ARITH_RSB, TCG_REG_R8, args[1], 0x20);
+            tcg_out_dat_imm(s, COND_AL, ARITH_RSB, TCG_REG_TMP, args[1], 0x20);
             tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1],
-                            SHIFT_REG_ROR(TCG_REG_R8));
+                            SHIFT_REG_ROR(TCG_REG_TMP));
         }
         break;
 
@@ -1885,15 +1887,15 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         tcg_out_udiv(s, COND_AL, args[0], args[1], args[2]);
         break;
     case INDEX_op_rem_i32:
-        tcg_out_sdiv(s, COND_AL, TCG_REG_R8, args[1], args[2]);
-        tcg_out_mul32(s, COND_AL, TCG_REG_R8, TCG_REG_R8, args[2]);
-        tcg_out_dat_reg(s, COND_AL, ARITH_SUB, args[0], args[1], TCG_REG_R8,
+        tcg_out_sdiv(s, COND_AL, TCG_REG_TMP, args[1], args[2]);
+        tcg_out_mul32(s, COND_AL, TCG_REG_TMP, TCG_REG_TMP, args[2]);
+        tcg_out_dat_reg(s, COND_AL, ARITH_SUB, args[0], args[1], TCG_REG_TMP,
                         SHIFT_IMM_LSL(0));
         break;
     case INDEX_op_remu_i32:
-        tcg_out_udiv(s, COND_AL, TCG_REG_R8, args[1], args[2]);
-        tcg_out_mul32(s, COND_AL, TCG_REG_R8, TCG_REG_R8, args[2]);
-        tcg_out_dat_reg(s, COND_AL, ARITH_SUB, args[0], args[1], TCG_REG_R8,
+        tcg_out_udiv(s, COND_AL, TCG_REG_TMP, args[1], args[2]);
+        tcg_out_mul32(s, COND_AL, TCG_REG_TMP, TCG_REG_TMP, args[2]);
+        tcg_out_dat_reg(s, COND_AL, ARITH_SUB, args[0], args[1], TCG_REG_TMP,
                         SHIFT_IMM_LSL(0));
         break;
 
@@ -2012,7 +2014,7 @@ static void tcg_target_init(TCGContext *s)
 
     tcg_regset_clear(s->reserved_regs);
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
-    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R8);
+    tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP);
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_PC);
 
     tcg_add_target_add_op_defs(arm_op_defs);
commit 0637c56c99be1c73f5814c7f02c0735242b757e5
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Mar 11 22:11:30 2013 -0700

    tcg-arm: Implement division instructions
    
    An armv7 extension implements division, present on Cortex A15.
    
    Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/disas/arm.c b/disas/arm.c
index 4927d8a..76e97a8 100644
--- a/disas/arm.c
+++ b/disas/arm.c
@@ -819,6 +819,10 @@ static const struct opcode32 arm_opcodes[] =
   {ARM_EXT_V3M, 0x00800090, 0x0fa000f0, "%22?sumull%20's%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
   {ARM_EXT_V3M, 0x00a00090, 0x0fa000f0, "%22?sumlal%20's%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
 
+  /* IDIV instructions.  */
+  {ARM_EXT_DIV, 0x0710f010, 0x0ff0f0f0, "sdiv%c\t%16-19r, %0-3r, %8-11r"},
+  {ARM_EXT_DIV, 0x0730f010, 0x0ff0f0f0, "udiv%c\t%16-19r, %0-3r, %8-11r"},
+
   /* V7 instructions.  */
   {ARM_EXT_V7, 0xf450f000, 0xfd70f000, "pli\t%P"},
   {ARM_EXT_V7, 0x0320f0f0, 0x0ffffff0, "dbg%c\t#%0-3d"},
diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 09f11e1..b0e73d2 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -597,6 +597,16 @@ static inline void tcg_out_smull32(TCGContext *s,
     }
 }
 
+static inline void tcg_out_sdiv(TCGContext *s, int cond, int rd, int rn, int rm)
+{
+    tcg_out32(s, 0x0710f010 | (cond << 28) | (rd << 16) | rn | (rm << 8));
+}
+
+static inline void tcg_out_udiv(TCGContext *s, int cond, int rd, int rn, int rm)
+{
+    tcg_out32(s, 0x0730f010 | (cond << 28) | (rd << 16) | rn | (rm << 8));
+}
+
 static inline void tcg_out_ext8s(TCGContext *s, int cond,
                                  int rd, int rn)
 {
@@ -1868,6 +1878,25 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
                         args[3], args[4], const_args[2]);
         break;
 
+    case INDEX_op_div_i32:
+        tcg_out_sdiv(s, COND_AL, args[0], args[1], args[2]);
+        break;
+    case INDEX_op_divu_i32:
+        tcg_out_udiv(s, COND_AL, args[0], args[1], args[2]);
+        break;
+    case INDEX_op_rem_i32:
+        tcg_out_sdiv(s, COND_AL, TCG_REG_R8, args[1], args[2]);
+        tcg_out_mul32(s, COND_AL, TCG_REG_R8, TCG_REG_R8, args[2]);
+        tcg_out_dat_reg(s, COND_AL, ARITH_SUB, args[0], args[1], TCG_REG_R8,
+                        SHIFT_IMM_LSL(0));
+        break;
+    case INDEX_op_remu_i32:
+        tcg_out_udiv(s, COND_AL, TCG_REG_R8, args[1], args[2]);
+        tcg_out_mul32(s, COND_AL, TCG_REG_R8, TCG_REG_R8, args[2]);
+        tcg_out_dat_reg(s, COND_AL, ARITH_SUB, args[0], args[1], TCG_REG_R8,
+                        SHIFT_IMM_LSL(0));
+        break;
+
     default:
         tcg_abort();
     }
@@ -1954,6 +1983,13 @@ static const TCGTargetOpDef arm_op_defs[] = {
 
     { INDEX_op_deposit_i32, { "r", "0", "rZ" } },
 
+#if TCG_TARGET_HAS_div_i32
+    { INDEX_op_div_i32, { "r", "r", "r" } },
+    { INDEX_op_rem_i32, { "r", "r", "r" } },
+    { INDEX_op_divu_i32, { "r", "r", "r" } },
+    { INDEX_op_remu_i32, { "r", "r", "r" } },
+#endif
+
     { -1 },
 };
 
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
index 209f585..3be41cc 100644
--- a/tcg/arm/tcg-target.h
+++ b/tcg/arm/tcg-target.h
@@ -56,7 +56,6 @@ typedef enum {
 #define TCG_TARGET_CALL_STACK_OFFSET	0
 
 /* optional instructions */
-#define TCG_TARGET_HAS_div_i32          0
 #define TCG_TARGET_HAS_ext8s_i32        1
 #define TCG_TARGET_HAS_ext16s_i32       1
 #define TCG_TARGET_HAS_ext8u_i32        0 /* and r0, r1, #0xff */
@@ -75,6 +74,12 @@ typedef enum {
 #define TCG_TARGET_HAS_movcond_i32      1
 #define TCG_TARGET_HAS_muls2_i32        1
 
+#ifdef __ARM_ARCH_EXT_IDIV__
+#define TCG_TARGET_HAS_div_i32          1
+#else
+#define TCG_TARGET_HAS_div_i32          0
+#endif
+
 extern bool tcg_target_deposit_valid(int ofs, int len);
 #define TCG_TARGET_deposit_i32_valid  tcg_target_deposit_valid
 
commit b6b24cb031d1d6e6f50abf0c8bdc1c309e549156
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Mar 4 21:12:30 2013 -0800

    tcg-arm: Implement deposit for armv7
    
    We have BFI and BFC available for implementing it.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index dfcc8e6..09f11e1 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -145,9 +145,10 @@ static void patch_reloc(uint8_t *code_ptr, int type,
     }
 }
 
-#define TCG_CT_CONST_ARM 0x100
-#define TCG_CT_CONST_INV 0x200
-#define TCG_CT_CONST_NEG 0x400
+#define TCG_CT_CONST_ARM  0x100
+#define TCG_CT_CONST_INV  0x200
+#define TCG_CT_CONST_NEG  0x400
+#define TCG_CT_CONST_ZERO 0x800
 
 /* parse target specific constraints */
 static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
@@ -165,6 +166,9 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
     case 'N': /* The gcc constraint letter is L, already used here.  */
         ct->ct |= TCG_CT_CONST_NEG;
         break;
+    case 'Z':
+        ct->ct |= TCG_CT_CONST_ZERO;
+        break;
 
     case 'r':
         ct->ct |= TCG_CT_REG;
@@ -297,6 +301,8 @@ static inline int tcg_target_const_match(tcg_target_long val,
         return 1;
     } else if ((ct & TCG_CT_CONST_NEG) && check_fit_imm(-val)) {
         return 1;
+    } else if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
+        return 1;
     } else {
         return 0;
     }
@@ -702,6 +708,28 @@ static inline void tcg_out_bswap32(TCGContext *s, int cond, int rd, int rn)
     }
 }
 
+bool tcg_target_deposit_valid(int ofs, int len)
+{
+    /* ??? Without bfi, we could improve over generic code by combining
+       the right-shift from a non-zero ofs with the orr.  We do run into
+       problems when rd == rs, and the mask generated from ofs+len doesn't
+       fit into an immediate.  We would have to be careful not to pessimize
+       wrt the optimizations performed on the expanded code.  */
+    return use_armv7_instructions;
+}
+
+static inline void tcg_out_deposit(TCGContext *s, int cond, TCGReg rd,
+                                   TCGArg a1, int ofs, int len, bool const_a1)
+{
+    if (const_a1) {
+        /* bfi becomes bfc with rn == 15.  */
+        a1 = 15;
+    }
+    /* bfi/bfc */
+    tcg_out32(s, 0x07c00010 | (cond << 28) | (rd << 12) | a1
+              | (ofs << 7) | ((ofs + len - 1) << 16));
+}
+
 static inline void tcg_out_ld32_12(TCGContext *s, int cond,
                 int rd, int rn, tcg_target_long im)
 {
@@ -1835,6 +1863,11 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         tcg_out_ext16u(s, COND_AL, args[0], args[1]);
         break;
 
+    case INDEX_op_deposit_i32:
+        tcg_out_deposit(s, COND_AL, args[0], args[2],
+                        args[3], args[4], const_args[2]);
+        break;
+
     default:
         tcg_abort();
     }
@@ -1919,6 +1952,8 @@ static const TCGTargetOpDef arm_op_defs[] = {
     { INDEX_op_ext16s_i32, { "r", "r" } },
     { INDEX_op_ext16u_i32, { "r", "r" } },
 
+    { INDEX_op_deposit_i32, { "r", "0", "rZ" } },
+
     { -1 },
 };
 
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
index 354dd8a..209f585 100644
--- a/tcg/arm/tcg-target.h
+++ b/tcg/arm/tcg-target.h
@@ -71,10 +71,13 @@ typedef enum {
 #define TCG_TARGET_HAS_eqv_i32          0
 #define TCG_TARGET_HAS_nand_i32         0
 #define TCG_TARGET_HAS_nor_i32          0
-#define TCG_TARGET_HAS_deposit_i32      0
+#define TCG_TARGET_HAS_deposit_i32      1
 #define TCG_TARGET_HAS_movcond_i32      1
 #define TCG_TARGET_HAS_muls2_i32        1
 
+extern bool tcg_target_deposit_valid(int ofs, int len);
+#define TCG_TARGET_deposit_i32_valid  tcg_target_deposit_valid
+
 enum {
     TCG_AREG0 = TCG_REG_R6,
 };
commit e86e0f2807fbadee09d9e06f11df69339cbbd94c
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Mar 4 23:16:24 2013 -0800

    tcg-arm: Improve constant generation
    
    Try fully rotated arguments to mov and mvn before trying movt
    or full decomposition.  Begin decomposition with mvn when it
    looks like it'll help.  Examples include
    
    -:        mov   r9, #0x00000fa0
    -:        orr   r9, r9, #0x000ee000
    -:        orr   r9, r9, #0x0ff00000
    -:        orr   r9, r9, #0xf0000000
    +:        mvn   r9, #0x0000005f
    +:        eor   r9, r9, #0x00011000
    
    Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 1a236c2..dfcc8e6 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -427,15 +427,31 @@ static inline void tcg_out_dat_imm(TCGContext *s,
                     (rn << 16) | (rd << 12) | im);
 }
 
-static inline void tcg_out_movi32(TCGContext *s,
-                int cond, int rd, uint32_t arg)
-{
-    /* TODO: This is very suboptimal, we can easily have a constant
-     * pool somewhere after all the instructions.  */
-    if ((int)arg < 0 && (int)arg >= -0x100) {
-        tcg_out_dat_imm(s, cond, ARITH_MVN, rd, 0, (~arg) & 0xff);
-    } else if (use_armv7_instructions) {
-        /* use movw/movt */
+static void tcg_out_movi32(TCGContext *s, int cond, int rd, uint32_t arg)
+{
+    int rot, opc, rn;
+
+    /* For armv7, make sure not to use movw+movt when mov/mvn would do.
+       Speed things up by only checking when movt would be required.
+       Prior to armv7, have one go at fully rotated immediates before
+       doing the decomposition thing below.  */
+    if (!use_armv7_instructions || (arg & 0xffff0000)) {
+        rot = encode_imm(arg);
+        if (rot >= 0) {
+            tcg_out_dat_imm(s, cond, ARITH_MOV, rd, 0,
+                            rotl(arg, rot) | (rot << 7));
+            return;
+        }
+        rot = encode_imm(~arg);
+        if (rot >= 0) {
+            tcg_out_dat_imm(s, cond, ARITH_MVN, rd, 0,
+                            rotl(~arg, rot) | (rot << 7));
+            return;
+        }
+    }
+
+    /* Use movw + movt.  */
+    if (use_armv7_instructions) {
         /* movw */
         tcg_out32(s, (cond << 28) | 0x03000000 | (rd << 12)
                   | ((arg << 4) & 0x000f0000) | (arg & 0xfff));
@@ -444,22 +460,27 @@ static inline void tcg_out_movi32(TCGContext *s,
             tcg_out32(s, (cond << 28) | 0x03400000 | (rd << 12)
                       | ((arg >> 12) & 0x000f0000) | ((arg >> 16) & 0xfff));
         }
-    } else {
-        int opc = ARITH_MOV;
-        int rn = 0;
-
-        do {
-            int i, rot;
-
-            i = ctz32(arg) & ~1;
-            rot = ((32 - i) << 7) & 0xf00;
-            tcg_out_dat_imm(s, cond, opc, rd, rn, ((arg >> i) & 0xff) | rot);
-            arg &= ~(0xff << i);
+        return;
+    }
 
-            opc = ARITH_ORR;
-            rn = rd;
-        } while (arg);
+    /* TODO: This is very suboptimal, we can easily have a constant
+       pool somewhere after all the instructions.  */
+    opc = ARITH_MOV;
+    rn = 0;
+    /* If we have lots of leading 1's, we can shorten the sequence by
+       beginning with mvn and then clearing higher bits with eor.  */
+    if (clz32(~arg) > clz32(arg)) {
+        opc = ARITH_MVN, arg = ~arg;
     }
+    do {
+        int i = ctz32(arg) & ~1;
+        rot = ((32 - i) << 7) & 0xf00;
+        tcg_out_dat_imm(s, cond, opc, rd, rn, ((arg >> i) & 0xff) | rot);
+        arg &= ~(0xff << i);
+
+        opc = ARITH_EOR;
+        rn = rd;
+    } while (arg);
 }
 
 static inline void tcg_out_dat_rI(TCGContext *s, int cond, int opc, TCGArg dst,
commit 2df3f1ee68269d40f5dcb5e8d9aba0869e150896
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Mar 11 19:51:56 2013 -0700

    tcg-arm: Handle constant arguments to add2/sub2
    
    We get to re-use the _rIN and _rIK subroutines to handle the various
    combinations of add vs sub.  Fold the << 21 into the opcode enum values
    so that we can explicitly add TO_CPSR as desired.
    
    Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 961b02c..1a236c2 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -302,27 +302,26 @@ static inline int tcg_target_const_match(tcg_target_long val,
     }
 }
 
+#define TO_CPSR (1 << 20)
+
 enum arm_data_opc_e {
-    ARITH_AND = 0x0,
-    ARITH_EOR = 0x1,
-    ARITH_SUB = 0x2,
-    ARITH_RSB = 0x3,
-    ARITH_ADD = 0x4,
-    ARITH_ADC = 0x5,
-    ARITH_SBC = 0x6,
-    ARITH_RSC = 0x7,
-    ARITH_TST = 0x8,
-    ARITH_CMP = 0xa,
-    ARITH_CMN = 0xb,
-    ARITH_ORR = 0xc,
-    ARITH_MOV = 0xd,
-    ARITH_BIC = 0xe,
-    ARITH_MVN = 0xf,
+    ARITH_AND = 0x0 << 21,
+    ARITH_EOR = 0x1 << 21,
+    ARITH_SUB = 0x2 << 21,
+    ARITH_RSB = 0x3 << 21,
+    ARITH_ADD = 0x4 << 21,
+    ARITH_ADC = 0x5 << 21,
+    ARITH_SBC = 0x6 << 21,
+    ARITH_RSC = 0x7 << 21,
+    ARITH_TST = 0x8 << 21 | TO_CPSR,
+    ARITH_CMP = 0xa << 21 | TO_CPSR,
+    ARITH_CMN = 0xb << 21 | TO_CPSR,
+    ARITH_ORR = 0xc << 21,
+    ARITH_MOV = 0xd << 21,
+    ARITH_BIC = 0xe << 21,
+    ARITH_MVN = 0xf << 21,
 };
 
-#define TO_CPSR(opc) \
-  ((opc == ARITH_CMP || opc == ARITH_CMN || opc == ARITH_TST) << 20)
-
 #define SHIFT_IMM_LSL(im)	(((im) << 7) | 0x00)
 #define SHIFT_IMM_LSR(im)	(((im) << 7) | 0x20)
 #define SHIFT_IMM_ASR(im)	(((im) << 7) | 0x40)
@@ -409,7 +408,7 @@ static inline void tcg_out_blx_imm(TCGContext *s, int32_t offset)
 static inline void tcg_out_dat_reg(TCGContext *s,
                 int cond, int opc, int rd, int rn, int rm, int shift)
 {
-    tcg_out32(s, (cond << 28) | (0 << 25) | (opc << 21) | TO_CPSR(opc) |
+    tcg_out32(s, (cond << 28) | (0 << 25) | opc |
                     (rn << 16) | (rd << 12) | shift | rm);
 }
 
@@ -421,29 +420,10 @@ static inline void tcg_out_mov_reg(TCGContext *s, int cond, int rd, int rm)
     }
 }
 
-static inline void tcg_out_dat_reg2(TCGContext *s,
-                int cond, int opc0, int opc1, int rd0, int rd1,
-                int rn0, int rn1, int rm0, int rm1, int shift)
-{
-    if (rd0 == rn1 || rd0 == rm1) {
-        tcg_out32(s, (cond << 28) | (0 << 25) | (opc0 << 21) | (1 << 20) |
-                        (rn0 << 16) | (8 << 12) | shift | rm0);
-        tcg_out32(s, (cond << 28) | (0 << 25) | (opc1 << 21) |
-                        (rn1 << 16) | (rd1 << 12) | shift | rm1);
-        tcg_out_dat_reg(s, cond, ARITH_MOV,
-                        rd0, 0, TCG_REG_R8, SHIFT_IMM_LSL(0));
-    } else {
-        tcg_out32(s, (cond << 28) | (0 << 25) | (opc0 << 21) | (1 << 20) |
-                        (rn0 << 16) | (rd0 << 12) | shift | rm0);
-        tcg_out32(s, (cond << 28) | (0 << 25) | (opc1 << 21) |
-                        (rn1 << 16) | (rd1 << 12) | shift | rm1);
-    }
-}
-
 static inline void tcg_out_dat_imm(TCGContext *s,
                 int cond, int opc, int rd, int rn, int im)
 {
-    tcg_out32(s, (cond << 28) | (1 << 25) | (opc << 21) | TO_CPSR(opc) |
+    tcg_out32(s, (cond << 28) | (1 << 25) | opc |
                     (rn << 16) | (rd << 12) | im);
 }
 
@@ -1523,6 +1503,7 @@ static uint8_t *tb_ret_addr;
 static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
                 const TCGArg *args, const int *const_args)
 {
+    TCGArg a0, a1, a2, a3, a4, a5;
     int c;
 
     switch (opc) {
@@ -1655,14 +1636,44 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         tcg_out_dat_rI(s, COND_AL, c, args[0], args[1], args[2], const_args[2]);
         break;
     case INDEX_op_add2_i32:
-        tcg_out_dat_reg2(s, COND_AL, ARITH_ADD, ARITH_ADC,
-                        args[0], args[1], args[2], args[3],
-                        args[4], args[5], SHIFT_IMM_LSL(0));
+        a0 = args[0], a1 = args[1], a2 = args[2];
+        a3 = args[3], a4 = args[4], a5 = args[5];
+        if (a0 == a3 || (a0 == a5 && !const_args[5])) {
+            a0 = TCG_REG_R8;
+        }
+        tcg_out_dat_rIN(s, COND_AL, ARITH_ADD | TO_CPSR, ARITH_SUB | TO_CPSR,
+                        a0, a2, a4, const_args[4]);
+        tcg_out_dat_rIK(s, COND_AL, ARITH_ADC, ARITH_SBC,
+                        a1, a3, a5, const_args[5]);
+        tcg_out_mov_reg(s, COND_AL, args[0], a0);
         break;
     case INDEX_op_sub2_i32:
-        tcg_out_dat_reg2(s, COND_AL, ARITH_SUB, ARITH_SBC,
-                        args[0], args[1], args[2], args[3],
-                        args[4], args[5], SHIFT_IMM_LSL(0));
+        a0 = args[0], a1 = args[1], a2 = args[2];
+        a3 = args[3], a4 = args[4], a5 = args[5];
+        if ((a0 == a3 && !const_args[3]) || (a0 == a5 && !const_args[5])) {
+            a0 = TCG_REG_R8;
+        }
+        if (const_args[2]) {
+            if (const_args[4]) {
+                tcg_out_movi32(s, COND_AL, a0, a4);
+                a4 = a0;
+            }
+            tcg_out_dat_rI(s, COND_AL, ARITH_RSB | TO_CPSR, a0, a4, a2, 1);
+        } else {
+            tcg_out_dat_rIN(s, COND_AL, ARITH_SUB | TO_CPSR,
+                            ARITH_ADD | TO_CPSR, a0, a2, a4, const_args[4]);
+        }
+        if (const_args[3]) {
+            if (const_args[5]) {
+                tcg_out_movi32(s, COND_AL, a1, a5);
+                a5 = a1;
+            }
+            tcg_out_dat_rI(s, COND_AL, ARITH_RSC, a1, a5, a3, 1);
+        } else {
+            tcg_out_dat_rIK(s, COND_AL, ARITH_SBC, ARITH_ADC,
+                            a1, a3, a5, const_args[5]);
+        }
+        tcg_out_mov_reg(s, COND_AL, args[0], a0);
         break;
     case INDEX_op_neg_i32:
         tcg_out_dat_imm(s, COND_AL, ARITH_RSB, args[0], args[1], 0);
@@ -1849,9 +1860,8 @@ static const TCGTargetOpDef arm_op_defs[] = {
     { INDEX_op_setcond_i32, { "r", "r", "rIN" } },
     { INDEX_op_movcond_i32, { "r", "r", "rIN", "rIK", "0" } },
 
-    /* TODO: "r", "r", "r", "r", "ri", "ri" */
-    { INDEX_op_add2_i32, { "r", "r", "r", "r", "r", "r" } },
-    { INDEX_op_sub2_i32, { "r", "r", "r", "r", "r", "r" } },
+    { INDEX_op_add2_i32, { "r", "r", "r", "r", "rIN", "rIK" } },
+    { INDEX_op_sub2_i32, { "r", "r", "rI", "rI", "rIN", "rIK" } },
     { INDEX_op_brcond2_i32, { "r", "r", "rIN", "rIN" } },
     { INDEX_op_setcond2_i32, { "r", "r", "r", "rIN", "rIN" } },
 
commit 5d53b4c93caf16531e65a95a9b5c93228fe48f8b
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Mar 11 18:21:59 2013 -0700

    tcg-arm: Use tcg_out_dat_rIN for compares
    
    This allows us to emit CMN instructions.
    
    Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 6c7113b..961b02c 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -1615,10 +1615,10 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         /* Constraints mean that v2 is always in the same register as dest,
          * so we only need to do "if condition passed, move v1 to dest".
          */
-        tcg_out_dat_rI(s, COND_AL, ARITH_CMP, 0,
-                       args[1], args[2], const_args[2]);
-        tcg_out_dat_rI(s, tcg_cond_to_arm_cond[args[5]],
-                       ARITH_MOV, args[0], 0, args[3], const_args[3]);
+        tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
+                        args[1], args[2], const_args[2]);
+        tcg_out_dat_rIK(s, tcg_cond_to_arm_cond[args[5]], ARITH_MOV,
+                        ARITH_MVN, args[0], 0, args[3], const_args[3]);
         break;
     case INDEX_op_add_i32:
         tcg_out_dat_rIN(s, COND_AL, ARITH_ADD, ARITH_SUB,
@@ -1715,7 +1715,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         break;
 
     case INDEX_op_brcond_i32:
-        tcg_out_dat_rI(s, COND_AL, ARITH_CMP, 0,
+        tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
                        args[0], args[1], const_args[1]);
         tcg_out_goto_label(s, tcg_cond_to_arm_cond[args[2]], args[3]);
         break;
@@ -1728,15 +1728,15 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
          * TCG_COND_LE(U) --> (a0 <= a2 && a1 == a3) || (a1 <= a3 && a1 != a3),
          * TCG_COND_GT(U) --> (a0 >  a2 && a1 == a3) ||  a1 >  a3,
          */
-        tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0,
-                        args[1], args[3], SHIFT_IMM_LSL(0));
-        tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
-                        args[0], args[2], SHIFT_IMM_LSL(0));
+        tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
+                        args[1], args[3], const_args[3]);
+        tcg_out_dat_rIN(s, COND_EQ, ARITH_CMP, ARITH_CMN, 0,
+                        args[0], args[2], const_args[2]);
         tcg_out_goto_label(s, tcg_cond_to_arm_cond[args[4]], args[5]);
         break;
     case INDEX_op_setcond_i32:
-        tcg_out_dat_rI(s, COND_AL, ARITH_CMP, 0,
-                       args[1], args[2], const_args[2]);
+        tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
+                        args[1], args[2], const_args[2]);
         tcg_out_dat_imm(s, tcg_cond_to_arm_cond[args[3]],
                         ARITH_MOV, args[0], 0, 1);
         tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(args[3])],
@@ -1744,10 +1744,10 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         break;
     case INDEX_op_setcond2_i32:
         /* See brcond2_i32 comment */
-        tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0,
-                        args[2], args[4], SHIFT_IMM_LSL(0));
-        tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
-                        args[1], args[3], SHIFT_IMM_LSL(0));
+        tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
+                        args[2], args[4], const_args[4]);
+        tcg_out_dat_rIN(s, COND_EQ, ARITH_CMP, ARITH_CMN, 0,
+                        args[1], args[3], const_args[3]);
         tcg_out_dat_imm(s, tcg_cond_to_arm_cond[args[5]],
                         ARITH_MOV, args[0], 0, 1);
         tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(args[5])],
@@ -1845,15 +1845,15 @@ static const TCGTargetOpDef arm_op_defs[] = {
     { INDEX_op_rotl_i32, { "r", "r", "ri" } },
     { INDEX_op_rotr_i32, { "r", "r", "ri" } },
 
-    { INDEX_op_brcond_i32, { "r", "rI" } },
-    { INDEX_op_setcond_i32, { "r", "r", "rI" } },
-    { INDEX_op_movcond_i32, { "r", "r", "rI", "rI", "0" } },
+    { INDEX_op_brcond_i32, { "r", "rIN" } },
+    { INDEX_op_setcond_i32, { "r", "r", "rIN" } },
+    { INDEX_op_movcond_i32, { "r", "r", "rIN", "rIK", "0" } },
 
     /* TODO: "r", "r", "r", "r", "ri", "ri" */
     { INDEX_op_add2_i32, { "r", "r", "r", "r", "r", "r" } },
     { INDEX_op_sub2_i32, { "r", "r", "r", "r", "r", "r" } },
-    { INDEX_op_brcond2_i32, { "r", "r", "r", "r" } },
-    { INDEX_op_setcond2_i32, { "r", "r", "r", "r", "r" } },
+    { INDEX_op_brcond2_i32, { "r", "r", "rIN", "rIN" } },
+    { INDEX_op_setcond2_i32, { "r", "r", "r", "rIN", "rIN" } },
 
 #if TARGET_LONG_BITS == 32
     { INDEX_op_qemu_ld8u, { "r", "l" } },
commit d9fda57549877045aa0ec91d2a067a67cb41a29f
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Mar 11 18:04:14 2013 -0700

    tcg-arm: Allow constant first argument to sub
    
    This allows the generation of RSB instructions.
    
    Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index de8465b..6c7113b 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -1625,8 +1625,17 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
                         args[0], args[1], args[2], const_args[2]);
         break;
     case INDEX_op_sub_i32:
-        tcg_out_dat_rIN(s, COND_AL, ARITH_SUB, ARITH_ADD,
-                        args[0], args[1], args[2], const_args[2]);
+        if (const_args[1]) {
+            if (const_args[2]) {
+                tcg_out_movi32(s, COND_AL, args[0], args[1] - args[2]);
+            } else {
+                tcg_out_dat_rI(s, COND_AL, ARITH_RSB,
+                               args[0], args[2], args[1], 1);
+            }
+        } else {
+            tcg_out_dat_rIN(s, COND_AL, ARITH_SUB, ARITH_ADD,
+                            args[0], args[1], args[2], const_args[2]);
+        }
         break;
     case INDEX_op_and_i32:
         tcg_out_dat_rIK(s, COND_AL, ARITH_AND, ARITH_BIC,
@@ -1819,7 +1828,7 @@ static const TCGTargetOpDef arm_op_defs[] = {
 
     /* TODO: "r", "r", "ri" */
     { INDEX_op_add_i32, { "r", "r", "rIN" } },
-    { INDEX_op_sub_i32, { "r", "r", "rIN" } },
+    { INDEX_op_sub_i32, { "r", "rI", "rIN" } },
     { INDEX_op_mul_i32, { "r", "r", "r" } },
     { INDEX_op_mulu2_i32, { "r", "r", "r", "r" } },
     { INDEX_op_muls2_i32, { "r", "r", "r", "r" } },
commit a9a86ae95d24c587285856405dffc9cacdf2b683
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Mar 4 22:06:21 2013 -0800

    tcg-arm: Handle negated constant arguments to and/sub
    
    This greatly improves code generation for addition of small
    negative constants.
    
    Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 886252f..de8465b 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -147,6 +147,7 @@ static void patch_reloc(uint8_t *code_ptr, int type,
 
 #define TCG_CT_CONST_ARM 0x100
 #define TCG_CT_CONST_INV 0x200
+#define TCG_CT_CONST_NEG 0x400
 
 /* parse target specific constraints */
 static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
@@ -161,6 +162,9 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
     case 'K':
         ct->ct |= TCG_CT_CONST_INV;
         break;
+    case 'N': /* The gcc constraint letter is L, already used here.  */
+        ct->ct |= TCG_CT_CONST_NEG;
+        break;
 
     case 'r':
         ct->ct |= TCG_CT_REG;
@@ -291,6 +295,8 @@ static inline int tcg_target_const_match(tcg_target_long val,
         return 1;
     } else if ((ct & TCG_CT_CONST_INV) && check_fit_imm(~val)) {
         return 1;
+    } else if ((ct & TCG_CT_CONST_NEG) && check_fit_imm(-val)) {
+        return 1;
     } else {
         return 0;
     }
@@ -512,6 +518,27 @@ static void tcg_out_dat_rIK(TCGContext *s, int cond, int opc, int opinv,
     }
 }
 
+static void tcg_out_dat_rIN(TCGContext *s, int cond, int opc, int opneg,
+                            TCGArg dst, TCGArg lhs, TCGArg rhs,
+                            bool rhs_is_const)
+{
+    /* Emit either the reg,imm or reg,reg form of a data-processing insn.
+     * rhs must satisfy the "rIN" constraint.
+     */
+    if (rhs_is_const) {
+        int rot = encode_imm(rhs);
+        if (rot < 0) {
+            rhs = -rhs;
+            rot = encode_imm(rhs);
+            assert(rot >= 0);
+            opc = opneg;
+        }
+        tcg_out_dat_imm(s, cond, opc, dst, lhs, rotl(rhs, rot) | (rot << 7));
+    } else {
+        tcg_out_dat_reg(s, cond, opc, dst, lhs, rhs, SHIFT_IMM_LSL(0));
+    }
+}
+
 static inline void tcg_out_mul32(TCGContext *s,
                 int cond, int rd, int rs, int rm)
 {
@@ -1594,11 +1621,13 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
                        ARITH_MOV, args[0], 0, args[3], const_args[3]);
         break;
     case INDEX_op_add_i32:
-        c = ARITH_ADD;
-        goto gen_arith;
+        tcg_out_dat_rIN(s, COND_AL, ARITH_ADD, ARITH_SUB,
+                        args[0], args[1], args[2], const_args[2]);
+        break;
     case INDEX_op_sub_i32:
-        c = ARITH_SUB;
-        goto gen_arith;
+        tcg_out_dat_rIN(s, COND_AL, ARITH_SUB, ARITH_ADD,
+                        args[0], args[1], args[2], const_args[2]);
+        break;
     case INDEX_op_and_i32:
         tcg_out_dat_rIK(s, COND_AL, ARITH_AND, ARITH_BIC,
                         args[0], args[1], args[2], const_args[2]);
@@ -1789,8 +1818,8 @@ static const TCGTargetOpDef arm_op_defs[] = {
     { INDEX_op_st_i32, { "r", "r" } },
 
     /* TODO: "r", "r", "ri" */
-    { INDEX_op_add_i32, { "r", "r", "rI" } },
-    { INDEX_op_sub_i32, { "r", "r", "rI" } },
+    { INDEX_op_add_i32, { "r", "r", "rIN" } },
+    { INDEX_op_sub_i32, { "r", "r", "rIN" } },
     { INDEX_op_mul_i32, { "r", "r", "r" } },
     { INDEX_op_mulu2_i32, { "r", "r", "r", "r" } },
     { INDEX_op_muls2_i32, { "r", "r", "r", "r" } },
commit 19b62bf4148d834c709c464f6fb1c6b72f906250
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Mar 4 21:36:45 2013 -0800

    tcg-arm: Use bic to implement and with constant
    
    This greatly improves the code we can produce for deposit
    without armv7 support.
    
    Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index eda6749..886252f 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -145,6 +145,9 @@ static void patch_reloc(uint8_t *code_ptr, int type,
     }
 }
 
+#define TCG_CT_CONST_ARM 0x100
+#define TCG_CT_CONST_INV 0x200
+
 /* parse target specific constraints */
 static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
 {
@@ -153,8 +156,11 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
     ct_str = *pct_str;
     switch (ct_str[0]) {
     case 'I':
-         ct->ct |= TCG_CT_CONST_ARM;
-         break;
+        ct->ct |= TCG_CT_CONST_ARM;
+        break;
+    case 'K':
+        ct->ct |= TCG_CT_CONST_INV;
+        break;
 
     case 'r':
         ct->ct |= TCG_CT_REG;
@@ -275,16 +281,19 @@ static inline int check_fit_imm(uint32_t imm)
  * add, sub, eor...: ditto
  */
 static inline int tcg_target_const_match(tcg_target_long val,
-                const TCGArgConstraint *arg_ct)
+                                         const TCGArgConstraint *arg_ct)
 {
     int ct;
     ct = arg_ct->ct;
-    if (ct & TCG_CT_CONST)
+    if (ct & TCG_CT_CONST) {
         return 1;
-    else if ((ct & TCG_CT_CONST_ARM) && check_fit_imm(val))
+    } else if ((ct & TCG_CT_CONST_ARM) && check_fit_imm(val)) {
         return 1;
-    else
+    } else if ((ct & TCG_CT_CONST_INV) && check_fit_imm(~val)) {
+        return 1;
+    } else {
         return 0;
+    }
 }
 
 enum arm_data_opc_e {
@@ -482,6 +491,27 @@ static inline void tcg_out_dat_rI(TCGContext *s, int cond, int opc, TCGArg dst,
     }
 }
 
+static void tcg_out_dat_rIK(TCGContext *s, int cond, int opc, int opinv,
+                            TCGReg dst, TCGReg lhs, TCGArg rhs,
+                            bool rhs_is_const)
+{
+    /* Emit either the reg,imm or reg,reg form of a data-processing insn.
+     * rhs must satisfy the "rIK" constraint.
+     */
+    if (rhs_is_const) {
+        int rot = encode_imm(rhs);
+        if (rot < 0) {
+            rhs = ~rhs;
+            rot = encode_imm(rhs);
+            assert(rot >= 0);
+            opc = opinv;
+        }
+        tcg_out_dat_imm(s, cond, opc, dst, lhs, rotl(rhs, rot) | (rot << 7));
+    } else {
+        tcg_out_dat_reg(s, cond, opc, dst, lhs, rhs, SHIFT_IMM_LSL(0));
+    }
+}
+
 static inline void tcg_out_mul32(TCGContext *s,
                 int cond, int rd, int rs, int rm)
 {
@@ -1570,11 +1600,13 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         c = ARITH_SUB;
         goto gen_arith;
     case INDEX_op_and_i32:
-        c = ARITH_AND;
-        goto gen_arith;
+        tcg_out_dat_rIK(s, COND_AL, ARITH_AND, ARITH_BIC,
+                        args[0], args[1], args[2], const_args[2]);
+        break;
     case INDEX_op_andc_i32:
-        c = ARITH_BIC;
-        goto gen_arith;
+        tcg_out_dat_rIK(s, COND_AL, ARITH_BIC, ARITH_AND,
+                        args[0], args[1], args[2], const_args[2]);
+        break;
     case INDEX_op_or_i32:
         c = ARITH_ORR;
         goto gen_arith;
@@ -1762,8 +1794,8 @@ static const TCGTargetOpDef arm_op_defs[] = {
     { INDEX_op_mul_i32, { "r", "r", "r" } },
     { INDEX_op_mulu2_i32, { "r", "r", "r", "r" } },
     { INDEX_op_muls2_i32, { "r", "r", "r", "r" } },
-    { INDEX_op_and_i32, { "r", "r", "rI" } },
-    { INDEX_op_andc_i32, { "r", "r", "rI" } },
+    { INDEX_op_and_i32, { "r", "r", "rIK" } },
+    { INDEX_op_andc_i32, { "r", "r", "rIK" } },
     { INDEX_op_or_i32, { "r", "r", "rI" } },
     { INDEX_op_xor_i32, { "r", "r", "rI" } },
     { INDEX_op_neg_i32, { "r", "r" } },
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
index b6eed1f..354dd8a 100644
--- a/tcg/arm/tcg-target.h
+++ b/tcg/arm/tcg-target.h
@@ -49,8 +49,6 @@ typedef enum {
 
 #define TCG_TARGET_NB_REGS 16
 
-#define TCG_CT_CONST_ARM 0x100
-
 /* used for function call generation */
 #define TCG_REG_CALL_STACK		TCG_REG_R13
 #define TCG_TARGET_STACK_ALIGN		8
commit d6b64b2b606fe0fe5f2208e84ff7a28445de666a
Author: Richard Henderson <rth at twiddle.net>
Date:   Sun Mar 31 13:15:19 2013 -0700

    tcg: Log the contents of the prologue with -d out_asm
    
    This makes it easier to verify changes to the code
    generating the prologue.
    
    [Aurelien: change the format from %i to %zu]
    
    Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/tcg.c b/tcg/tcg.c
index 1d8265e..1d8099c 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -268,6 +268,16 @@ void tcg_prologue_init(TCGContext *s)
     tcg_target_qemu_prologue(s);
     flush_icache_range((tcg_target_ulong)s->code_buf,
                        (tcg_target_ulong)s->code_ptr);
+
+#ifdef DEBUG_DISAS
+    if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) {
+        size_t size = s->code_ptr - s->code_buf;
+        qemu_log("PROLOGUE: [size=%zu]\n", size);
+        log_disas(s->code_buf, size);
+        qemu_log("\n");
+        qemu_log_flush();
+    }
+#endif
 }
 
 void tcg_set_frame(TCGContext *s, int reg,
commit ae12e3a643c66575c77211e1226ada041e56b889
Author: Cole Robinson <crobinso at redhat.com>
Date:   Sun Apr 14 16:06:59 2013 -0400

    ccid: Fix crash when backend isn't specified
    
    Reproducer:
    
    ./x86_64-softmmu/qemu-system-x86_64 -device usb-ccid,id=ccid0 -usb -device ccid-card-emulated -monitor stdio
    
    Signed-off-by: Cole Robinson <crobinso at redhat.com>
    Reviewed-by: Alon Levy <alevy at redhat.com>

diff --git a/hw/usb/ccid-card-emulated.c b/hw/usb/ccid-card-emulated.c
index 094284d..deb6d47 100644
--- a/hw/usb/ccid-card-emulated.c
+++ b/hw/usb/ccid-card-emulated.c
@@ -503,9 +503,15 @@ static int emulated_initfn(CCIDCardState *base)
     if (init_pipe_signaling(card) < 0) {
         return -1;
     }
-    card->backend = parse_enumeration(card->backend_str, backend_enum_table, 0);
+
+    card->backend = 0;
+    if (card->backend_str) {
+        card->backend = parse_enumeration(card->backend_str,
+                                          backend_enum_table, 0);
+    }
+
     if (card->backend == 0) {
-        printf("unknown backend, must be one of:\n");
+        printf("backend must be one of:\n");
         for (ptable = backend_enum_table; ptable->name != NULL; ++ptable) {
             printf("%s\n", ptable->name);
         }
commit fc4d60ee16e9c20404e9970b421ac3e96df4c214
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Mar 12 17:11:40 2013 -0700

    tcg-arm: Fix local stack frame
    
    We were not allocating TCG_STATIC_CALL_ARGS_SIZE, so this meant that
    any helper with more than 4 arguments would clobber the saved regs.
    Realizing that we're supposed to have this memory pre-allocated means
    we can clean up the tcg_out_arg functions, which were trying to do
    more stack allocation.
    
    Allocate stack memory for the TCG temporaries while we're at it.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 94c6ca4..eda6749 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -1017,64 +1017,35 @@ static const void * const qemu_st_helpers[4] = {
  * argreg is where we want to put this argument, arg is the argument itself.
  * Return value is the updated argreg ready for the next call.
  * Note that argreg 0..3 is real registers, 4+ on stack.
- * When we reach the first stacked argument, we allocate space for it
- * and the following stacked arguments using "str r8, [sp, #-0x10]!".
- * Following arguments are filled in with "str r8, [sp, #0xNN]".
- * For more than 4 stacked arguments we'd need to know how much
- * space to allocate when we pushed the first stacked argument.
- * We don't need this, so don't implement it (and will assert if you try it.)
  *
  * We provide routines for arguments which are: immediate, 32 bit
  * value in register, 16 and 8 bit values in register (which must be zero
  * extended before use) and 64 bit value in a lo:hi register pair.
  */
-#define DEFINE_TCG_OUT_ARG(NAME, ARGPARAM)                                 \
-    static TCGReg NAME(TCGContext *s, TCGReg argreg, ARGPARAM)             \
-    {                                                                      \
-        if (argreg < 4) {                                                  \
-            TCG_OUT_ARG_GET_ARG(argreg);                                   \
-        } else if (argreg == 4) {                                          \
-            TCG_OUT_ARG_GET_ARG(TCG_REG_R8);                               \
-            tcg_out32(s, (COND_AL << 28) | 0x052d8010);                    \
-        } else {                                                           \
-            assert(argreg < 8);                                            \
-            TCG_OUT_ARG_GET_ARG(TCG_REG_R8);                               \
-            tcg_out32(s, (COND_AL << 28) | 0x058d8000 | (argreg - 4) * 4); \
-        }                                                                  \
-        return argreg + 1;                                                 \
-    }
-
-#define TCG_OUT_ARG_GET_ARG(A) tcg_out_dat_imm(s, COND_AL, ARITH_MOV, A, 0, arg)
-DEFINE_TCG_OUT_ARG(tcg_out_arg_imm32, uint32_t arg)
-#undef TCG_OUT_ARG_GET_ARG
-#define TCG_OUT_ARG_GET_ARG(A) tcg_out_ext8u(s, COND_AL, A, arg)
-DEFINE_TCG_OUT_ARG(tcg_out_arg_reg8, TCGReg arg)
-#undef TCG_OUT_ARG_GET_ARG
-#define TCG_OUT_ARG_GET_ARG(A) tcg_out_ext16u(s, COND_AL, A, arg)
-DEFINE_TCG_OUT_ARG(tcg_out_arg_reg16, TCGReg arg)
-#undef TCG_OUT_ARG_GET_ARG
-
-/* We don't use the macro for this one to avoid an unnecessary reg-reg
- * move when storing to the stack.
- */
-static TCGReg tcg_out_arg_reg32(TCGContext *s, TCGReg argreg, TCGReg arg)
-{
-    if (argreg < 4) {
-        tcg_out_mov_reg(s, COND_AL, argreg, arg);
-    } else if (argreg == 4) {
-        /* str arg, [sp, #-0x10]! */
-        tcg_out32(s, (COND_AL << 28) | 0x052d0010 | (arg << 12));
-    } else {
-        assert(argreg < 8);
-        /* str arg, [sp, #0xNN] */
-        tcg_out32(s, (COND_AL << 28) | 0x058d0000 |
-                  (arg << 12) | (argreg - 4) * 4);
-    }
-    return argreg + 1;
-}
-
-static inline TCGReg tcg_out_arg_reg64(TCGContext *s, TCGReg argreg,
-                                       TCGReg arglo, TCGReg arghi)
+#define DEFINE_TCG_OUT_ARG(NAME, ARGTYPE, MOV_ARG, EXT_ARG)                \
+static TCGReg NAME(TCGContext *s, TCGReg argreg, ARGTYPE arg)              \
+{                                                                          \
+    if (argreg < 4) {                                                      \
+        MOV_ARG(s, COND_AL, argreg, arg);                                  \
+    } else {                                                               \
+        int ofs = (argreg - 4) * 4;                                        \
+        EXT_ARG;                                                           \
+        assert(ofs + 4 <= TCG_STATIC_CALL_ARGS_SIZE);                      \
+        tcg_out_st32_12(s, COND_AL, arg, TCG_REG_CALL_STACK, ofs);         \
+    }                                                                      \
+    return argreg + 1;                                                     \
+}
+
+DEFINE_TCG_OUT_ARG(tcg_out_arg_imm32, uint32_t, tcg_out_movi32,
+    (tcg_out_movi32(s, COND_AL, TCG_REG_R8, arg), arg = TCG_REG_R8))
+DEFINE_TCG_OUT_ARG(tcg_out_arg_reg8, TCGReg, tcg_out_ext8u,
+    (tcg_out_ext8u(s, COND_AL, TCG_REG_R8, arg), arg = TCG_REG_R8))
+DEFINE_TCG_OUT_ARG(tcg_out_arg_reg16, TCGReg, tcg_out_ext16u,
+    (tcg_out_ext16u(s, COND_AL, TCG_REG_R8, arg), arg = TCG_REG_R8))
+DEFINE_TCG_OUT_ARG(tcg_out_arg_reg32, TCGReg, tcg_out_mov_reg, )
+
+static TCGReg tcg_out_arg_reg64(TCGContext *s, TCGReg argreg,
+                                TCGReg arglo, TCGReg arghi)
 {
     /* 64 bit arguments must go in even/odd register pairs
      * and in 8-aligned stack slots.
@@ -1086,16 +1057,7 @@ static inline TCGReg tcg_out_arg_reg64(TCGContext *s, TCGReg argreg,
     argreg = tcg_out_arg_reg32(s, argreg, arghi);
     return argreg;
 }
-
-static inline void tcg_out_arg_stacktidy(TCGContext *s, TCGReg argreg)
-{
-    /* Output any necessary post-call cleanup of the stack */
-    if (argreg > 4) {
-        tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R13, TCG_REG_R13, 0x10);
-    }
-}
-
-#endif
+#endif /* SOFTMMU */
 
 #define TLB_SHIFT	(CPU_TLB_ENTRY_BITS + CPU_TLB_BITS)
 
@@ -1226,7 +1188,6 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
 #endif
     argreg = tcg_out_arg_imm32(s, argreg, mem_index);
     tcg_out_call(s, (tcg_target_long) qemu_ld_helpers[s_bits]);
-    tcg_out_arg_stacktidy(s, argreg);
 
     switch (opc) {
     case 0 | 4:
@@ -1444,7 +1405,6 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
 
     argreg = tcg_out_arg_imm32(s, argreg, mem_index);
     tcg_out_call(s, (tcg_target_long) qemu_st_helpers[s_bits]);
-    tcg_out_arg_stacktidy(s, argreg);
 
     reloc_pc24(label_ptr, (tcg_target_long)s->code_ptr);
 #else /* !CONFIG_SOFTMMU */
@@ -1884,8 +1844,6 @@ static void tcg_target_init(TCGContext *s)
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_PC);
 
     tcg_add_target_add_op_defs(arm_op_defs);
-    tcg_set_frame(s, TCG_AREG0, offsetof(CPUArchState, temp_buf),
-                  CPU_TEMP_BUF_NLONGS * sizeof(long));
 }
 
 static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
@@ -1914,18 +1872,33 @@ static inline void tcg_out_movi(TCGContext *s, TCGType type,
 
 static void tcg_target_qemu_prologue(TCGContext *s)
 {
-    /* Calling convention requires us to save r4-r11 and lr;
-     * save also r12 to maintain stack 8-alignment.
-     */
+    int frame_size;
+
+    /* Calling convention requires us to save r4-r11 and lr.  */
+    /* stmdb sp!, { r4 - r11, lr } */
+    tcg_out32(s, (COND_AL << 28) | 0x092d4ff0);
 
-    /* stmdb sp!, { r4 - r12, lr } */
-    tcg_out32(s, (COND_AL << 28) | 0x092d5ff0);
+    /* Allocate the local stack frame.  */
+    frame_size = TCG_STATIC_CALL_ARGS_SIZE;
+    frame_size += CPU_TEMP_BUF_NLONGS * sizeof(long);
+    /* We saved an odd number of registers above; keep an 8 aligned stack.  */
+    frame_size = ((frame_size + TCG_TARGET_STACK_ALIGN - 1)
+                  & -TCG_TARGET_STACK_ALIGN) + 4;
+
+    tcg_out_dat_rI(s, COND_AL, ARITH_SUB, TCG_REG_CALL_STACK,
+                   TCG_REG_CALL_STACK, frame_size, 1);
+    tcg_set_frame(s, TCG_REG_CALL_STACK, TCG_STATIC_CALL_ARGS_SIZE,
+                  CPU_TEMP_BUF_NLONGS * sizeof(long));
 
     tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
 
     tcg_out_bx(s, COND_AL, tcg_target_call_iarg_regs[1]);
     tb_ret_addr = s->code_ptr;
 
-    /* ldmia sp!, { r4 - r12, pc } */
-    tcg_out32(s, (COND_AL << 28) | 0x08bd9ff0);
+    /* Epilogue.  We branch here via tb_ret_addr.  */
+    tcg_out_dat_rI(s, COND_AL, ARITH_ADD, TCG_REG_CALL_STACK,
+                   TCG_REG_CALL_STACK, frame_size, 1);
+
+    /* ldmia sp!, { r4 - r11, pc } */
+    tcg_out32(s, (COND_AL << 28) | 0x08bd8ff0);
 }
commit ed605126a8d826e60587cc21d9e7b95e8c49b6f6
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Sun Apr 21 00:42:56 2013 +0200

    tcg: fix deposit_i64 op on 32-bit targets
    
    On 32-bit TCG targets, when emulating deposit_i64 with a mov_i32 +
    deposit_i32, care should be taken to not overwrite the low part of
    the second argument before the deposit when it is the same the
    destination.
    
    This fixes the shld instruction in qemu-system-x86_64, which in turns
    fixes booting "system rescue CD version 2.8.0" on this target.
    
    Reported-by: Michael S. Tsirkin <mst at redhat.com>
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
index d70b2eb..94f6043 100644
--- a/tcg/tcg-op.h
+++ b/tcg/tcg-op.h
@@ -2188,9 +2188,9 @@ static inline void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1,
 
 #if TCG_TARGET_REG_BITS == 32
     if (ofs >= 32) {
-        tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
         tcg_gen_deposit_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1),
                             TCGV_LOW(arg2), ofs - 32, len);
+        tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
         return;
     }
     if (ofs + len <= 32) {
commit 909eedb74f88d1d6d9e6bbdc34875772e7a8a5ab
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Sat Apr 27 00:37:46 2013 +0200

    target-ppc: slightly optimize lfiwax
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 6182bd7..1a84653 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -2551,7 +2551,6 @@ static inline void gen_qemu_ld32u(DisasContext *ctx, TCGv arg1, TCGv arg2)
     }
 }
 
-#if defined(TARGET_PPC64)
 static inline void gen_qemu_ld32s(DisasContext *ctx, TCGv arg1, TCGv arg2)
 {
     if (unlikely(ctx->le_mode)) {
@@ -2561,7 +2560,6 @@ static inline void gen_qemu_ld32s(DisasContext *ctx, TCGv arg1, TCGv arg2)
     } else
         tcg_gen_qemu_ld32s(arg1, arg2, ctx->mem_idx);
 }
-#endif
 
 static inline void gen_qemu_ld64(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
 {
@@ -3379,9 +3377,8 @@ static void gen_lfiwax(DisasContext *ctx)
     EA = tcg_temp_new();
     t0 = tcg_temp_new();
     gen_addr_reg_index(ctx, EA);
-    gen_qemu_ld32u(ctx, t0, EA);
+    gen_qemu_ld32s(ctx, t0, EA);
     tcg_gen_ext_tl_i64(cpu_fpr[rD(ctx->opcode)], t0);
-    tcg_gen_ext32s_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);
     tcg_temp_free(EA);
     tcg_temp_free(t0);
 }
commit 076bfd7c65ce08c18d0c375e3779be25206ee2b7
Merge: 75f6e8b 7d08d85
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Sat Apr 27 00:33:23 2013 +0200

    Merge branch 'ppc-for-upstream' of git://github.com/agraf/qemu
    
    * 'ppc-for-upstream' of git://github.com/agraf/qemu: (30 commits)
      target-ppc: add support for extended mtfsf/mtfsfi forms
      target-ppc: emulate store doubleword pair instructions
      target-ppc: emulate load doubleword pair instructions
      target-ppc: emulate lfiwax instruction
      target-ppc: emulate fcpsgn instruction
      target-ppc: emulate prtyw and prtyd instructions
      target-ppc: emulate cmpb instruction
      target-ppc: add instruction flags for Book I 2.05
      disas: Disassemble all ppc insns for the guest
      target-ppc: optimize fabs, fnabs, fneg
      PPC: Fix dcbz for linux-user on 970
      powerpc: correctly handle fpu exceptions.
      pseries: Generate device paths for VIO devices
      pseries: Convert VIO code to QOM style type safe(ish) casts
      target-ppc: Synchronize VPA state with KVM
      pseries: Fix some small errors in XICS logic
      target-ppc: Add more stubs for POWER7 PMU registers
      pseries: Fixes and enhancements to L1 cache properties
      pseries: Fix incorrect calculation of RMA size in certain configurations
      PPC: Fix compile with profiling enabled
      ...

commit c12915e638a31010923b8dbbf8ce06f564a175f9
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Apr 24 22:57:59 2013 +0200

    win32: generate console executable again
    
    The -mwindows option is not anymore in LIBS at this point of the Makefile,
    it is only in libs_softmmu.  Check the right variable.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile.target b/Makefile.target
index 7e4c77a..6583b05 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -18,7 +18,7 @@ ifdef CONFIG_USER_ONLY
 QEMU_PROG=qemu-$(TARGET_ARCH2)
 else
 # system emulator name
-ifneq (,$(findstring -mwindows,$(LIBS)))
+ifneq (,$(findstring -mwindows,$(libs_softmmu)))
 # Terminate program name with a 'w' because the linker builds a windows executable.
 QEMU_PROGW=qemu-system-$(TARGET_ARCH2)w$(EXESUF)
 endif # windows executable
commit c02817e5bfbb27955cac970019e6670dc427bc41
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sat Apr 27 00:27:48 2013 +0200

    win32: move Makefile dependencies on version-obj-y to rules.mak
    
    This makes the test on $(LIBTOOL) work.  Otherwise, LIBTOOL
    is /bin/false by the time the test is done.
    
    Fixes Win32 compilation without a working cross-libtool.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile b/Makefile
index 58e3527..f91f3b0 100644
--- a/Makefile
+++ b/Makefile
@@ -170,8 +170,7 @@ version.o: $(SRC_PATH)/version.rc config-host.h | version.lo
 version.lo: $(SRC_PATH)/version.rc config-host.h
 
 version-obj-$(CONFIG_WIN32) += version.o
-version-lobj-$(CONFIG_WIN32) += $(if $(LIBTOOL),version.lo)
-Makefile: $(version-obj-y) $(version-lobj-y)
+version-lobj-$(CONFIG_WIN32) += version.lo
 
 
 ######################################################################
diff --git a/rules.mak b/rules.mak
index 279525d..197a9d7 100644
--- a/rules.mak
+++ b/rules.mak
@@ -22,12 +22,15 @@ QEMU_CFLAGS += -I$(<D) -I$(@D)
 %.o: %.rc
 	$(call quiet-command,$(WINDRES) -I. -o $@ $<,"  RC    $(TARGET_DIR)$@")
 
+Makefile: $(version-obj-y)
+
 ifeq ($(LIBTOOL),)
 LIBTOOL = /bin/false
 LINK = $(call quiet-command,$(CC) $(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ \
        $(sort $(filter %.o, $1)) $(filter-out %.o, $1) $(version-obj-y) \
        $(LIBS),"  LINK  $(TARGET_DIR)$@")
 else
+Makefile: $(version-lobj-y)
 LIBTOOL += $(if $(V),,--quiet)
 %.lo: %.c
 	$(call quiet-command,$(LIBTOOL) --mode=compile --tag=CC $(CC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<,"  lt CC $@")
commit 6821cdc7c857c6af47277e98dde24cc99ddc0531
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sat Apr 27 00:25:31 2013 +0200

    win32: add generic RC rules to rules.mak
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile b/Makefile
index 8aca92f..58e3527 100644
--- a/Makefile
+++ b/Makefile
@@ -167,9 +167,7 @@ recurse-all: $(SUBDIR_RULES) $(ROMSUBDIR_RULES)
 bt-host.o: QEMU_CFLAGS += $(BLUEZ_CFLAGS)
 
 version.o: $(SRC_PATH)/version.rc config-host.h | version.lo
-	$(call quiet-command,$(WINDRES) -I. -o $@ $<,"  RC    $(TARGET_DIR)$@")
 version.lo: $(SRC_PATH)/version.rc config-host.h
-	$(call quiet-command,$(LIBTOOL) --mode=compile --tag=RC $(WINDRES) -I. -o $@ $<,"lt RC   $(TARGET_DIR)$@")
 
 version-obj-$(CONFIG_WIN32) += version.o
 version-lobj-$(CONFIG_WIN32) += $(if $(LIBTOOL),version.lo)
diff --git a/rules.mak b/rules.mak
index 292a422..279525d 100644
--- a/rules.mak
+++ b/rules.mak
@@ -19,6 +19,8 @@ QEMU_CFLAGS += -I$(<D) -I$(@D)
 
 %.o: %.c
 	$(call quiet-command,$(CC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<,"  CC    $(TARGET_DIR)$@")
+%.o: %.rc
+	$(call quiet-command,$(WINDRES) -I. -o $@ $<,"  RC    $(TARGET_DIR)$@")
 
 ifeq ($(LIBTOOL),)
 LIBTOOL = /bin/false
@@ -29,6 +31,8 @@ else
 LIBTOOL += $(if $(V),,--quiet)
 %.lo: %.c
 	$(call quiet-command,$(LIBTOOL) --mode=compile --tag=CC $(CC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<,"  lt CC $@")
+%.lo: %.rc
+	$(call quiet-command,$(LIBTOOL) --mode=compile --tag=RC $(WINDRES) -I. -o $@ $<,"lt RC   $(TARGET_DIR)$@")
 %.lo: %.dtrace
 	$(call quiet-command,$(LIBTOOL) --mode=compile --tag=CC dtrace -o $@ -G -s $<, " lt GEN $(TARGET_DIR)$@")
 
commit 7d08d85645def18eac2a9d672c1868a35e0bcf79
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Sat Apr 20 08:56:22 2013 +0000

    target-ppc: add support for extended mtfsf/mtfsfi forms
    
    Power ISA 2.05 adds support for extended mtfsf/mtfsfi form, with a new
    W field to select the upper part of the FPCSR register.
    
    For that the helper is changed to handle 64-bit input values and mask with
    up to 16 bits. The mtfsf/mtfsfi instructions do not have the W bit
    marked as invalid anymore. Instead this is checked in the helper, which
    therefore needs to access to the insns/insns_flags2. They are added in
    the DisasContext struct. Finally change all accesses to the opcode fields
    through extract helpers, prefixed with FP for consistency.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/fpu_helper.c b/target-ppc/fpu_helper.c
index 1f0eeab..4f60218 100644
--- a/target-ppc/fpu_helper.c
+++ b/target-ppc/fpu_helper.c
@@ -430,20 +430,17 @@ void helper_fpscr_setbit(CPUPPCState *env, uint32_t bit)
 
 void helper_store_fpscr(CPUPPCState *env, uint64_t arg, uint32_t mask)
 {
-    /*
-     * We use only the 32 LSB of the incoming fpr
-     */
-    uint32_t prev, new;
+    target_ulong prev, new;
     int i;
 
     prev = env->fpscr;
-    new = (uint32_t)arg;
-    new &= ~0x60000000;
-    new |= prev & 0x60000000;
-    for (i = 0; i < 8; i++) {
+    new = (target_ulong)arg;
+    new &= ~0x60000000LL;
+    new |= prev & 0x60000000LL;
+    for (i = 0; i < sizeof(target_ulong) * 2; i++) {
         if (mask & (1 << i)) {
-            env->fpscr &= ~(0xF << (4 * i));
-            env->fpscr |= new & (0xF << (4 * i));
+            env->fpscr &= ~(0xFLL << (4 * i));
+            env->fpscr |= new & (0xFLL << (4 * i));
         }
     }
     /* Update VX and FEX */
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index e40c452..6182bd7 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -202,6 +202,8 @@ typedef struct DisasContext {
     int spe_enabled;
     ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
     int singlestep_enabled;
+    uint64_t insns_flags;
+    uint64_t insns_flags2;
 } DisasContext;
 
 /* True when active word size < size of target_long.  */
@@ -423,9 +425,14 @@ EXTRACT_HELPER(ME, 1, 5);
 EXTRACT_HELPER(TO, 21, 5);
 
 EXTRACT_HELPER(CRM, 12, 8);
-EXTRACT_HELPER(FM, 17, 8);
 EXTRACT_HELPER(SR, 16, 4);
+
+/* mtfsf/mtfsfi */
+EXTRACT_HELPER(FPBF, 19, 3);
 EXTRACT_HELPER(FPIMM, 12, 4);
+EXTRACT_HELPER(FPL, 21, 1);
+EXTRACT_HELPER(FPFLM, 17, 8);
+EXTRACT_HELPER(FPW, 16, 1);
 
 /***                            Jump target decoding                       ***/
 /* Displacement */
@@ -2360,19 +2367,27 @@ static void gen_mtfsb1(DisasContext *ctx)
 static void gen_mtfsf(DisasContext *ctx)
 {
     TCGv_i32 t0;
-    int L = ctx->opcode & 0x02000000;
+    int flm, l, w;
 
     if (unlikely(!ctx->fpu_enabled)) {
         gen_exception(ctx, POWERPC_EXCP_FPU);
         return;
     }
+    flm = FPFLM(ctx->opcode);
+    l = FPL(ctx->opcode);
+    w = FPW(ctx->opcode);
+    if (unlikely(w & !(ctx->insns_flags2 & PPC2_ISA205))) {
+        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
+        return;
+    }
     /* NIP cannot be restored if the memory exception comes from an helper */
     gen_update_nip(ctx, ctx->nip - 4);
     gen_reset_fpstatus();
-    if (L)
-        t0 = tcg_const_i32(0xff);
-    else
-        t0 = tcg_const_i32(FM(ctx->opcode));
+    if (l) {
+        t0 = tcg_const_i32((ctx->insns_flags2 & PPC2_ISA205) ? 0xffff : 0xff);
+    } else {
+        t0 = tcg_const_i32(flm << (w * 8));
+    }
     gen_helper_store_fpscr(cpu_env, cpu_fpr[rB(ctx->opcode)], t0);
     tcg_temp_free_i32(t0);
     if (unlikely(Rc(ctx->opcode) != 0)) {
@@ -2386,7 +2401,7 @@ static void gen_mtfsf(DisasContext *ctx)
 /* mtfsfi */
 static void gen_mtfsfi(DisasContext *ctx)
 {
-    int bf, sh;
+    int bf, sh, w;
     TCGv_i64 t0;
     TCGv_i32 t1;
 
@@ -2394,12 +2409,17 @@ static void gen_mtfsfi(DisasContext *ctx)
         gen_exception(ctx, POWERPC_EXCP_FPU);
         return;
     }
-    bf = crbD(ctx->opcode) >> 2;
-    sh = 7 - bf;
+    w = FPW(ctx->opcode);
+    bf = FPBF(ctx->opcode);
+    if (unlikely(w & !(ctx->insns_flags2 & PPC2_ISA205))) {
+        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
+        return;
+    }
+    sh = (8 * w) + 7 - bf;
     /* NIP cannot be restored if the memory exception comes from an helper */
     gen_update_nip(ctx, ctx->nip - 4);
     gen_reset_fpstatus();
-    t0 = tcg_const_i64(FPIMM(ctx->opcode) << (4 * sh));
+    t0 = tcg_const_i64(((uint64_t)FPIMM(ctx->opcode)) << (4 * sh));
     t1 = tcg_const_i32(1 << sh);
     gen_helper_store_fpscr(cpu_env, t0, t1);
     tcg_temp_free_i64(t0);
@@ -8689,8 +8709,8 @@ GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT),
 GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT),
 GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT),
 GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT),
-GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x00010000, PPC_FLOAT),
-GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT),
+GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x00000000, PPC_FLOAT),
+GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006e0800, PPC_FLOAT),
 #if defined(TARGET_PPC64)
 GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B),
 GEN_HANDLER(lq, 0x38, 0xFF, 0xFF, 0x00000000, PPC_64BX),
@@ -9728,6 +9748,8 @@ static inline void gen_intermediate_code_internal(CPUPPCState *env,
     ctx.exception = POWERPC_EXCP_NONE;
     ctx.spr_cb = env->spr_cb;
     ctx.mem_idx = env->mmu_idx;
+    ctx.insns_flags = env->insns_flags;
+    ctx.insns_flags2 = env->insns_flags2;
     ctx.access_type = -1;
     ctx.le_mode = env->hflags & (1 << MSR_LE) ? 1 : 0;
 #if defined(TARGET_PPC64)
commit 44bc0c4d3e90bfa1fafdbcc19d023d2d4b119eed
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Sat Apr 20 08:56:21 2013 +0000

    target-ppc: emulate store doubleword pair instructions
    
    Needed for Power ISA version 2.05 compliance. The check for odd register
    pairs is done using the invalid bits.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 40b6162..e40c452 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -3459,6 +3459,52 @@ GEN_STFS(stfd, st64, 0x16, PPC_FLOAT);
 /* stfs stfsu stfsux stfsx */
 GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT);
 
+/* stfdp */
+static void gen_stfdp(DisasContext *ctx)
+{
+    TCGv EA;
+    if (unlikely(!ctx->fpu_enabled)) {
+        gen_exception(ctx, POWERPC_EXCP_FPU);
+        return;
+    }
+    gen_set_access_type(ctx, ACCESS_FLOAT);
+    EA = tcg_temp_new();
+    gen_addr_imm_index(ctx, EA, 0);                                           \
+    if (unlikely(ctx->le_mode)) {
+        gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
+        tcg_gen_addi_tl(EA, EA, 8);
+        gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
+    } else {
+        gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
+        tcg_gen_addi_tl(EA, EA, 8);
+        gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
+    }
+    tcg_temp_free(EA);
+}
+
+/* stfdpx */
+static void gen_stfdpx(DisasContext *ctx)
+{
+    TCGv EA;
+    if (unlikely(!ctx->fpu_enabled)) {
+        gen_exception(ctx, POWERPC_EXCP_FPU);
+        return;
+    }
+    gen_set_access_type(ctx, ACCESS_FLOAT);
+    EA = tcg_temp_new();
+    gen_addr_reg_index(ctx, EA);
+    if (unlikely(ctx->le_mode)) {
+        gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
+        tcg_gen_addi_tl(EA, EA, 8);
+        gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
+    } else {
+        gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
+        tcg_gen_addi_tl(EA, EA, 8);
+        gen_qemu_st64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
+    }
+    tcg_temp_free(EA);
+}
+
 /* Optional: */
 static inline void gen_qemu_st32fiw(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
 {
@@ -9106,6 +9152,8 @@ GEN_STXF(name, stop, 0x17, op | 0x00, type)
 GEN_STFS(stfd, st64, 0x16, PPC_FLOAT)
 GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT)
 GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX)
+GEN_HANDLER_E(stfdp, 0x3D, 0xFF, 0xFF, 0x00200003, PPC_NONE, PPC2_ISA205),
+GEN_HANDLER_E(stfdpx, 0x1F, 0x17, 0x1C, 0x00200001, PPC_NONE, PPC2_ISA205),
 
 #undef GEN_CRLOGIC
 #define GEN_CRLOGIC(name, tcg_op, opc)                                        \
commit 05050ee8049f9fe75ffcac4a5aa053b5631653bf
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Sat Apr 20 08:56:20 2013 +0000

    target-ppc: emulate load doubleword pair instructions
    
    Needed for Power ISA version 2.05 compliance. The check for odd register
    pairs is done using the invalid bits.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 228c695..40b6162 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -3300,6 +3300,52 @@ GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT);
  /* lfs lfsu lfsux lfsx */
 GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT);
 
+/* lfdp */
+static void gen_lfdp(DisasContext *ctx)
+{
+    TCGv EA;
+    if (unlikely(!ctx->fpu_enabled)) {
+        gen_exception(ctx, POWERPC_EXCP_FPU);
+        return;
+    }
+    gen_set_access_type(ctx, ACCESS_FLOAT);
+    EA = tcg_temp_new();
+    gen_addr_imm_index(ctx, EA, 0);                                           \
+    if (unlikely(ctx->le_mode)) {
+        gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
+        tcg_gen_addi_tl(EA, EA, 8);
+        gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
+    } else {
+        gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
+        tcg_gen_addi_tl(EA, EA, 8);
+        gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
+    }
+    tcg_temp_free(EA);
+}
+
+/* lfdpx */
+static void gen_lfdpx(DisasContext *ctx)
+{
+    TCGv EA;
+    if (unlikely(!ctx->fpu_enabled)) {
+        gen_exception(ctx, POWERPC_EXCP_FPU);
+        return;
+    }
+    gen_set_access_type(ctx, ACCESS_FLOAT);
+    EA = tcg_temp_new();
+    gen_addr_reg_index(ctx, EA);
+    if (unlikely(ctx->le_mode)) {
+        gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
+        tcg_gen_addi_tl(EA, EA, 8);
+        gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
+    } else {
+        gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode)], EA);
+        tcg_gen_addi_tl(EA, EA, 8);
+        gen_qemu_ld64(ctx, cpu_fpr[rD(ctx->opcode) + 1], EA);
+    }
+    tcg_temp_free(EA);
+}
+
 /* lfiwax */
 static void gen_lfiwax(DisasContext *ctx)
 {
@@ -9035,6 +9081,8 @@ GEN_LDXF(name, ldop, 0x17, op | 0x00, type)
 GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT)
 GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT)
 GEN_HANDLER_E(lfiwax, 0x1f, 0x17, 0x1a, 0x00000001, PPC_NONE, PPC2_ISA205),
+GEN_HANDLER_E(lfdp, 0x39, 0xFF, 0xFF, 0x00200003, PPC_NONE, PPC2_ISA205),
+GEN_HANDLER_E(lfdpx, 0x1F, 0x17, 0x18, 0x00200001, PPC_NONE, PPC2_ISA205),
 
 #undef GEN_STF
 #undef GEN_STUF
commit 199f830d19576c77a5ed8fec81c218258d73f1dd
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Sat Apr 20 08:56:19 2013 +0000

    target-ppc: emulate lfiwax instruction
    
    Needed for Power ISA version 2.05 compliance.
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
    [agraf: fix tcg debug error]
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 1989818..228c695 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -3300,6 +3300,26 @@ GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT);
  /* lfs lfsu lfsux lfsx */
 GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT);
 
+/* lfiwax */
+static void gen_lfiwax(DisasContext *ctx)
+{
+    TCGv EA;
+    TCGv t0;
+    if (unlikely(!ctx->fpu_enabled)) {
+        gen_exception(ctx, POWERPC_EXCP_FPU);
+        return;
+    }
+    gen_set_access_type(ctx, ACCESS_FLOAT);
+    EA = tcg_temp_new();
+    t0 = tcg_temp_new();
+    gen_addr_reg_index(ctx, EA);
+    gen_qemu_ld32u(ctx, t0, EA);
+    tcg_gen_ext_tl_i64(cpu_fpr[rD(ctx->opcode)], t0);
+    tcg_gen_ext32s_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);
+    tcg_temp_free(EA);
+    tcg_temp_free(t0);
+}
+
 /***                         Floating-point store                          ***/
 #define GEN_STF(name, stop, opc, type)                                        \
 static void glue(gen_, name)(DisasContext *ctx)                                       \
@@ -9014,6 +9034,7 @@ GEN_LDXF(name, ldop, 0x17, op | 0x00, type)
 
 GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT)
 GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT)
+GEN_HANDLER_E(lfiwax, 0x1f, 0x17, 0x1a, 0x00000001, PPC_NONE, PPC2_ISA205),
 
 #undef GEN_STF
 #undef GEN_STUF
commit f03328882f8008fc299d5f8ae33b9a80571fea3c
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Sat Apr 20 08:56:18 2013 +0000

    target-ppc: emulate fcpsgn instruction
    
    Needed for Power ISA version 2.05 compliance.
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 2fabbaf..1989818 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -2258,6 +2258,19 @@ static void gen_fneg(DisasContext *ctx)
     gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
 }
 
+/* fcpsgn: PowerPC 2.05 specification */
+/* XXX: beware that fcpsgn never checks for NaNs nor update FPSCR */
+static void gen_fcpsgn(DisasContext *ctx)
+{
+    if (unlikely(!ctx->fpu_enabled)) {
+        gen_exception(ctx, POWERPC_EXCP_FPU);
+        return;
+    }
+    tcg_gen_deposit_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)],
+                        cpu_fpr[rB(ctx->opcode)], 0, 63);
+    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
+}
+
 /***                  Floating-Point status & ctrl register                ***/
 
 /* mcrfs */
@@ -8559,6 +8572,7 @@ GEN_HANDLER(fabs, 0x3F, 0x08, 0x08, 0x001F0000, PPC_FLOAT),
 GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT),
 GEN_HANDLER(fnabs, 0x3F, 0x08, 0x04, 0x001F0000, PPC_FLOAT),
 GEN_HANDLER(fneg, 0x3F, 0x08, 0x01, 0x001F0000, PPC_FLOAT),
+GEN_HANDLER_E(fcpsgn, 0x3F, 0x08, 0x00, 0x00000000, PPC_NONE, PPC2_ISA205),
 GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT),
 GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT),
 GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT),
commit 725bcec2885d4f6df78e24fb54459c9efb97abd5
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Sat Apr 20 08:56:17 2013 +0000

    target-ppc: emulate prtyw and prtyd instructions
    
    Needed for Power ISA version 2.05 compliance.
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
    [agraf: fix 32-bit host compile, simplify code]
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 4d477d2..2fabbaf 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -1467,6 +1467,38 @@ static void gen_popcntd(DisasContext *ctx)
 }
 #endif
 
+/* prtyw: PowerPC 2.05 specification */
+static void gen_prtyw(DisasContext *ctx)
+{
+    TCGv ra = cpu_gpr[rA(ctx->opcode)];
+    TCGv rs = cpu_gpr[rS(ctx->opcode)];
+    TCGv t0 = tcg_temp_new();
+    tcg_gen_shri_tl(t0, rs, 16);
+    tcg_gen_xor_tl(ra, rs, t0);
+    tcg_gen_shri_tl(t0, ra, 8);
+    tcg_gen_xor_tl(ra, ra, t0);
+    tcg_gen_andi_tl(ra, ra, (target_ulong)0x100000001ULL);
+    tcg_temp_free(t0);
+}
+
+#if defined(TARGET_PPC64)
+/* prtyd: PowerPC 2.05 specification */
+static void gen_prtyd(DisasContext *ctx)
+{
+    TCGv ra = cpu_gpr[rA(ctx->opcode)];
+    TCGv rs = cpu_gpr[rS(ctx->opcode)];
+    TCGv t0 = tcg_temp_new();
+    tcg_gen_shri_tl(t0, rs, 32);
+    tcg_gen_xor_tl(ra, rs, t0);
+    tcg_gen_shri_tl(t0, ra, 16);
+    tcg_gen_xor_tl(ra, ra, t0);
+    tcg_gen_shri_tl(t0, ra, 8);
+    tcg_gen_xor_tl(ra, ra, t0);
+    tcg_gen_andi_tl(ra, ra, 1);
+    tcg_temp_free(t0);
+}
+#endif
+
 #if defined(TARGET_PPC64)
 /* extsw & extsw. */
 GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B);
@@ -8498,9 +8530,11 @@ GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
 GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
 GEN_HANDLER(popcntb, 0x1F, 0x03, 0x03, 0x0000F801, PPC_POPCNTB),
 GEN_HANDLER(popcntw, 0x1F, 0x1A, 0x0b, 0x0000F801, PPC_POPCNTWD),
+GEN_HANDLER_E(prtyw, 0x1F, 0x1A, 0x04, 0x0000F801, PPC_NONE, PPC2_ISA205),
 #if defined(TARGET_PPC64)
 GEN_HANDLER(popcntd, 0x1F, 0x1A, 0x0F, 0x0000F801, PPC_POPCNTWD),
 GEN_HANDLER(cntlzd, 0x1F, 0x1A, 0x01, 0x00000000, PPC_64B),
+GEN_HANDLER_E(prtyd, 0x1F, 0x1A, 0x05, 0x0000F801, PPC_NONE, PPC2_ISA205),
 #endif
 GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
 GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
commit fcfda20f2f5df30d88d087d443c1c08649df8827
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Sat Apr 20 08:56:16 2013 +0000

    target-ppc: emulate cmpb instruction
    
    Needed for Power ISA version 2.05 compliance.
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index 07397b2..56814b5 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -36,6 +36,7 @@ DEF_HELPER_3(mulldo, i64, env, i64, i64)
 DEF_HELPER_FLAGS_1(cntlzw, TCG_CALL_NO_RWG_SE, tl, tl)
 DEF_HELPER_FLAGS_1(popcntb, TCG_CALL_NO_RWG_SE, tl, tl)
 DEF_HELPER_FLAGS_1(popcntw, TCG_CALL_NO_RWG_SE, tl, tl)
+DEF_HELPER_FLAGS_2(cmpb, TCG_CALL_NO_RWG_SE, tl, tl, tl)
 DEF_HELPER_3(sraw, tl, env, tl, tl)
 #if defined(TARGET_PPC64)
 DEF_HELPER_FLAGS_1(cntlzd, TCG_CALL_NO_RWG_SE, tl, tl)
diff --git a/target-ppc/int_helper.c b/target-ppc/int_helper.c
index 54eca9b..e50bdd2 100644
--- a/target-ppc/int_helper.c
+++ b/target-ppc/int_helper.c
@@ -53,6 +53,21 @@ target_ulong helper_cntlzd(target_ulong t)
 }
 #endif
 
+target_ulong helper_cmpb(target_ulong rs, target_ulong rb)
+{
+    target_ulong mask = 0xff;
+    target_ulong ra = 0;
+    int i;
+
+    for (i = 0; i < sizeof(target_ulong); i++) {
+        if ((rs & mask) == (rb & mask)) {
+            ra |= mask;
+        }
+        mask <<= 8;
+    }
+    return ra;
+}
+
 /* shift right arithmetic helper */
 target_ulong helper_sraw(CPUPPCState *env, target_ulong value,
                          target_ulong shift)
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 6cc7893..4d477d2 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -739,6 +739,13 @@ static void gen_isel(DisasContext *ctx)
     tcg_temp_free_i32(t0);
 }
 
+/* cmpb: PowerPC 2.05 specification */
+static void gen_cmpb(DisasContext *ctx)
+{
+    gen_helper_cmpb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],
+                    cpu_gpr[rB(ctx->opcode)]);
+}
+
 /***                           Integer arithmetic                          ***/
 
 static inline void gen_op_arith_compute_ov(DisasContext *ctx, TCGv arg0,
@@ -8463,6 +8470,7 @@ GEN_HANDLER(cmp, 0x1F, 0x00, 0x00, 0x00400000, PPC_INTEGER),
 GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER),
 GEN_HANDLER(cmpl, 0x1F, 0x00, 0x01, 0x00400000, PPC_INTEGER),
 GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER),
+GEN_HANDLER_E(cmpb, 0x1F, 0x1C, 0x0F, 0x00000001, PPC_NONE, PPC2_ISA205),
 GEN_HANDLER(isel, 0x1F, 0x0F, 0xFF, 0x00000001, PPC_ISEL),
 GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
 GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
commit 9c2627b09d1bdee8a58730bbf48c76be48bd659f
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Sat Apr 20 08:56:15 2013 +0000

    target-ppc: add instruction flags for Book I 2.05
    
    .. and enable it on POWER7 CPU.
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index b8b09b9..7cacb56 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1870,8 +1870,10 @@ enum {
     PPC2_PRCNTL        = 0x0000000000000008ULL,
     /* Byte-reversed, indexed, double-word load and store                    */
     PPC2_DBRX          = 0x0000000000000010ULL,
+    /* Book I 2.05 PowerPC specification                                     */
+    PPC2_ISA205        = 0x0000000000000020ULL,
 
-#define PPC_TCG_INSNS2 (PPC2_BOOKE206 | PPC2_PRCNTL | PPC2_DBRX)
+#define PPC_TCG_INSNS2 (PPC2_BOOKE206 | PPC2_PRCNTL | PPC2_DBRX | PPC2_ISA205)
 };
 
 /*****************************************************************************/
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index b0e3536..6feb62a 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7042,7 +7042,7 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
                        PPC_64B | PPC_ALTIVEC |
                        PPC_SEGMENT_64B | PPC_SLBI |
                        PPC_POPCNTB | PPC_POPCNTWD;
-    pcc->insns_flags2 = PPC2_VSX | PPC2_DFP | PPC2_DBRX;
+    pcc->insns_flags2 = PPC2_VSX | PPC2_DFP | PPC2_DBRX | PPC2_ISA205;
     pcc->msr_mask = 0x800000000204FF36ULL;
     pcc->mmu_model = POWERPC_MMU_2_06;
 #if defined(CONFIG_SOFTMMU)
commit 88770fec6c8daeb96c1f5cdbedff9df173431fd6
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Sat Apr 20 08:56:14 2013 +0000

    disas: Disassemble all ppc insns for the guest
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/disas.c b/disas.c
index 67103e0..e51127e 100644
--- a/disas.c
+++ b/disas.c
@@ -227,6 +227,7 @@ void target_disas(FILE *out, CPUArchState *env, target_ulong code,
         s.info.mach = bfd_mach_ppc;
 #endif
     }
+    s.info.disassembler_options = (char *)"any";
     print_insn = print_insn_ppc;
 #elif defined(TARGET_M68K)
     print_insn = print_insn_m68k;
commit bf45a2e67cab8fcccb24e389bbd4ef68866a1cff
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Sat Apr 20 08:56:13 2013 +0000

    target-ppc: optimize fabs, fnabs, fneg
    
    fabs, fnabs and fneg are just flipping the bit sign of an FP register,
    this can be implemented in TCG instead of using softfloat.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/fpu_helper.c b/target-ppc/fpu_helper.c
index 1e141fb..1f0eeab 100644
--- a/target-ppc/fpu_helper.c
+++ b/target-ppc/fpu_helper.c
@@ -596,37 +596,6 @@ uint64_t helper_fdiv(CPUPPCState *env, uint64_t arg1, uint64_t arg2)
     return farg1.ll;
 }
 
-/* fabs */
-uint64_t helper_fabs(CPUPPCState *env, uint64_t arg)
-{
-    CPU_DoubleU farg;
-
-    farg.ll = arg;
-    farg.d = float64_abs(farg.d);
-    return farg.ll;
-}
-
-/* fnabs */
-uint64_t helper_fnabs(CPUPPCState *env, uint64_t arg)
-{
-    CPU_DoubleU farg;
-
-    farg.ll = arg;
-    farg.d = float64_abs(farg.d);
-    farg.d = float64_chs(farg.d);
-    return farg.ll;
-}
-
-/* fneg */
-uint64_t helper_fneg(CPUPPCState *env, uint64_t arg)
-{
-    CPU_DoubleU farg;
-
-    farg.ll = arg;
-    farg.d = float64_chs(farg.d);
-    return farg.ll;
-}
-
 /* fctiw - fctiw. */
 uint64_t helper_fctiw(CPUPPCState *env, uint64_t arg)
 {
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index d33ee66..07397b2 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -80,9 +80,6 @@ DEF_HELPER_4(fmadd, i64, env, i64, i64, i64)
 DEF_HELPER_4(fmsub, i64, env, i64, i64, i64)
 DEF_HELPER_4(fnmadd, i64, env, i64, i64, i64)
 DEF_HELPER_4(fnmsub, i64, env, i64, i64, i64)
-DEF_HELPER_2(fabs, i64, env, i64)
-DEF_HELPER_2(fnabs, i64, env, i64)
-DEF_HELPER_2(fneg, i64, env, i64)
 DEF_HELPER_2(fsqrt, i64, env, i64)
 DEF_HELPER_2(fre, i64, env, i64)
 DEF_HELPER_2(fres, i64, env, i64)
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 362ca3a..6cc7893 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -2170,7 +2170,16 @@ static void gen_fcmpu(DisasContext *ctx)
 /***                         Floating-point move                           ***/
 /* fabs */
 /* XXX: beware that fabs never checks for NaNs nor update FPSCR */
-GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT);
+static void gen_fabs(DisasContext *ctx)
+{
+    if (unlikely(!ctx->fpu_enabled)) {
+        gen_exception(ctx, POWERPC_EXCP_FPU);
+        return;
+    }
+    tcg_gen_andi_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)],
+                     ~(1ULL << 63));
+    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
+}
 
 /* fmr  - fmr. */
 /* XXX: beware that fmr never checks for NaNs nor update FPSCR */
@@ -2186,10 +2195,29 @@ static void gen_fmr(DisasContext *ctx)
 
 /* fnabs */
 /* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
-GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT);
+static void gen_fnabs(DisasContext *ctx)
+{
+    if (unlikely(!ctx->fpu_enabled)) {
+        gen_exception(ctx, POWERPC_EXCP_FPU);
+        return;
+    }
+    tcg_gen_ori_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)],
+                    1ULL << 63);
+    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
+}
+
 /* fneg */
 /* XXX: beware that fneg never checks for NaNs nor update FPSCR */
-GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT);
+static void gen_fneg(DisasContext *ctx)
+{
+    if (unlikely(!ctx->fpu_enabled)) {
+        gen_exception(ctx, POWERPC_EXCP_FPU);
+        return;
+    }
+    tcg_gen_xori_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)],
+                     1ULL << 63);
+    gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
+}
 
 /***                  Floating-Point status & ctrl register                ***/
 
@@ -8485,7 +8513,10 @@ GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT),
 GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT),
 GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT),
 GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT),
+GEN_HANDLER(fabs, 0x3F, 0x08, 0x08, 0x001F0000, PPC_FLOAT),
 GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT),
+GEN_HANDLER(fnabs, 0x3F, 0x08, 0x04, 0x001F0000, PPC_FLOAT),
+GEN_HANDLER(fneg, 0x3F, 0x08, 0x01, 0x001F0000, PPC_FLOAT),
 GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT),
 GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT),
 GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT),
@@ -8842,9 +8873,6 @@ GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT),
 GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT),
 GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT),
 GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT),
-GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT),
-GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT),
-GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT),
 
 #undef GEN_LD
 #undef GEN_LDU
commit 414f5d1448fef9aad6d37f1d40d1158396573447
Author: Alexander Graf <agraf at suse.de>
Date:   Fri Apr 26 09:18:58 2013 +0200

    PPC: Fix dcbz for linux-user on 970
    
    The default with linux-user for dcbz on 970 is to emulate 32 byte clears.
    However, redoing the dcbzl support we added a check to not honor the bit
    in HID5 that sets this.
    
    Remove the #ifdef check on linux user, so that we get 32 byte clears again.
    
    Reported-by: Riku Voipio <riku.voipio at iki.fi>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/mem_helper.c b/target-ppc/mem_helper.c
index 9783e52..d8e63ca 100644
--- a/target-ppc/mem_helper.c
+++ b/target-ppc/mem_helper.c
@@ -140,7 +140,7 @@ void helper_dcbz(CPUPPCState *env, target_ulong addr, uint32_t is_dcbzl)
 {
     int dcbz_size = env->dcache_line_size;
 
-#if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64)
+#if defined(TARGET_PPC64)
     if (!is_dcbzl &&
         (env->excp_model == POWERPC_EXCP_970) &&
         ((env->spr[SPR_970_HID5] >> 7) & 0x3) == 1) {
commit db72c9f256ae70b30c5d5985234f085df4226c55
Author: Tristan Gingold <gingold at adacore.com>
Date:   Tue Apr 9 05:00:55 2013 +0000

    powerpc: correctly handle fpu exceptions.
    
    Raise the exception on the first occurence, do not wait for the next
    floating point operation.
    
    Signed-off-by: Fabien Chouteau <chouteau at adacore.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/fpu_helper.c b/target-ppc/fpu_helper.c
index 9e779ea..1e141fb 100644
--- a/target-ppc/fpu_helper.c
+++ b/target-ppc/fpu_helper.c
@@ -470,6 +470,18 @@ void store_fpscr(CPUPPCState *env, uint64_t arg, uint32_t mask)
 
 void helper_float_check_status(CPUPPCState *env)
 {
+    int status = get_float_exception_flags(&env->fp_status);
+
+    if (status & float_flag_divbyzero) {
+        float_zero_divide_excp(env);
+    } else if (status & float_flag_overflow) {
+        float_overflow_excp(env);
+    } else if (status & float_flag_underflow) {
+        float_underflow_excp(env);
+    } else if (status & float_flag_inexact) {
+        float_inexact_excp(env);
+    }
+
     if (env->exception_index == POWERPC_EXCP_PROGRAM &&
         (env->error_code & POWERPC_EXCP_FP)) {
         /* Differred floating-point exception after target FPR update */
@@ -477,17 +489,6 @@ void helper_float_check_status(CPUPPCState *env)
             helper_raise_exception_err(env, env->exception_index,
                                        env->error_code);
         }
-    } else {
-        int status = get_float_exception_flags(&env->fp_status);
-        if (status & float_flag_divbyzero) {
-            float_zero_divide_excp(env);
-        } else if (status & float_flag_overflow) {
-            float_overflow_excp(env);
-        } else if (status & float_flag_underflow) {
-            float_underflow_excp(env);
-        } else if (status & float_flag_inexact) {
-            float_inexact_excp(env);
-        }
     }
 }
 
commit c4eda5b7234265313b09c2c9f9fdd3a960db97db
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Sun Apr 7 19:08:17 2013 +0000

    pseries: Generate device paths for VIO devices
    
    This patch implements a get_dev_path qdev hook for the pseries paravirtual
    VIO bus.  With upcoming savevm support, this will become very important for
    scsi disks hanging of VIO virtual SCSI adapters.  scsibus_get_dev_path
    uses the get_dev_path of the parent adapter if available, but otherwise
    just uses a local channel/target/lun number to identify the device.  So if
    two disks are present in the system having the same target and lun on
    seperate VIO scsi adapters, savevm cannot distinguish them.  Since the
    conventional way of using VSCSI adapters is to have just one disk per
    adapter, such a conflict is very likely.
    
    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_vio.c b/hw/ppc/spapr_vio.c
index ccc794d..1405c32 100644
--- a/hw/ppc/spapr_vio.c
+++ b/hw/ppc/spapr_vio.c
@@ -53,9 +53,29 @@ static Property spapr_vio_props[] = {
     DEFINE_PROP_END_OF_LIST(),
 };
 
+static char *spapr_vio_get_dev_name(DeviceState *qdev)
+{
+    VIOsPAPRDevice *dev = VIO_SPAPR_DEVICE(qdev);
+    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;
+}
+
+static void spapr_vio_bus_class_init(ObjectClass *klass, void *data)
+{
+    BusClass *k = BUS_CLASS(klass);
+
+    k->get_dev_path = spapr_vio_get_dev_name;
+}
+
 static const TypeInfo spapr_vio_bus_info = {
     .name = TYPE_SPAPR_VIO_BUS,
     .parent = TYPE_BUS,
+    .class_init = spapr_vio_bus_class_init,
     .instance_size = sizeof(VIOsPAPRBus),
 };
 
@@ -74,17 +94,6 @@ VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg)
     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)
@@ -98,7 +107,7 @@ static int vio_make_devnode(VIOsPAPRDevice *dev,
         return vdevice_off;
     }
 
-    dt_name = vio_format_dev_name(dev);
+    dt_name = spapr_vio_get_dev_name(DEVICE(dev));
     node_off = fdt_add_subnode(fdt, vdevice_off, dt_name);
     g_free(dt_name);
     if (node_off < 0) {
@@ -437,7 +446,7 @@ static int spapr_vio_busdev_init(DeviceState *qdev)
 
     /* Don't overwrite ids assigned on the command line */
     if (!dev->qdev.id) {
-        id = vio_format_dev_name(dev);
+        id = spapr_vio_get_dev_name(DEVICE(dev));
         dev->qdev.id = id;
     }
 
@@ -636,7 +645,7 @@ int spapr_populate_chosen_stdout(void *fdt, VIOsPAPRBus *bus)
         return offset;
     }
 
-    name = vio_format_dev_name(dev);
+    name = spapr_vio_get_dev_name(DEVICE(dev));
     path = g_strdup_printf("/vdevice/%s", name);
 
     ret = fdt_setprop_string(fdt, offset, "linux,stdout-path", path);
commit fd506b4f61cd22793f8c54a9adf5c69345792501
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Sun Apr 7 19:08:16 2013 +0000

    pseries: Convert VIO code to QOM style type safe(ish) casts
    
    Curerntly the pseries VIO device code contains quite a few explicit
    uses of DO_UPCAST and plain C casts.  This is (obviously) type unsafe,
    and not the conventional way of doing things in the QOM model.  This
    patch converts the code to use the QOM convention of per-type macros
    to do verified casts with OBJECT_CHECK().
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/char/spapr_vty.c b/hw/char/spapr_vty.c
index afcec1f..2993848 100644
--- a/hw/char/spapr_vty.c
+++ b/hw/char/spapr_vty.c
@@ -12,16 +12,20 @@ typedef struct VIOsPAPRVTYDevice {
     uint8_t buf[VTERM_BUFSIZE];
 } VIOsPAPRVTYDevice;
 
+#define TYPE_VIO_SPAPR_VTY_DEVICE "spapr-vty"
+#define VIO_SPAPR_VTY_DEVICE(obj) \
+     OBJECT_CHECK(VIOsPAPRVTYDevice, (obj), TYPE_VIO_SPAPR_VTY_DEVICE)
+
 static int vty_can_receive(void *opaque)
 {
-    VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)opaque;
+    VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(opaque);
 
     return (dev->in - dev->out) < VTERM_BUFSIZE;
 }
 
 static void vty_receive(void *opaque, const uint8_t *buf, int size)
 {
-    VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)opaque;
+    VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(opaque);
     int i;
 
     if ((dev->in == dev->out) && size) {
@@ -36,7 +40,7 @@ static void vty_receive(void *opaque, const uint8_t *buf, int size)
 
 static int vty_getchars(VIOsPAPRDevice *sdev, uint8_t *buf, int max)
 {
-    VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev;
+    VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(sdev);
     int n = 0;
 
     while ((n < max) && (dev->out != dev->in)) {
@@ -48,7 +52,7 @@ static int vty_getchars(VIOsPAPRDevice *sdev, uint8_t *buf, int max)
 
 void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len)
 {
-    VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev;
+    VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(sdev);
 
     /* FIXME: should check the qemu_chr_fe_write() return value */
     qemu_chr_fe_write(dev->chardev, buf, len);
@@ -56,7 +60,7 @@ void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len)
 
 static int spapr_vty_init(VIOsPAPRDevice *sdev)
 {
-    VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev;
+    VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(sdev);
 
     if (!dev->chardev) {
         fprintf(stderr, "spapr-vty: Can't create vty without a chardev!\n");
@@ -151,7 +155,7 @@ static void spapr_vty_class_init(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo spapr_vty_info = {
-    .name          = "spapr-vty",
+    .name          = TYPE_VIO_SPAPR_VTY_DEVICE,
     .parent        = TYPE_VIO_SPAPR_DEVICE,
     .instance_size = sizeof(VIOsPAPRVTYDevice),
     .class_init    = spapr_vty_class_init,
@@ -177,7 +181,7 @@ VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus)
             continue;
         }
 
-        sdev = DO_UPCAST(VIOsPAPRDevice, qdev, iter);
+        sdev = VIO_SPAPR_DEVICE(iter);
 
         /* First VTY we've found, so it is selected for now */
         if (!selected) {
diff --git a/hw/net/spapr_llan.c b/hw/net/spapr_llan.c
index 34332f2..3150add 100644
--- a/hw/net/spapr_llan.c
+++ b/hw/net/spapr_llan.c
@@ -73,6 +73,10 @@ typedef uint64_t vlan_bd_t;
 #define VLAN_RX_BDS_OFF      16
 #define VLAN_MAX_BUFS        ((SPAPR_TCE_PAGE_SIZE - VLAN_RX_BDS_OFF) / 8)
 
+#define TYPE_VIO_SPAPR_VLAN_DEVICE "spapr-vlan"
+#define VIO_SPAPR_VLAN_DEVICE(obj) \
+     OBJECT_CHECK(VIOsPAPRVLANDevice, (obj), TYPE_VIO_SPAPR_VLAN_DEVICE)
+
 typedef struct VIOsPAPRVLANDevice {
     VIOsPAPRDevice sdev;
     NICConf nicconf;
@@ -93,8 +97,8 @@ static int spapr_vlan_can_receive(NetClientState *nc)
 static ssize_t spapr_vlan_receive(NetClientState *nc, const uint8_t *buf,
                                   size_t size)
 {
-    VIOsPAPRDevice *sdev = qemu_get_nic_opaque(nc);
-    VIOsPAPRVLANDevice *dev = (VIOsPAPRVLANDevice *)sdev;
+    VIOsPAPRVLANDevice *dev = qemu_get_nic_opaque(nc);
+    VIOsPAPRDevice *sdev = VIO_SPAPR_DEVICE(dev);
     vlan_bd_t rxq_bd = vio_ldq(sdev, dev->buf_list + VLAN_RXQ_BD_OFF);
     vlan_bd_t bd;
     int buf_ptr = dev->use_buf_ptr;
@@ -192,7 +196,7 @@ static NetClientInfo net_spapr_vlan_info = {
 
 static void spapr_vlan_reset(VIOsPAPRDevice *sdev)
 {
-    VIOsPAPRVLANDevice *dev = DO_UPCAST(VIOsPAPRVLANDevice, sdev, sdev);
+    VIOsPAPRVLANDevice *dev = VIO_SPAPR_VLAN_DEVICE(sdev);
 
     dev->buf_list = 0;
     dev->rx_bufs = 0;
@@ -201,7 +205,7 @@ static void spapr_vlan_reset(VIOsPAPRDevice *sdev)
 
 static int spapr_vlan_init(VIOsPAPRDevice *sdev)
 {
-    VIOsPAPRVLANDevice *dev = (VIOsPAPRVLANDevice *)sdev;
+    VIOsPAPRVLANDevice *dev = VIO_SPAPR_VLAN_DEVICE(sdev);
 
     qemu_macaddr_default_if_unset(&dev->nicconf.macaddr);
 
@@ -225,7 +229,7 @@ void spapr_vlan_create(VIOsPAPRBus *bus, NICInfo *nd)
 
 static int spapr_vlan_devnode(VIOsPAPRDevice *dev, void *fdt, int node_off)
 {
-    VIOsPAPRVLANDevice *vdev = (VIOsPAPRVLANDevice *)dev;
+    VIOsPAPRVLANDevice *vdev = VIO_SPAPR_VLAN_DEVICE(dev);
     uint8_t padded_mac[8] = {0, 0};
     int ret;
 
@@ -282,7 +286,7 @@ static target_ulong h_register_logical_lan(PowerPCCPU *cpu,
     target_ulong rec_queue = args[2];
     target_ulong filter_list = args[3];
     VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
-    VIOsPAPRVLANDevice *dev = (VIOsPAPRVLANDevice *)sdev;
+    VIOsPAPRVLANDevice *dev = VIO_SPAPR_VLAN_DEVICE(sdev);
     vlan_bd_t filter_list_bd;
 
     if (!dev) {
@@ -341,7 +345,7 @@ static target_ulong h_free_logical_lan(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 {
     target_ulong reg = args[0];
     VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
-    VIOsPAPRVLANDevice *dev = (VIOsPAPRVLANDevice *)sdev;
+    VIOsPAPRVLANDevice *dev = VIO_SPAPR_VLAN_DEVICE(sdev);
 
     if (!dev) {
         return H_PARAMETER;
@@ -365,7 +369,7 @@ static target_ulong h_add_logical_lan_buffer(PowerPCCPU *cpu,
     target_ulong reg = args[0];
     target_ulong buf = args[1];
     VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
-    VIOsPAPRVLANDevice *dev = (VIOsPAPRVLANDevice *)sdev;
+    VIOsPAPRVLANDevice *dev = VIO_SPAPR_VLAN_DEVICE(sdev);
     vlan_bd_t bd;
 
     dprintf("H_ADD_LOGICAL_LAN_BUFFER(0x" TARGET_FMT_lx
@@ -413,7 +417,7 @@ static target_ulong h_send_logical_lan(PowerPCCPU *cpu, sPAPREnvironment *spapr,
     target_ulong *bufs = args + 1;
     target_ulong continue_token = args[7];
     VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
-    VIOsPAPRVLANDevice *dev = (VIOsPAPRVLANDevice *)sdev;
+    VIOsPAPRVLANDevice *dev = VIO_SPAPR_VLAN_DEVICE(sdev);
     unsigned total_len;
     uint8_t *lbuf, *p;
     int i, nbufs;
@@ -511,7 +515,7 @@ static void spapr_vlan_class_init(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo spapr_vlan_info = {
-    .name          = "spapr-vlan",
+    .name          = TYPE_VIO_SPAPR_VLAN_DEVICE,
     .parent        = TYPE_VIO_SPAPR_DEVICE,
     .instance_size = sizeof(VIOsPAPRVLANDevice),
     .class_init    = spapr_vlan_class_init,
diff --git a/hw/nvram/spapr_nvram.c b/hw/nvram/spapr_nvram.c
index 0cc6cba..1eb05c9 100644
--- a/hw/nvram/spapr_nvram.c
+++ b/hw/nvram/spapr_nvram.c
@@ -36,6 +36,10 @@ typedef struct sPAPRNVRAM {
     BlockDriverState *drive;
 } sPAPRNVRAM;
 
+#define TYPE_VIO_SPAPR_NVRAM "spapr-nvram"
+#define VIO_SPAPR_NVRAM(obj) \
+     OBJECT_CHECK(sPAPRNVRAM, (obj), TYPE_VIO_SPAPR_NVRAM)
+
 #define MIN_NVRAM_SIZE 8192
 #define DEFAULT_NVRAM_SIZE 65536
 #define MAX_NVRAM_SIZE (UINT16_MAX * 16)
@@ -134,7 +138,7 @@ static void rtas_nvram_store(sPAPREnvironment *spapr,
 
 static int spapr_nvram_init(VIOsPAPRDevice *dev)
 {
-    sPAPRNVRAM *nvram = (sPAPRNVRAM *)dev;
+    sPAPRNVRAM *nvram = VIO_SPAPR_NVRAM(dev);
 
     if (nvram->drive) {
         nvram->size = bdrv_getlength(nvram->drive);
@@ -157,7 +161,7 @@ static int spapr_nvram_init(VIOsPAPRDevice *dev)
 
 static int spapr_nvram_devnode(VIOsPAPRDevice *dev, void *fdt, int node_off)
 {
-    sPAPRNVRAM *nvram = (sPAPRNVRAM *)dev;
+    sPAPRNVRAM *nvram = VIO_SPAPR_NVRAM(dev);
 
     return fdt_setprop_cell(fdt, node_off, "#bytes", nvram->size);
 }
@@ -182,7 +186,7 @@ static void spapr_nvram_class_init(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo spapr_nvram_type_info = {
-    .name          = "spapr-nvram",
+    .name          = TYPE_VIO_SPAPR_NVRAM,
     .parent        = TYPE_VIO_SPAPR_DEVICE,
     .instance_size = sizeof(sPAPRNVRAM),
     .class_init    = spapr_nvram_class_init,
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
index 4dbc315..ccc794d 100644
--- a/hw/ppc/spapr_vio.c
+++ b/hw/ppc/spapr_vio.c
@@ -379,7 +379,7 @@ static VIOsPAPRDevice *reg_conflict(VIOsPAPRDevice *dev)
      * the given dev might already be in the list.
      */
     QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
-        other = DO_UPCAST(VIOsPAPRDevice, qdev, kid->child);
+        other = VIO_SPAPR_DEVICE(kid->child);
 
         if (other != dev && other->reg == dev->reg) {
             return other;
@@ -391,7 +391,7 @@ static VIOsPAPRDevice *reg_conflict(VIOsPAPRDevice *dev)
 
 static void spapr_vio_busdev_reset(DeviceState *qdev)
 {
-    VIOsPAPRDevice *dev = DO_UPCAST(VIOsPAPRDevice, qdev, qdev);
+    VIOsPAPRDevice *dev = VIO_SPAPR_DEVICE(qdev);
     VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
 
     /* Shut down the request queue and TCEs if necessary */
diff --git a/hw/scsi/spapr_vscsi.c b/hw/scsi/spapr_vscsi.c
index 999a463..3d322d5 100644
--- a/hw/scsi/spapr_vscsi.c
+++ b/hw/scsi/spapr_vscsi.c
@@ -91,6 +91,9 @@ typedef struct vscsi_req {
     int                     total_desc;
 } vscsi_req;
 
+#define TYPE_VIO_SPAPR_VSCSI_DEVICE "spapr-vscsi"
+#define VIO_SPAPR_VSCSI_DEVICE(obj) \
+     OBJECT_CHECK(VSCSIState, (obj), TYPE_VIO_SPAPR_VSCSI_DEVICE)
 
 typedef struct {
     VIOsPAPRDevice vdev;
@@ -461,7 +464,7 @@ static int vscsi_preprocess_desc(vscsi_req *req)
 /* Callback to indicate that the SCSI layer has completed a transfer.  */
 static void vscsi_transfer_data(SCSIRequest *sreq, uint32_t len)
 {
-    VSCSIState *s = DO_UPCAST(VSCSIState, vdev.qdev, sreq->bus->qbus.parent);
+    VSCSIState *s = VIO_SPAPR_VSCSI_DEVICE(sreq->bus->qbus.parent);
     vscsi_req *req = sreq->hba_private;
     uint8_t *buf;
     int rc = 0;
@@ -492,7 +495,7 @@ static void vscsi_transfer_data(SCSIRequest *sreq, uint32_t len)
 /* Callback to indicate that the SCSI layer has completed a transfer.  */
 static void vscsi_command_complete(SCSIRequest *sreq, uint32_t status, size_t resid)
 {
-    VSCSIState *s = DO_UPCAST(VSCSIState, vdev.qdev, sreq->bus->qbus.parent);
+    VSCSIState *s = VIO_SPAPR_VSCSI_DEVICE(sreq->bus->qbus.parent);
     vscsi_req *req = sreq->hba_private;
     int32_t res_in = 0, res_out = 0;
 
@@ -827,7 +830,7 @@ static void vscsi_got_payload(VSCSIState *s, vscsi_crq *crq)
 
 static int vscsi_do_crq(struct VIOsPAPRDevice *dev, uint8_t *crq_data)
 {
-    VSCSIState *s = DO_UPCAST(VSCSIState, vdev, dev);
+    VSCSIState *s = VIO_SPAPR_VSCSI_DEVICE(dev);
     vscsi_crq crq;
 
     memcpy(crq.raw, crq_data, 16);
@@ -897,7 +900,7 @@ static const struct SCSIBusInfo vscsi_scsi_info = {
 
 static void spapr_vscsi_reset(VIOsPAPRDevice *dev)
 {
-    VSCSIState *s = DO_UPCAST(VSCSIState, vdev, dev);
+    VSCSIState *s = VIO_SPAPR_VSCSI_DEVICE(dev);
     int i;
 
     memset(s->reqs, 0, sizeof(s->reqs));
@@ -908,7 +911,7 @@ static void spapr_vscsi_reset(VIOsPAPRDevice *dev)
 
 static int spapr_vscsi_init(VIOsPAPRDevice *dev)
 {
-    VSCSIState *s = DO_UPCAST(VSCSIState, vdev, dev);
+    VSCSIState *s = VIO_SPAPR_VSCSI_DEVICE(dev);
 
     dev->crq.SendFunc = vscsi_do_crq;
 
@@ -968,7 +971,7 @@ static void spapr_vscsi_class_init(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo spapr_vscsi_info = {
-    .name          = "spapr-vscsi",
+    .name          = TYPE_VIO_SPAPR_VSCSI_DEVICE,
     .parent        = TYPE_VIO_SPAPR_DEVICE,
     .instance_size = sizeof(VSCSIState),
     .class_init    = spapr_vscsi_class_init,
commit 9b00ea4906a618756bcd10f09d432780eab87782
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Sun Apr 7 19:08:22 2013 +0000

    target-ppc: Synchronize VPA state with KVM
    
    For PAPR guests, KVM tracks the various areas registered with the
    H_REGISTER_VPA hypercall.  For full emulation, of course, these are tracked
    within qemu.  At present these values are not synchronized.  This is a
    problem for reset (qemu's reset of the VPA address is not pushed to KVM)
    and will also be a problem for savevm / migration.
    
    The kernel now supports accessing the VPA state via the ONE_REG interface,
    this patch adds code to qemu to use that interface to keep the qemu and
    KVM ideas of the VPA state synchronized.
    
    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 4e8f448..725071e 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -66,6 +66,7 @@ static int cap_hior;
 static int cap_one_reg;
 static int cap_epr;
 static int cap_ppc_watchdog;
+static int cap_papr;
 
 /* 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
@@ -100,6 +101,8 @@ int kvm_arch_init(KVMState *s)
     cap_hior = kvm_check_extension(s, KVM_CAP_PPC_HIOR);
     cap_epr = kvm_check_extension(s, KVM_CAP_PPC_EPR);
     cap_ppc_watchdog = kvm_check_extension(s, KVM_CAP_PPC_BOOKE_WATCHDOG);
+    /* Note: we don't set cap_papr here, because this capability is
+     * only activated after this by kvmppc_set_papr() */
 
     if (!cap_interrupt_level) {
         fprintf(stderr, "KVM: Couldn't find level irq capability. Expect the "
@@ -657,6 +660,103 @@ static int kvm_get_fp(CPUState *cs)
     return 0;
 }
 
+#if defined(TARGET_PPC64)
+static int kvm_get_vpa(CPUState *cs)
+{
+    PowerPCCPU *cpu = POWERPC_CPU(cs);
+    CPUPPCState *env = &cpu->env;
+    struct kvm_one_reg reg;
+    int ret;
+
+    reg.id = KVM_REG_PPC_VPA_ADDR;
+    reg.addr = (uintptr_t)&env->vpa_addr;
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
+    if (ret < 0) {
+        dprintf("Unable to get VPA address from KVM: %s\n", strerror(errno));
+        return ret;
+    }
+
+    assert((uintptr_t)&env->slb_shadow_size
+           == ((uintptr_t)&env->slb_shadow_addr + 8));
+    reg.id = KVM_REG_PPC_VPA_SLB;
+    reg.addr = (uintptr_t)&env->slb_shadow_addr;
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
+    if (ret < 0) {
+        dprintf("Unable to get SLB shadow state from KVM: %s\n",
+                strerror(errno));
+        return ret;
+    }
+
+    assert((uintptr_t)&env->dtl_size == ((uintptr_t)&env->dtl_addr + 8));
+    reg.id = KVM_REG_PPC_VPA_DTL;
+    reg.addr = (uintptr_t)&env->dtl_addr;
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
+    if (ret < 0) {
+        dprintf("Unable to get dispatch trace log state from KVM: %s\n",
+                strerror(errno));
+        return ret;
+    }
+
+    return 0;
+}
+
+static int kvm_put_vpa(CPUState *cs)
+{
+    PowerPCCPU *cpu = POWERPC_CPU(cs);
+    CPUPPCState *env = &cpu->env;
+    struct kvm_one_reg reg;
+    int ret;
+
+    /* SLB shadow or DTL can't be registered unless a master VPA is
+     * registered.  That means when restoring state, if a VPA *is*
+     * registered, we need to set that up first.  If not, we need to
+     * deregister the others before deregistering the master VPA */
+    assert(env->vpa_addr || !(env->slb_shadow_addr || env->dtl_addr));
+
+    if (env->vpa_addr) {
+        reg.id = KVM_REG_PPC_VPA_ADDR;
+        reg.addr = (uintptr_t)&env->vpa_addr;
+        ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
+        if (ret < 0) {
+            dprintf("Unable to set VPA address to KVM: %s\n", strerror(errno));
+            return ret;
+        }
+    }
+
+    assert((uintptr_t)&env->slb_shadow_size
+           == ((uintptr_t)&env->slb_shadow_addr + 8));
+    reg.id = KVM_REG_PPC_VPA_SLB;
+    reg.addr = (uintptr_t)&env->slb_shadow_addr;
+    ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
+    if (ret < 0) {
+        dprintf("Unable to set SLB shadow state to KVM: %s\n", strerror(errno));
+        return ret;
+    }
+
+    assert((uintptr_t)&env->dtl_size == ((uintptr_t)&env->dtl_addr + 8));
+    reg.id = KVM_REG_PPC_VPA_DTL;
+    reg.addr = (uintptr_t)&env->dtl_addr;
+    ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
+    if (ret < 0) {
+        dprintf("Unable to set dispatch trace log state to KVM: %s\n",
+                strerror(errno));
+        return ret;
+    }
+
+    if (!env->vpa_addr) {
+        reg.id = KVM_REG_PPC_VPA_ADDR;
+        reg.addr = (uintptr_t)&env->vpa_addr;
+        ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
+        if (ret < 0) {
+            dprintf("Unable to set VPA address to KVM: %s\n", strerror(errno));
+            return ret;
+        }
+    }
+
+    return 0;
+}
+#endif /* TARGET_PPC64 */
+
 int kvm_arch_put_registers(CPUState *cs, int level)
 {
     PowerPCCPU *cpu = POWERPC_CPU(cs);
@@ -757,6 +857,14 @@ int kvm_arch_put_registers(CPUState *cs, int level)
                 kvm_put_one_spr(cs, id, i);
             }
         }
+
+#ifdef TARGET_PPC64
+        if (cap_papr) {
+            if (kvm_put_vpa(cs) < 0) {
+                dprintf("Warning: Unable to set VPA information to KVM\n");
+            }
+        }
+#endif /* TARGET_PPC64 */
     }
 
     return ret;
@@ -958,6 +1066,14 @@ int kvm_arch_get_registers(CPUState *cs)
                 kvm_get_one_spr(cs, id, i);
             }
         }
+
+#ifdef TARGET_PPC64
+        if (cap_papr) {
+            if (kvm_get_vpa(cs) < 0) {
+                dprintf("Warning: Unable to get VPA information from KVM\n");
+            }
+        }
+#endif
     }
 
     return 0;
@@ -1377,6 +1493,10 @@ void kvmppc_set_papr(PowerPCCPU *cpu)
     if (ret) {
         cpu_abort(env, "This KVM version does not support PAPR\n");
     }
+
+    /* Update the capability flag so we sync the right information
+     * with kvm */
+    cap_papr = 1;
 }
 
 void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy)
commit e03c902cb617414dae49d77a810f6957ff7affac
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Sun Apr 7 19:08:21 2013 +0000

    pseries: Fix some small errors in XICS logic
    
    Under certain circumstances the emulation for the pseries "XICS" interrupt
    controller was clearing a pending interrupt from the XISR register, without
    also clearing the corresponding priority variable.  This will cause
    problems later when can trigger sanity checks in the under-development
    in-kernel XICS implementation.
    
    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/xics.c b/hw/ppc/xics.c
index 8e1e85e..1b25075 100644
--- a/hw/ppc/xics.c
+++ b/hw/ppc/xics.c
@@ -101,6 +101,7 @@ static void icp_set_cppr(struct icp_state *icp, int server, uint8_t cppr)
         if (XISR(ss) && (cppr <= ss->pending_priority)) {
             old_xisr = XISR(ss);
             ss->xirr &= ~XISR_MASK; /* Clear XISR */
+            ss->pending_priority = 0xff;
             qemu_irq_lower(ss->output);
             ics_reject(icp->ics, old_xisr);
         }
@@ -127,6 +128,7 @@ static uint32_t icp_accept(struct icp_server_state *ss)
 
     qemu_irq_lower(ss->output);
     ss->xirr = ss->pending_priority << 24;
+    ss->pending_priority = 0xff;
 
     trace_xics_icp_accept(xirr, ss->xirr);
 
commit 702763fa322ea69dde92517735507e0ac3879b5d
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Sun Apr 7 19:08:20 2013 +0000

    target-ppc: Add more stubs for POWER7 PMU registers
    
    In addition to the performance monitor registers found on nearly all
    6xx chips, the POWER7 has two additional counters (PMC5 & PMC6) and an
    extra control register (MMCRA).  This patch adds stub support for them to
    qemu - the registers won't do anything, but with this change won't cause
    illegal instruction traps accessing them.  They're also registered with
    their ONE_REG ids, so their value will be kept in sync with KVM where
    appropriate.
    
    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 99ebf7e..b8b09b9 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1445,6 +1445,7 @@ static inline void cpu_clone_regs(CPUPPCState *env, target_ulong newsp)
 #define SPR_PERF2             (0x302)
 #define SPR_RCPU_MI_RBA2      (0x302)
 #define SPR_MPC_MI_AP         (0x302)
+#define SPR_MMCRA             (0x302)
 #define SPR_PERF3             (0x303)
 #define SPR_RCPU_MI_RBA3      (0x303)
 #define SPR_MPC_MI_EPN        (0x303)
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 769f5fd..b0e3536 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -6977,6 +6977,18 @@ static void init_proc_POWER7 (CPUPPCState *env)
                      SPR_NOACCESS, SPR_NOACCESS,
                      &spr_read_generic, &spr_write_generic,
                      KVM_REG_PPC_DSCR, 0x00000000);
+    spr_register_kvm(env, SPR_MMCRA, "SPR_MMCRA",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     KVM_REG_PPC_MMCRA, 0x00000000);
+    spr_register_kvm(env, SPR_PMC5, "SPR_PMC5",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     KVM_REG_PPC_PMC5, 0x00000000);
+    spr_register_kvm(env, SPR_PMC6, "SPR_PMC6",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     KVM_REG_PPC_PMC6, 0x00000000);
 #endif /* !CONFIG_USER_ONLY */
     /* Memory management */
     /* XXX : not implemented */
commit 0cbad81f70546b58f08de3225f1eca7a8b869b09
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Sun Apr 7 19:08:19 2013 +0000

    pseries: Fixes and enhancements to L1 cache properties
    
    PAPR requires that the device tree's CPU nodes have several properties
    with information about the L1 cache.  We already create two of these
    properties, but with incorrect names - "[id]cache-block-size" instead
    of "[id]-cache-block-size" (note the extra hyphen).
    
    We were also missing some of the required cache properties.  This
    patch adds the [id]-cache-line-size properties (which have the same
    values as the block size properties in all current cases).  We also
    add the [id]-cache-size properties.
    
    Adding the cache sizes requires some extra infrastructure in the
    general target-ppc code to (optionally) set the cache sizes for
    various CPUs.  The CPU family descriptions in translate_init.c can set
    these sizes - this patch adds correct information for POWER7, I'm
    leaving other CPU types to people who have a physical example to
    verify against.  In addition, for -cpu host we take the values
    advertised by the host (if available) and use those to override the
    information based on PVR.
    
    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 e35c26f..c96ac81 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -308,6 +308,7 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
 
     for (env = first_cpu; env != NULL; env = env->next_cpu) {
         CPUState *cpu = CPU(ppc_env_get_cpu(env));
+        PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
         int index = cpu->cpu_index;
         uint32_t servers_prop[smp_threads];
         uint32_t gservers_prop[smp_threads * 2];
@@ -333,10 +334,26 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
         _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",
+        _FDT((fdt_property_cell(fdt, "d-cache-block-size",
                                 env->dcache_line_size)));
-        _FDT((fdt_property_cell(fdt, "icache-block-size",
+        _FDT((fdt_property_cell(fdt, "d-cache-line-size",
+                                env->dcache_line_size)));
+        _FDT((fdt_property_cell(fdt, "i-cache-block-size",
+                                env->icache_line_size)));
+        _FDT((fdt_property_cell(fdt, "i-cache-line-size",
                                 env->icache_line_size)));
+
+        if (pcc->l1_dcache_size) {
+            _FDT((fdt_property_cell(fdt, "d-cache-size", pcc->l1_dcache_size)));
+        } else {
+            fprintf(stderr, "Warning: Unknown L1 dcache size for cpu\n");
+        }
+        if (pcc->l1_icache_size) {
+            _FDT((fdt_property_cell(fdt, "i-cache-size", pcc->l1_icache_size)));
+        } else {
+            fprintf(stderr, "Warning: Unknown L1 icache size for cpu\n");
+        }
+
         _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)));
diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h
index c27cef7..eb03a00 100644
--- a/target-ppc/cpu-qom.h
+++ b/target-ppc/cpu-qom.h
@@ -63,6 +63,7 @@ typedef struct PowerPCCPUClass {
     powerpc_input_t bus_model;
     uint32_t flags;
     int bfd_mach;
+    uint32_t l1_dcache_size, l1_icache_size;
 #if defined(TARGET_PPC64)
     const struct ppc_segment_page_sizes *sps;
 #endif
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index a1fa8d3..4e8f448 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -1603,6 +1603,8 @@ static void kvmppc_host_cpu_class_init(ObjectClass *oc, void *data)
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
     uint32_t vmx = kvmppc_get_vmx();
     uint32_t dfp = kvmppc_get_dfp();
+    uint32_t dcache_size = kvmppc_read_int_cpu_dt("d-cache-size");
+    uint32_t icache_size = kvmppc_read_int_cpu_dt("i-cache-size");
 
     /* Now fix up the class with information we can query from the host */
 
@@ -1615,6 +1617,14 @@ static void kvmppc_host_cpu_class_init(ObjectClass *oc, void *data)
         /* Only override when we know what the host supports */
         alter_insns(&pcc->insns_flags2, PPC2_DFP, dfp);
     }
+
+    if (dcache_size != -1) {
+        pcc->l1_dcache_size = dcache_size;
+    }
+
+    if (icache_size != -1) {
+        pcc->l1_icache_size = icache_size;
+    }
 }
 
 int kvmppc_fixup_cpu(PowerPCCPU *cpu)
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index a9bacd2..769f5fd 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7004,6 +7004,7 @@ static void init_proc_POWER7 (CPUPPCState *env)
     init_excp_POWER7(env);
     env->dcache_line_size = 128;
     env->icache_line_size = 128;
+
     /* Allocate hardware IRQ controller */
     ppcPOWER7_irq_init(env);
     /* Can't find information on what this should be on reset.  This
@@ -7041,6 +7042,8 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
     pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
                  POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
                  POWERPC_FLAG_BUS_CLK | POWERPC_FLAG_CFAR;
+    pcc->l1_dcache_size = 0x8000;
+    pcc->l1_icache_size = 0x8000;
 }
 #endif /* defined (TARGET_PPC64) */
 
commit f36951c19f15f3c053a31234bd2c297d86c1a052
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Sun Apr 7 19:08:18 2013 +0000

    pseries: Fix incorrect calculation of RMA size in certain configurations
    
    For the pseries machine, we need to advertise to the guest the size of its
    RMA - that is the amount of memory it can access with the MMU off.  For HV
    KVM, this is constrained by the hardware limitations on the virtual RMA of
    one hash PTE per PTE group in the hash page table.  We already had code to
    calculate this, but it was assuming the VRMA page size was the same as the
    (host) backing page size for guest RAM.
    
    In the case of a host kernel configured for 64k base page size, but running
    on hardware (or firmware) which only allows 4k pages, the hose will do all
    its allocations with a 64k page size, but still use 4k hardware pages for
    actual mappings.  Usually that's transparent to things running under the
    host, but in the case of the maximum VRMA size it's not.
    
    This patch refines the RMA size calculation to instead use the largest
    available hardware page size (as reported by the SMMU_INFO call) which is
    less than or equal to the backing page size.  This now gives the correct
    RMA size in all cases I've tested.
    
    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 759983d..a1fa8d3 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -1446,11 +1446,35 @@ off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem)
 
 uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift)
 {
+    struct kvm_ppc_smmu_info info;
+    long rampagesize, best_page_shift;
+    int i;
+
     if (cap_ppc_rma >= 2) {
         return current_size;
     }
+
+    /* Find the largest hardware supported page size that's less than
+     * or equal to the (logical) backing page size of guest RAM */
+    kvm_get_smmu_info(ppc_env_get_cpu(first_cpu), &info);
+    rampagesize = getrampagesize();
+    best_page_shift = 0;
+
+    for (i = 0; i < KVM_PPC_PAGE_SIZES_MAX_SZ; i++) {
+        struct kvm_ppc_one_seg_page_size *sps = &info.sps[i];
+
+        if (!sps->page_shift) {
+            continue;
+        }
+
+        if ((sps->page_shift > best_page_shift)
+            && ((1UL << sps->page_shift) <= rampagesize)) {
+            best_page_shift = sps->page_shift;
+        }
+    }
+
     return MIN(current_size,
-               getrampagesize() << (hash_shift - 7));
+               1ULL << (best_page_shift + hash_shift - 7));
 }
 #endif
 
commit c8ff5daa09516272117eb23cd00da5d188ba73eb
Author: Alexander Graf <agraf at suse.de>
Date:   Fri Apr 19 02:35:08 2013 +0200

    PPC: Fix compile with profiling enabled
    
    When using profiling, we rely on profile_getclock() being available
    at our disposal. Somehow that function got moved from an indirect
    include we used to have in translate-init.c, so that we were now
    left not properly compiling anymore.
    
    Add an explicit include to timer.h which defines profile_getclock,
    so that we can compile again.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/translate-all.c b/translate-all.c
index d04a116..da93608 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -55,6 +55,7 @@
 #else
 #include "exec/address-spaces.h"
 #endif
+#include "qemu/timer.h"
 
 #include "exec/cputlb.h"
 #include "translate-all.h"
commit 20f649dd22dae13301c906c27a8768a318591ae8
Author: Alexander Graf <agraf at suse.de>
Date:   Thu Apr 4 18:45:07 2013 +0200

    PPC: mac newworld: fix cpu NIP reset value
    
    On -M mac99, we can run 970 CPUs. However, these CPUs define the initial
    instruction pointer they start execution at as part of their bootup protocol,
    so effectively it's up to the board to decide where they start.
    
    This went unnoticed, because they used to boot at the same location our flash
    was mapped to, but due to the recent reset changes our 970 CPUs want to reset
    to 0x100 now, which is always a 0 instruction.
    
    Set the initial IP to something reasonable for -M mac99.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Reviewed-by: Fabien Chouteau <chouteau at adacore.com>

diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c
index 4a9b883..ce44e95 100644
--- a/hw/ppc/mac_newworld.c
+++ b/hw/ppc/mac_newworld.c
@@ -126,6 +126,8 @@ static void ppc_core99_reset(void *opaque)
     PowerPCCPU *cpu = opaque;
 
     cpu_reset(CPU(cpu));
+    /* 970 CPUs want to get their initial IP as part of their boot protocol */
+    cpu->env.nip = PROM_ADDR + 0x100;
 }
 
 /* PowerPC Mac99 hardware initialisation */
commit 31f2cb8ff415e376b05335dcf63ba38c00f29e5e
Author: Bharat Bhushan <r65777 at freescale.com>
Date:   Sun Feb 24 18:16:21 2013 +0000

    Enable kvm emulated watchdog
    
    Enable the KVM emulated watchdog if KVM supports (use the
    capability enablement in watchdog handler). Also watchdog exit
    (KVM_EXIT_WATCHDOG) handling is added.
    Watchdog state machine is cleared whenever VM state changes to running.
    This is to handle the cases like return from debug halt etc.
    
    Signed-off-by: Bharat Bhushan <bharat.bhushan at freescale.com>
    [agraf: rebase to current code base, fix non-kvm cases]
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/ppc/ppc_booke.c b/hw/ppc/ppc_booke.c
index 585f53b..e41b036 100644
--- a/hw/ppc/ppc_booke.c
+++ b/hw/ppc/ppc_booke.c
@@ -28,6 +28,7 @@
 #include "hw/timer/m48t59.h"
 #include "qemu/log.h"
 #include "hw/loader.h"
+#include "kvm_ppc.h"
 
 
 /* Timer Control Register */
@@ -211,6 +212,7 @@ void store_booke_tsr(CPUPPCState *env, target_ulong val)
     PowerPCCPU *cpu = ppc_env_get_cpu(env);
 
     env->spr[SPR_BOOKE_TSR] &= ~val;
+    kvmppc_clear_tsr_bits(cpu, val);
     booke_update_irq(cpu);
 }
 
@@ -222,6 +224,7 @@ void store_booke_tcr(CPUPPCState *env, target_ulong val)
 
     tb_env = env->tb_env;
     env->spr[SPR_BOOKE_TCR] = val;
+    kvmppc_set_tcr(cpu);
 
     booke_update_irq(cpu);
 
@@ -234,7 +237,6 @@ void store_booke_tcr(CPUPPCState *env, target_ulong val)
                              booke_get_wdt_target(env, tb_env),
                              &booke_timer->wdt_next,
                              booke_timer->wdt_timer);
-
 }
 
 static void ppc_booke_timer_reset_handle(void *opaque)
@@ -242,16 +244,39 @@ 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;
+    store_booke_tcr(env, 0);
+    store_booke_tsr(env, -1);
+}
 
-    booke_update_irq(cpu);
+/*
+ * This function will be called whenever the CPU state changes.
+ * CPU states are defined "typedef enum RunState".
+ * Regarding timer, When CPU state changes to running after debug halt
+ * or similar cases which takes time then in between final watchdog
+ * expiry happenes. This will cause exit to QEMU and configured watchdog
+ * action will be taken. To avoid this we always clear the watchdog state when
+ * state changes to running.
+ */
+static void cpu_state_change_handler(void *opaque, int running, RunState state)
+{
+    PowerPCCPU *cpu = opaque;
+    CPUPPCState *env = &cpu->env;
+
+    if (!running) {
+        return;
+    }
+
+    /*
+     * Clear watchdog interrupt condition by clearing TSR.
+     */
+    store_booke_tsr(env, TSR_ENW | TSR_WIS | TSR_WRS_MASK);
 }
 
 void ppc_booke_timers_init(PowerPCCPU *cpu, uint32_t freq, uint32_t flags)
 {
     ppc_tb_t *tb_env;
     booke_timer_t *booke_timer;
+    int ret = 0;
 
     tb_env      = g_malloc0(sizeof(ppc_tb_t));
     booke_timer = g_malloc0(sizeof(booke_timer_t));
@@ -269,5 +294,17 @@ void ppc_booke_timers_init(PowerPCCPU *cpu, uint32_t freq, uint32_t flags)
     booke_timer->wdt_timer =
         qemu_new_timer_ns(vm_clock, &booke_wdt_cb, cpu);
 
+    ret = kvmppc_booke_watchdog_enable(cpu);
+
+    if (ret) {
+        /* TODO: Start the QEMU emulated watchdog if not running on KVM.
+         * Also start the QEMU emulated watchdog if KVM does not support
+         * emulated watchdog or somehow it is not enabled (supported but
+         * not enabled is though some bug and requires debugging :)).
+         */
+    }
+
+    qemu_add_vm_change_state_handler(cpu_state_change_handler, cpu);
+
     qemu_register_reset(ppc_booke_timer_reset_handle, cpu);
 }
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index f2658bb..759983d 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -37,6 +37,7 @@
 #include "hw/sysbus.h"
 #include "hw/ppc/spapr.h"
 #include "hw/ppc/spapr_vio.h"
+#include "sysemu/watchdog.h"
 
 //#define DEBUG_KVM
 
@@ -64,6 +65,7 @@ static int cap_spapr_tce;
 static int cap_hior;
 static int cap_one_reg;
 static int cap_epr;
+static int cap_ppc_watchdog;
 
 /* 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
@@ -97,6 +99,7 @@ int kvm_arch_init(KVMState *s)
     cap_one_reg = kvm_check_extension(s, KVM_CAP_ONE_REG);
     cap_hior = kvm_check_extension(s, KVM_CAP_PPC_HIOR);
     cap_epr = kvm_check_extension(s, KVM_CAP_PPC_EPR);
+    cap_ppc_watchdog = kvm_check_extension(s, KVM_CAP_PPC_BOOKE_WATCHDOG);
 
     if (!cap_interrupt_level) {
         fprintf(stderr, "KVM: Couldn't find level irq capability. Expect the "
@@ -1094,6 +1097,12 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
         run->epr.epr = ldl_phys(env->mpic_iack);
         ret = 0;
         break;
+    case KVM_EXIT_WATCHDOG:
+        dprintf("handle watchdog expiry\n");
+        watchdog_perform_action();
+        ret = 0;
+        break;
+
     default:
         fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
         ret = -1;
@@ -1103,6 +1112,71 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
     return ret;
 }
 
+int kvmppc_or_tsr_bits(PowerPCCPU *cpu, uint32_t tsr_bits)
+{
+    CPUState *cs = CPU(cpu);
+    uint32_t bits = tsr_bits;
+    struct kvm_one_reg reg = {
+        .id = KVM_REG_PPC_OR_TSR,
+        .addr = (uintptr_t) &bits,
+    };
+
+    return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
+}
+
+int kvmppc_clear_tsr_bits(PowerPCCPU *cpu, uint32_t tsr_bits)
+{
+
+    CPUState *cs = CPU(cpu);
+    uint32_t bits = tsr_bits;
+    struct kvm_one_reg reg = {
+        .id = KVM_REG_PPC_CLEAR_TSR,
+        .addr = (uintptr_t) &bits,
+    };
+
+    return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
+}
+
+int kvmppc_set_tcr(PowerPCCPU *cpu)
+{
+    CPUState *cs = CPU(cpu);
+    CPUPPCState *env = &cpu->env;
+    uint32_t tcr = env->spr[SPR_BOOKE_TCR];
+
+    struct kvm_one_reg reg = {
+        .id = KVM_REG_PPC_TCR,
+        .addr = (uintptr_t) &tcr,
+    };
+
+    return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
+}
+
+int kvmppc_booke_watchdog_enable(PowerPCCPU *cpu)
+{
+    CPUState *cs = CPU(cpu);
+    struct kvm_enable_cap encap = {};
+    int ret;
+
+    if (!kvm_enabled()) {
+        return -1;
+    }
+
+    if (!cap_ppc_watchdog) {
+        printf("warning: KVM does not support watchdog");
+        return -1;
+    }
+
+    encap.cap = KVM_CAP_PPC_BOOKE_WATCHDOG;
+    ret = kvm_vcpu_ioctl(cs, KVM_ENABLE_CAP, &encap);
+    if (ret < 0) {
+        fprintf(stderr, "%s: couldn't enable KVM_CAP_PPC_BOOKE_WATCHDOG: %s\n",
+                __func__, strerror(-ret));
+        return ret;
+    }
+
+    return ret;
+}
+
 static int read_cpuinfo(const char *field, char *value, int len)
 {
     FILE *f;
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
index 600d632..771cfbe 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -25,6 +25,10 @@ int kvmppc_set_interrupt(PowerPCCPU *cpu, int irq, int level);
 void kvmppc_set_papr(PowerPCCPU *cpu);
 void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy);
 int kvmppc_smt_threads(void);
+int kvmppc_clear_tsr_bits(PowerPCCPU *cpu, uint32_t tsr_bits);
+int kvmppc_or_tsr_bits(PowerPCCPU *cpu, uint32_t tsr_bits);
+int kvmppc_set_tcr(PowerPCCPU *cpu);
+int kvmppc_booke_watchdog_enable(PowerPCCPU *cpu);
 #ifndef CONFIG_USER_ONLY
 off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem);
 void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd);
@@ -90,6 +94,26 @@ static inline int kvmppc_smt_threads(void)
     return 1;
 }
 
+static inline int kvmppc_or_tsr_bits(PowerPCCPU *cpu, uint32_t tsr_bits)
+{
+    return 0;
+}
+
+static inline int kvmppc_clear_tsr_bits(PowerPCCPU *cpu, uint32_t tsr_bits)
+{
+    return 0;
+}
+
+static inline int kvmppc_set_tcr(PowerPCCPU *cpu)
+{
+    return 0;
+}
+
+static inline int kvmppc_booke_watchdog_enable(PowerPCCPU *cpu)
+{
+    return -1;
+}
+
 #ifndef CONFIG_USER_ONLY
 static inline off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem)
 {
commit cae7f586419ad261f55ef8700bf8f3fa5b4879d4
Author: Alexander Graf <agraf at suse.de>
Date:   Thu Apr 4 15:40:44 2013 +0200

    linux-headers: Update to kvm/queue
    
    Based on kvm.git queue branch with commit e1e2e605.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/linux-headers/asm-powerpc/kvm.h b/linux-headers/asm-powerpc/kvm.h
index 16064d0..ef072b1 100644
--- a/linux-headers/asm-powerpc/kvm.h
+++ b/linux-headers/asm-powerpc/kvm.h
@@ -417,4 +417,9 @@ struct kvm_get_htab_header {
 #define KVM_REG_PPC_EPCR	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x85)
 #define KVM_REG_PPC_EPR		(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x86)
 
+/* Timer Status Register OR/CLEAR interface */
+#define KVM_REG_PPC_OR_TSR	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x87)
+#define KVM_REG_PPC_CLEAR_TSR	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x88)
+#define KVM_REG_PPC_TCR		(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x89)
+#define KVM_REG_PPC_TSR		(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x8a)
 #endif /* __LINUX_KVM_POWERPC_H */
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index caca979..eb02d8a 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -449,12 +449,15 @@ enum {
 	kvm_ioeventfd_flag_nr_datamatch,
 	kvm_ioeventfd_flag_nr_pio,
 	kvm_ioeventfd_flag_nr_deassign,
+	kvm_ioeventfd_flag_nr_virtio_ccw_notify,
 	kvm_ioeventfd_flag_nr_max,
 };
 
 #define KVM_IOEVENTFD_FLAG_DATAMATCH (1 << kvm_ioeventfd_flag_nr_datamatch)
 #define KVM_IOEVENTFD_FLAG_PIO       (1 << kvm_ioeventfd_flag_nr_pio)
 #define KVM_IOEVENTFD_FLAG_DEASSIGN  (1 << kvm_ioeventfd_flag_nr_deassign)
+#define KVM_IOEVENTFD_FLAG_VIRTIO_CCW_NOTIFY \
+	(1 << kvm_ioeventfd_flag_nr_virtio_ccw_notify)
 
 #define KVM_IOEVENTFD_VALID_FLAG_MASK  ((1 << kvm_ioeventfd_flag_nr_max) - 1)
 
commit 752d634ecc74c76eb5e32db0e536d84c2d6aa3d8
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Apr 3 10:56:45 2013 +0000

    target-ppc: Fix narrow-mode add/sub carry output
    
    Broken in b5a73f8d8a57e940f9bbeb399a9e47897522ee9a, the carry itself was
    fixed in 79482e5ab38a05ca8869040b0d8b8f451f16ff62.  But we still need to
    produce the full 64-bit addition.
    
    Simplify the conditions at the top of the functions for when we need a
    new temporary.  Only plain addition is important enough to warrent avoiding
    the temporary, and the extra tcg move op that would come with it.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
    Tested-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 294ab58..362ca3a 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -768,22 +768,25 @@ static inline void gen_op_arith_add(DisasContext *ctx, TCGv ret, TCGv arg1,
 {
     TCGv t0 = ret;
 
-    if (((compute_ca && add_ca) || compute_ov)
-        && (TCGV_EQUAL(ret, arg1) || TCGV_EQUAL(ret, arg2)))  {
+    if (compute_ca || compute_ov) {
         t0 = tcg_temp_new();
     }
 
     if (compute_ca) {
         if (NARROW_MODE(ctx)) {
+            /* Caution: a non-obvious corner case of the spec is that we
+               must produce the *entire* 64-bit addition, but produce the
+               carry into bit 32.  */
             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);
+            tcg_gen_xor_tl(t1, arg1, arg2);        /* add without carry */
+            tcg_gen_add_tl(t0, arg1, arg2);
             if (add_ca) {
                 tcg_gen_add_tl(t0, t0, cpu_ca);
             }
-            tcg_gen_shri_tl(cpu_ca, t0, 32);
+            tcg_gen_xor_tl(cpu_ca, t0, t1);        /* bits changed w/ carry */
+            tcg_temp_free(t1);
+            tcg_gen_shri_tl(cpu_ca, cpu_ca, 32);   /* extract bit 32 */
+            tcg_gen_andi_tl(cpu_ca, cpu_ca, 1);
         } else {
             TCGv zero = tcg_const_tl(0);
             if (add_ca) {
@@ -1122,24 +1125,30 @@ static inline void gen_op_arith_subf(DisasContext *ctx, TCGv ret, TCGv arg1,
 {
     TCGv t0 = ret;
 
-    if (compute_ov && (TCGV_EQUAL(ret, arg1) || TCGV_EQUAL(ret, arg2)))  {
+    if (compute_ca || compute_ov) {
         t0 = tcg_temp_new();
     }
 
     if (compute_ca) {
         /* dest = ~arg1 + arg2 [+ ca].  */
         if (NARROW_MODE(ctx)) {
+            /* Caution: a non-obvious corner case of the spec is that we
+               must produce the *entire* 64-bit addition, but produce the
+               carry into bit 32.  */
             TCGv inv1 = tcg_temp_new();
+            TCGv t1 = 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);
+                tcg_gen_add_tl(t0, arg2, cpu_ca);
             } else {
-                tcg_gen_addi_tl(t0, t0, 1);
+                tcg_gen_addi_tl(t0, arg2, 1);
             }
+            tcg_gen_xor_tl(t1, arg2, inv1);         /* add without carry */
             tcg_gen_add_tl(t0, t0, inv1);
-            tcg_gen_shri_tl(cpu_ca, t0, 32);
+            tcg_gen_xor_tl(cpu_ca, t0, t1);         /* bits changes w/ carry */
+            tcg_temp_free(t1);
+            tcg_gen_shri_tl(cpu_ca, cpu_ca, 32);    /* extract bit 32 */
+            tcg_gen_andi_tl(cpu_ca, cpu_ca, 1);
         } else if (add_ca) {
             TCGv zero, inv1 = tcg_temp_new();
             tcg_gen_not_tl(inv1, arg1);
commit 2bc173224adc0fc318f2bd6fcf65dfdbc7d51123
Author: Fabien Chouteau <chouteau at adacore.com>
Date:   Wed Apr 3 04:03:38 2013 +0000

    PPC: Add breakpoint registers for 603 and e300
    
    Signed-off-by: Fabien Chouteau <chouteau at adacore.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index f1d150a..a9bacd2 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -1149,6 +1149,13 @@ static void gen_spr_603 (CPUPPCState *env)
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
+    /* Breakpoints */
+    /* XXX : not implemented */
+    spr_register(env, SPR_IABR, "IABR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+
 }
 
 /* SPR specific to PowerPC G2 implementation */
@@ -4138,6 +4145,33 @@ static void init_proc_G2LE (CPUPPCState *env)
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
+    /* Breakpoints */
+    /* 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_DABR2, "DABR2",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_IABR2, "IABR2",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_IBCR, "IBCR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_DBCR, "DBCR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+
     /* Memory management */
     gen_low_BATs(env);
     gen_high_BATs(env);
commit 09d9828ace37ead29d510a7e24e63c2f15cd4b1c
Author: Fabien Chouteau <chouteau at adacore.com>
Date:   Fri Mar 29 02:06:28 2013 +0000

    PPC: fix hreset_vector for 60x, 7x0, 7x5, G2, MPC8xx, MPC5xx, 7400 and 7450
    
    According to the different user's manuals, the vector offset for system
    reset (both /HRESET and /SRESET) is 0x00100.
    
    This patch may break support of some executables, as the power-on start
    address may change. For a specific board, if the power-on start address
    is different than HRESET vector (i.e. 0x00000100 or 0xfff00100), this
    should be fixed in board's initialization code.
    
    Signed-off-by: Fabien Chouteau <chouteau at adacore.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 402ad2a..f1d150a 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -2645,7 +2645,7 @@ static void init_excp_MPC5xx (CPUPPCState *env)
     env->ivor_mask = 0x0000FFF0UL;
     env->ivpr_mask = 0xFFFF0000UL;
     /* Hardware reset vector */
-    env->hreset_vector = 0xFFFFFFFCUL;
+    env->hreset_vector = 0x00000100UL;
 #endif
 }
 
@@ -2676,7 +2676,7 @@ static void init_excp_MPC8xx (CPUPPCState *env)
     env->ivor_mask = 0x0000FFF0UL;
     env->ivpr_mask = 0xFFFF0000UL;
     /* Hardware reset vector */
-    env->hreset_vector = 0xFFFFFFFCUL;
+    env->hreset_vector = 0x00000100UL;
 #endif
 }
 
@@ -2701,7 +2701,7 @@ static void init_excp_G2 (CPUPPCState *env)
     env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001300;
     env->excp_vectors[POWERPC_EXCP_SMI]      = 0x00001400;
     /* Hardware reset vector */
-    env->hreset_vector = 0xFFFFFFFCUL;
+    env->hreset_vector = 0x00000100UL;
 #endif
 }
 
@@ -2804,7 +2804,7 @@ static void init_excp_602 (CPUPPCState *env)
     env->excp_vectors[POWERPC_EXCP_WDT]      = 0x00001500;
     env->excp_vectors[POWERPC_EXCP_EMUL]     = 0x00001600;
     /* Hardware reset vector */
-    env->hreset_vector = 0xFFFFFFFCUL;
+    env->hreset_vector = 0x00000100UL;
 #endif
 }
 
@@ -2828,7 +2828,7 @@ static void init_excp_603 (CPUPPCState *env)
     env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001300;
     env->excp_vectors[POWERPC_EXCP_SMI]      = 0x00001400;
     /* Hardware reset vector */
-    env->hreset_vector = 0xFFFFFFFCUL;
+    env->hreset_vector = 0x00000100UL;
 #endif
 }
 
@@ -2873,7 +2873,7 @@ static void init_excp_7x0 (CPUPPCState *env)
     env->excp_vectors[POWERPC_EXCP_SMI]      = 0x00001400;
     env->excp_vectors[POWERPC_EXCP_THERM]    = 0x00001700;
     /* Hardware reset vector */
-    env->hreset_vector = 0xFFFFFFFCUL;
+    env->hreset_vector = 0x00000100UL;
 #endif
 }
 
@@ -2895,7 +2895,7 @@ static void init_excp_750cl (CPUPPCState *env)
     env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001300;
     env->excp_vectors[POWERPC_EXCP_SMI]      = 0x00001400;
     /* Hardware reset vector */
-    env->hreset_vector = 0xFFFFFFFCUL;
+    env->hreset_vector = 0x00000100UL;
 #endif
 }
 
@@ -2917,7 +2917,7 @@ static void init_excp_750cx (CPUPPCState *env)
     env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001300;
     env->excp_vectors[POWERPC_EXCP_THERM]    = 0x00001700;
     /* Hardware reset vector */
-    env->hreset_vector = 0xFFFFFFFCUL;
+    env->hreset_vector = 0x00000100UL;
 #endif
 }
 
@@ -2944,7 +2944,7 @@ static void init_excp_7x5 (CPUPPCState *env)
     env->excp_vectors[POWERPC_EXCP_SMI]      = 0x00001400;
     env->excp_vectors[POWERPC_EXCP_THERM]    = 0x00001700;
     /* Hardware reset vector */
-    env->hreset_vector = 0xFFFFFFFCUL;
+    env->hreset_vector = 0x00000100UL;
 #endif
 }
 
@@ -2969,7 +2969,7 @@ static void init_excp_7400 (CPUPPCState *env)
     env->excp_vectors[POWERPC_EXCP_VPUA]     = 0x00001600;
     env->excp_vectors[POWERPC_EXCP_THERM]    = 0x00001700;
     /* Hardware reset vector */
-    env->hreset_vector = 0xFFFFFFFCUL;
+    env->hreset_vector = 0x00000100UL;
 #endif
 }
 
@@ -2996,7 +2996,7 @@ static void init_excp_7450 (CPUPPCState *env)
     env->excp_vectors[POWERPC_EXCP_SMI]      = 0x00001400;
     env->excp_vectors[POWERPC_EXCP_VPUA]     = 0x00001600;
     /* Hardware reset vector */
-    env->hreset_vector = 0xFFFFFFFCUL;
+    env->hreset_vector = 0x00000100UL;
 #endif
 }
 
commit 8e7a6db96566fe4162edaeb3e8b62fc8004d1598
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Sun Mar 31 14:33:16 2013 +0000

    target-ppc: fix nego and subf*o instructions
    
    The overflow computation of nego and subf*o instructions has been broken
    in commit ffe30937. Contrary to other targets, the instruction is subtract
    from an not subtract on PowerPC.
    
    This patch fixes the issue by using the correct argument in the xor
    computation. Thanks to Peter Maydell for the hint.
    
    With this change the PPC emulation passes the Gwenole Beauchesne
    testsuite again.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
    Reviewed-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 5e741d1..294ab58 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -746,7 +746,7 @@ static inline void gen_op_arith_compute_ov(DisasContext *ctx, TCGv arg0,
 {
     TCGv t0 = tcg_temp_new();
 
-    tcg_gen_xor_tl(cpu_ov, arg0, arg1);
+    tcg_gen_xor_tl(cpu_ov, arg0, arg2);
     tcg_gen_xor_tl(t0, arg1, arg2);
     if (sub) {
         tcg_gen_and_tl(cpu_ov, cpu_ov, t0);
commit 2cf3eb6df552cee74b52de9989e270b74e42847e
Author: Fabien Chouteau <chouteau at adacore.com>
Date:   Fri Mar 29 02:06:27 2013 +0000

    PPC: Remove env->hreset_excp_prefix
    
    This value is not needed if we use correctly the MSR[IP] bit.
    
    excp_prefix is always 0x00000000, except when the MSR[IP] bit is
    implemented and set to 1, in that case excp_prefix is 0xfff00000.
    
    The handling of MSR[IP] was already implemented but not used at reset
    because the value of env->msr was changed "manually".
    
    The patch uses the function hreg_store_msr() to set env->msr, this
    ensures a good handling of MSR[IP] at reset, and therefore a good value
    for excp_prefix.
    
    Signed-off-by: Fabien Chouteau <chouteau at adacore.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 7a42501..e35c26f 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -801,8 +801,10 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args)
         /* 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;
+        /* PAPR always has exception vectors in RAM not ROM. To ensure this,
+         * MSR[IP] should never be set.
+         */
+        env->msr_mask &= ~(1 << 6);
 
         /* Tell KVM that we're in PAPR mode */
         if (kvm_enabled()) {
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 42c36e2..99ebf7e 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1026,7 +1026,6 @@ struct CPUPPCState {
     /* Exception vectors */
     target_ulong excp_vectors[POWERPC_EXCP_NB];
     target_ulong excp_prefix;
-    target_ulong hreset_excp_prefix;
     target_ulong ivor_mask;
     target_ulong ivpr_mask;
     target_ulong hreset_vector;
diff --git a/target-ppc/machine.c b/target-ppc/machine.c
index 235b0d5..2d10adb 100644
--- a/target-ppc/machine.c
+++ b/target-ppc/machine.c
@@ -78,7 +78,6 @@ void cpu_save(QEMUFile *f, void *opaque)
     for (i = 0; i < POWERPC_EXCP_NB; i++)
         qemu_put_betls(f, &env->excp_vectors[i]);
     qemu_put_betls(f, &env->excp_prefix);
-    qemu_put_betls(f, &env->hreset_excp_prefix);
     qemu_put_betls(f, &env->ivor_mask);
     qemu_put_betls(f, &env->ivpr_mask);
     qemu_put_betls(f, &env->hreset_vector);
@@ -167,7 +166,6 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     for (i = 0; i < POWERPC_EXCP_NB; i++)
         qemu_get_betls(f, &env->excp_vectors[i]);
     qemu_get_betls(f, &env->excp_prefix);
-    qemu_get_betls(f, &env->hreset_excp_prefix);
     qemu_get_betls(f, &env->ivor_mask);
     qemu_get_betls(f, &env->ivpr_mask);
     qemu_get_betls(f, &env->hreset_vector);
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index aea7d27..402ad2a 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -2593,7 +2593,6 @@ static void init_excp_4xx_real (CPUPPCState *env)
     env->excp_vectors[POWERPC_EXCP_FIT]      = 0x00001010;
     env->excp_vectors[POWERPC_EXCP_WDT]      = 0x00001020;
     env->excp_vectors[POWERPC_EXCP_DEBUG]    = 0x00002000;
-    env->hreset_excp_prefix = 0x00000000UL;
     env->ivor_mask = 0x0000FFF0UL;
     env->ivpr_mask = 0xFFFF0000UL;
     /* Hardware reset vector */
@@ -2618,7 +2617,6 @@ static void init_excp_4xx_softmmu (CPUPPCState *env)
     env->excp_vectors[POWERPC_EXCP_DTLB]     = 0x00001100;
     env->excp_vectors[POWERPC_EXCP_ITLB]     = 0x00001200;
     env->excp_vectors[POWERPC_EXCP_DEBUG]    = 0x00002000;
-    env->hreset_excp_prefix = 0x00000000UL;
     env->ivor_mask = 0x0000FFF0UL;
     env->ivpr_mask = 0xFFFF0000UL;
     /* Hardware reset vector */
@@ -2644,7 +2642,6 @@ static void init_excp_MPC5xx (CPUPPCState *env)
     env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001C00;
     env->excp_vectors[POWERPC_EXCP_MEXTBR]   = 0x00001E00;
     env->excp_vectors[POWERPC_EXCP_NMEXTBR]  = 0x00001F00;
-    env->hreset_excp_prefix = 0x00000000UL;
     env->ivor_mask = 0x0000FFF0UL;
     env->ivpr_mask = 0xFFFF0000UL;
     /* Hardware reset vector */
@@ -2676,7 +2673,6 @@ static void init_excp_MPC8xx (CPUPPCState *env)
     env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001C00;
     env->excp_vectors[POWERPC_EXCP_MEXTBR]   = 0x00001E00;
     env->excp_vectors[POWERPC_EXCP_NMEXTBR]  = 0x00001F00;
-    env->hreset_excp_prefix = 0x00000000UL;
     env->ivor_mask = 0x0000FFF0UL;
     env->ivpr_mask = 0xFFFF0000UL;
     /* Hardware reset vector */
@@ -2704,7 +2700,6 @@ static void init_excp_G2 (CPUPPCState *env)
     env->excp_vectors[POWERPC_EXCP_DSTLB]    = 0x00001200;
     env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001300;
     env->excp_vectors[POWERPC_EXCP_SMI]      = 0x00001400;
-    env->hreset_excp_prefix = 0x00000000UL;
     /* Hardware reset vector */
     env->hreset_vector = 0xFFFFFFFCUL;
 #endif
@@ -2733,7 +2728,6 @@ static void init_excp_e200(CPUPPCState *env, target_ulong ivpr_mask)
     env->excp_vectors[POWERPC_EXCP_SPEU]     = 0x00000000;
     env->excp_vectors[POWERPC_EXCP_EFPDI]    = 0x00000000;
     env->excp_vectors[POWERPC_EXCP_EFPRI]    = 0x00000000;
-    env->hreset_excp_prefix = 0x00000000UL;
     env->ivor_mask = 0x0000FFF7UL;
     env->ivpr_mask = ivpr_mask;
     /* Hardware reset vector */
@@ -2760,7 +2754,6 @@ static void init_excp_BookE (CPUPPCState *env)
     env->excp_vectors[POWERPC_EXCP_DTLB]     = 0x00000000;
     env->excp_vectors[POWERPC_EXCP_ITLB]     = 0x00000000;
     env->excp_vectors[POWERPC_EXCP_DEBUG]    = 0x00000000;
-    env->hreset_excp_prefix = 0x00000000UL;
     env->ivor_mask = 0x0000FFE0UL;
     env->ivpr_mask = 0xFFFF0000UL;
     /* Hardware reset vector */
@@ -2783,7 +2776,6 @@ static void init_excp_601 (CPUPPCState *env)
     env->excp_vectors[POWERPC_EXCP_IO]       = 0x00000A00;
     env->excp_vectors[POWERPC_EXCP_SYSCALL]  = 0x00000C00;
     env->excp_vectors[POWERPC_EXCP_RUNM]     = 0x00002000;
-    env->hreset_excp_prefix = 0xFFF00000UL;
     /* Hardware reset vector */
     env->hreset_vector = 0x00000100UL;
 #endif
@@ -2811,7 +2803,6 @@ static void init_excp_602 (CPUPPCState *env)
     env->excp_vectors[POWERPC_EXCP_SMI]      = 0x00001400;
     env->excp_vectors[POWERPC_EXCP_WDT]      = 0x00001500;
     env->excp_vectors[POWERPC_EXCP_EMUL]     = 0x00001600;
-    env->hreset_excp_prefix = 0xFFF00000UL;
     /* Hardware reset vector */
     env->hreset_vector = 0xFFFFFFFCUL;
 #endif
@@ -2836,7 +2827,6 @@ static void init_excp_603 (CPUPPCState *env)
     env->excp_vectors[POWERPC_EXCP_DSTLB]    = 0x00001200;
     env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001300;
     env->excp_vectors[POWERPC_EXCP_SMI]      = 0x00001400;
-    env->hreset_excp_prefix = 0x00000000UL;
     /* Hardware reset vector */
     env->hreset_vector = 0xFFFFFFFCUL;
 #endif
@@ -2859,7 +2849,6 @@ static void init_excp_604 (CPUPPCState *env)
     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 = 0x00000100UL;
 #endif
@@ -2883,7 +2872,6 @@ static void init_excp_7x0 (CPUPPCState *env)
     env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001300;
     env->excp_vectors[POWERPC_EXCP_SMI]      = 0x00001400;
     env->excp_vectors[POWERPC_EXCP_THERM]    = 0x00001700;
-    env->hreset_excp_prefix = 0x00000000UL;
     /* Hardware reset vector */
     env->hreset_vector = 0xFFFFFFFCUL;
 #endif
@@ -2906,7 +2894,6 @@ static void init_excp_750cl (CPUPPCState *env)
     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 = 0x00000000UL;
     /* Hardware reset vector */
     env->hreset_vector = 0xFFFFFFFCUL;
 #endif
@@ -2929,7 +2916,6 @@ static void init_excp_750cx (CPUPPCState *env)
     env->excp_vectors[POWERPC_EXCP_PERFM]    = 0x00000F00;
     env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001300;
     env->excp_vectors[POWERPC_EXCP_THERM]    = 0x00001700;
-    env->hreset_excp_prefix = 0x00000000UL;
     /* Hardware reset vector */
     env->hreset_vector = 0xFFFFFFFCUL;
 #endif
@@ -2957,7 +2943,6 @@ static void init_excp_7x5 (CPUPPCState *env)
     env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001300;
     env->excp_vectors[POWERPC_EXCP_SMI]      = 0x00001400;
     env->excp_vectors[POWERPC_EXCP_THERM]    = 0x00001700;
-    env->hreset_excp_prefix = 0x00000000UL;
     /* Hardware reset vector */
     env->hreset_vector = 0xFFFFFFFCUL;
 #endif
@@ -2983,7 +2968,6 @@ static void init_excp_7400 (CPUPPCState *env)
     env->excp_vectors[POWERPC_EXCP_SMI]      = 0x00001400;
     env->excp_vectors[POWERPC_EXCP_VPUA]     = 0x00001600;
     env->excp_vectors[POWERPC_EXCP_THERM]    = 0x00001700;
-    env->hreset_excp_prefix = 0x00000000UL;
     /* Hardware reset vector */
     env->hreset_vector = 0xFFFFFFFCUL;
 #endif
@@ -3011,7 +2995,6 @@ static void init_excp_7450 (CPUPPCState *env)
     env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001300;
     env->excp_vectors[POWERPC_EXCP_SMI]      = 0x00001400;
     env->excp_vectors[POWERPC_EXCP_VPUA]     = 0x00001600;
-    env->hreset_excp_prefix = 0x00000000UL;
     /* Hardware reset vector */
     env->hreset_vector = 0xFFFFFFFCUL;
 #endif
@@ -3041,7 +3024,6 @@ static void init_excp_970 (CPUPPCState *env)
     env->excp_vectors[POWERPC_EXCP_MAINT]    = 0x00001600;
     env->excp_vectors[POWERPC_EXCP_VPUA]     = 0x00001700;
     env->excp_vectors[POWERPC_EXCP_THERM]    = 0x00001800;
-    env->hreset_excp_prefix = 0x00000000FFF00000ULL;
     /* Hardware reset vector */
     env->hreset_vector = 0x0000000000000100ULL;
 #endif
@@ -3070,7 +3052,6 @@ static void init_excp_POWER7 (CPUPPCState *env)
     env->excp_vectors[POWERPC_EXCP_MAINT]    = 0x00001600;
     env->excp_vectors[POWERPC_EXCP_VPUA]     = 0x00001700;
     env->excp_vectors[POWERPC_EXCP_THERM]    = 0x00001800;
-    env->hreset_excp_prefix = 0;
     /* Hardware reset vector */
     env->hreset_vector = 0x0000000000000100ULL;
 #endif
@@ -7043,7 +7024,6 @@ static void init_ppc_proc(PowerPCCPU *cpu)
     /* Set all exception vectors to an invalid address */
     for (i = 0; i < POWERPC_EXCP_NB; i++)
         env->excp_vectors[i] = (target_ulong)(-1ULL);
-    env->hreset_excp_prefix = 0x00000000;
     env->ivor_mask = 0x00000000;
     env->ivpr_mask = 0x00000000;
     /* Default MMU definitions */
@@ -7080,9 +7060,7 @@ static void init_ppc_proc(PowerPCCPU *cpu)
     }
     /* PowerPC implementation specific initialisations (SPRs, timers, ...) */
     (*pcc->init_proc)(env);
-#if !defined(CONFIG_USER_ONLY)
-    env->excp_prefix = env->hreset_excp_prefix;
-#endif
+
     /* MSR bits & flags consistency checks */
     if (env->msr_mask & (1 << 25)) {
         switch (env->flags & (POWERPC_FLAG_SPE | POWERPC_FLAG_VRE)) {
@@ -8182,19 +8160,23 @@ static void ppc_cpu_reset(CPUState *s)
     msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
     msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
     msr |= (target_ulong)1 << MSR_PR;
-#else
-    env->excp_prefix = env->hreset_excp_prefix;
-    env->nip = env->hreset_vector | env->excp_prefix;
-    if (env->mmu_model != POWERPC_MMU_REAL) {
-        ppc_tlb_invalidate_all(env);
-    }
 #endif
-    env->msr = msr & env->msr_mask;
+
 #if defined(TARGET_PPC64)
     if (env->mmu_model & POWERPC_MMU_64) {
         env->msr |= (1ULL << MSR_SF);
     }
 #endif
+
+    hreg_store_msr(env, msr, 1);
+
+#if !defined(CONFIG_USER_ONLY)
+    env->nip = env->hreset_vector | env->excp_prefix;
+    if (env->mmu_model != POWERPC_MMU_REAL) {
+        ppc_tlb_invalidate_all(env);
+    }
+#endif
+
     hreg_compute_hflags(env);
     env->reserve_addr = (target_ulong)-1ULL;
     /* Be sure no exception or interrupt is pending */
commit 3b961124bf8a0b490e4fc3a6a39e004500ae6967
Author: Stuart Yoder <stuart.yoder at freescale.com>
Date:   Sat Mar 30 06:40:49 2013 +0000

    PPC: e500: advertise 4.2 MPIC only if KVM supports EPR
    
    Older KVM versions don't support EPR which breaks guests when we announce
    MPIC variants that support EPR.
    
    Catch that case and expose only MPIC version 2.0 which tells the guest that
    we don't support the EPR capability yet.
    
    Signed-off-by: Stuart Yoder <stuart.yoder at freescale.com>
    [agraf: Add comment, route cap check through kvm_ppc.c]
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/ppc/e500plat.c b/hw/ppc/e500plat.c
index 7292ce1..c852995 100644
--- a/hw/ppc/e500plat.c
+++ b/hw/ppc/e500plat.c
@@ -16,6 +16,7 @@
 #include "sysemu/device_tree.h"
 #include "hw/pci/pci.h"
 #include "hw/ppc/openpic.h"
+#include "kvm_ppc.h"
 
 static void e500plat_fixup_devtree(PPCE500Params *params, void *fdt)
 {
@@ -48,6 +49,12 @@ static void e500plat_init(QEMUMachineInitArgs *args)
         .mpic_version = OPENPIC_MODEL_FSL_MPIC_42,
     };
 
+    /* Older KVM versions don't support EPR which breaks guests when we announce
+       MPIC variants that support EPR. Revert to an older one for those */
+    if (kvm_enabled() && !kvmppc_has_cap_epr()) {
+        params.mpic_version = OPENPIC_MODEL_FSL_MPIC_20;
+    }
+
     ppce500_init(&params);
 }
 
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 5e9dddb..f2658bb 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -63,6 +63,7 @@ static int cap_ppc_rma;
 static int cap_spapr_tce;
 static int cap_hior;
 static int cap_one_reg;
+static int cap_epr;
 
 /* 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
@@ -95,6 +96,7 @@ int kvm_arch_init(KVMState *s)
     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);
+    cap_epr = kvm_check_extension(s, KVM_CAP_PPC_EPR);
 
     if (!cap_interrupt_level) {
         fprintf(stderr, "KVM: Couldn't find level irq capability. Expect the "
@@ -1530,6 +1532,11 @@ int kvmppc_fixup_cpu(PowerPCCPU *cpu)
     return 0;
 }
 
+bool kvmppc_has_cap_epr(void)
+{
+    return cap_epr;
+}
+
 static int kvm_ppc_register_host_cpu_type(void)
 {
     TypeInfo type_info = {
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
index 6bcc5cc..600d632 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -33,6 +33,7 @@ int kvmppc_reset_htab(int shift_hint);
 uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift);
 #endif /* !CONFIG_USER_ONLY */
 int kvmppc_fixup_cpu(PowerPCCPU *cpu);
+bool kvmppc_has_cap_epr(void);
 
 #else
 
@@ -129,6 +130,11 @@ static inline int kvmppc_fixup_cpu(PowerPCCPU *cpu)
 {
     return -1;
 }
+
+static inline bool kvmppc_has_cap_epr(void)
+{
+    return false;
+}
 #endif
 
 #ifndef CONFIG_KVM
commit e71ec2e93dad4446d245031382e30b377640d9ca
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Mon Apr 1 05:06:23 2013 +0000

    target-ppc: Enable ISEL on POWER7
    
    ISEL is a Power ISA 2.06 instruction and thus is available on POWER7.
    Given this is trapped and emulated by the Linux kernel, I guess it went
    unnoticed.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 781170f..aea7d27 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7004,7 +7004,7 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
     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 |
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB |
                        PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
                        PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
                        PPC_FLOAT_STFIWX |
commit 75f6e8b0f121beeee6a95eb9e35d88ec1f01824f
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Sun Apr 14 03:14:49 2013 +0000

    virtio-rng-s390: add properties.
    
    I don't see any reason why these properties are missing.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    
    Note: Need to apply virtio-rng-refactoring first!
    Acked-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    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 a7e81d1..2cff6b7 100644
--- a/hw/s390x/s390-virtio-bus.c
+++ b/hw/s390x/s390-virtio-bus.c
@@ -531,11 +531,19 @@ static const TypeInfo s390_virtio_serial = {
     .class_init    = s390_virtio_serial_class_init,
 };
 
+static Property s390_virtio_rng_properties[] = {
+    DEFINE_VIRTIO_COMMON_FEATURES(VirtIOS390Device, host_features),
+    DEFINE_VIRTIO_RNG_PROPERTIES(VirtIORNGS390, vdev.conf),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
 static void s390_virtio_rng_class_init(ObjectClass *klass, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(klass);
     VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
 
     k->init = s390_virtio_rng_init;
+    dc->props = s390_virtio_rng_properties;
 }
 
 static const TypeInfo s390_virtio_rng = {
commit 3474b679486caa8f6448bae974e131370f360c13
Author: Jason J. Herne <jjherne at us.ibm.com>
Date:   Thu Apr 25 04:25:51 2013 +0000

    Utilize selective runtime reg sync for hot code paths
    
    Make use of new kvm_s390_get_registers_partial() for kvm_handle_css_inst() and
    handle_hypercall() since they only need registers from the partial set and they
    are called quite frequently.
    
    Signed-off-by: Jason J. Herne <jjherne at us.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 02b2e39..fb006ee 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -467,12 +467,16 @@ static int kvm_handle_css_inst(S390CPU *cpu, struct kvm_run *run,
     int r = 0;
     int no_cc = 0;
     CPUS390XState *env = &cpu->env;
+    CPUState *cs = ENV_GET_CPU(env);
 
     if (ipa0 != 0xb2) {
         /* Not handled for now. */
         return -1;
     }
-    cpu_synchronize_state(env);
+
+    kvm_s390_get_registers_partial(cs);
+    cs->kvm_vcpu_dirty = true;
+
     switch (ipa1) {
     case PRIV_XSCH:
         r = ioinst_handle_xsch(env, env->regs[1]);
@@ -603,7 +607,10 @@ static int handle_priv(S390CPU *cpu, struct kvm_run *run,
 
 static int handle_hypercall(CPUS390XState *env, struct kvm_run *run)
 {
-    cpu_synchronize_state(env);
+    CPUState *cs = ENV_GET_CPU(env);
+
+    kvm_s390_get_registers_partial(cs);
+    cs->kvm_vcpu_dirty = true;
     env->regs[2] = s390_virtio_hypercall(env);
 
     return 0;
@@ -808,7 +815,9 @@ static int handle_tsch(S390CPU *cpu)
     struct kvm_run *run = cs->kvm_run;
     int ret;
 
-    cpu_synchronize_state(env);
+    kvm_s390_get_registers_partial(cs);
+    cs->kvm_vcpu_dirty = true;
+
     ret = ioinst_handle_tsch(env, env->regs[1], run->s390_tsch.ipb);
     if (ret >= 0) {
         /* Success; set condition code. */
commit 420840e58b85f7f4e5493dca3f273566f261090a
Author: Jason J. Herne <jjherne at us.ibm.com>
Date:   Thu Apr 25 04:25:50 2013 +0000

    Allow selective runtime register synchronization
    
    We want to avoid expensive register synchronization IOCTL's on the hot path so
    a new kvm_s390_get_registers_partial() is introduced as a compliment to
    kvm_arch_get_registers().  The new function is called on the hot path, and
    kvm_arch_get_registers() is called when we need the complete runtime register
    state.
    
    kvm_arch_put_registers() is updated to only sync the partial runtime set when
    we've only dirtied the partial runtime set.  This is to avoid sending bad data
    back to KVM if we've only partially synced the runtime register set.
    
    Signed-off-by: Jason J. Herne <jjherne at us.ibm.com>
    Reviewed-by: Christian Borntraeger <borntraeger at de.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index e351005..0ce82cf 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -78,6 +78,11 @@ typedef struct MchkQueue {
     uint16_t type;
 } MchkQueue;
 
+/* Defined values for CPUS390XState.runtime_reg_dirty_mask */
+#define KVM_S390_RUNTIME_DIRTY_NONE     0
+#define KVM_S390_RUNTIME_DIRTY_PARTIAL  1
+#define KVM_S390_RUNTIME_DIRTY_FULL     2
+
 typedef struct CPUS390XState {
     uint64_t regs[16];     /* GP registers */
     CPU_DoubleU fregs[16]; /* FP registers */
@@ -121,6 +126,13 @@ typedef struct CPUS390XState {
     uint64_t cputm;
     uint32_t todpr;
 
+    /* on S390 the runtime register set has two dirty states:
+     * a partial dirty state in which only the registers that
+     * are needed all the time are fetched. And a fully dirty
+     * state in which all runtime registers are fetched.
+     */
+    uint32_t runtime_reg_dirty_mask;
+
     CPU_COMMON
 
     /* reset does memset(0) up to here */
@@ -1068,6 +1080,7 @@ void kvm_s390_io_interrupt(S390CPU *cpu, uint16_t subchannel_id,
                            uint32_t io_int_word);
 void kvm_s390_crw_mchk(S390CPU *cpu);
 void kvm_s390_enable_css_support(S390CPU *cpu);
+int kvm_s390_get_registers_partial(CPUState *cpu);
 #else
 static inline void kvm_s390_io_interrupt(S390CPU *cpu,
                                         uint16_t subchannel_id,
@@ -1082,6 +1095,10 @@ static inline void kvm_s390_crw_mchk(S390CPU *cpu)
 static inline void kvm_s390_enable_css_support(S390CPU *cpu)
 {
 }
+static inline int kvm_s390_get_registers_partial(CPUState *cpu)
+{
+    return -ENOSYS;
+}
 #endif
 
 static inline void s390_io_interrupt(S390CPU *cpu,
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 644f484..02b2e39 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -123,6 +123,7 @@ int kvm_arch_put_registers(CPUState *cs, int level)
 {
     S390CPU *cpu = S390_CPU(cs);
     CPUS390XState *env = &cpu->env;
+    struct kvm_one_reg reg;
     struct kvm_sregs sregs;
     struct kvm_regs regs;
     int ret;
@@ -147,6 +148,30 @@ int kvm_arch_put_registers(CPUState *cs, int level)
         }
     }
 
+    if (env->runtime_reg_dirty_mask == KVM_S390_RUNTIME_DIRTY_FULL) {
+        reg.id = KVM_REG_S390_CPU_TIMER;
+        reg.addr = (__u64)&(env->cputm);
+        ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
+        if (ret < 0) {
+            return ret;
+        }
+
+        reg.id = KVM_REG_S390_CLOCK_COMP;
+        reg.addr = (__u64)&(env->ckc);
+        ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
+        if (ret < 0) {
+            return ret;
+        }
+
+        reg.id = KVM_REG_S390_TODPR;
+        reg.addr = (__u64)&(env->todpr);
+        ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
+        if (ret < 0) {
+            return ret;
+        }
+    }
+    env->runtime_reg_dirty_mask = KVM_S390_RUNTIME_DIRTY_NONE;
+
     /* Do we need to save more than that? */
     if (level == KVM_PUT_RUNTIME_STATE) {
         return 0;
@@ -186,11 +211,52 @@ int kvm_arch_get_registers(CPUState *cs)
 {
     S390CPU *cpu = S390_CPU(cs);
     CPUS390XState *env = &cpu->env;
+    struct kvm_one_reg reg;
+    int r;
+
+    r = kvm_s390_get_registers_partial(cs);
+    if (r < 0) {
+        return r;
+    }
+
+    reg.id = KVM_REG_S390_CPU_TIMER;
+    reg.addr = (__u64)&(env->cputm);
+    r = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
+    if (r < 0) {
+        return r;
+    }
+
+    reg.id = KVM_REG_S390_CLOCK_COMP;
+    reg.addr = (__u64)&(env->ckc);
+    r = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
+    if (r < 0) {
+        return r;
+    }
+
+    reg.id = KVM_REG_S390_TODPR;
+    reg.addr = (__u64)&(env->todpr);
+    r = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
+    if (r < 0) {
+        return r;
+    }
+
+    env->runtime_reg_dirty_mask = KVM_S390_RUNTIME_DIRTY_FULL;
+    return 0;
+}
+
+int kvm_s390_get_registers_partial(CPUState *cs)
+{
+    S390CPU *cpu = S390_CPU(cs);
+    CPUS390XState *env = &cpu->env;
     struct kvm_sregs sregs;
     struct kvm_regs regs;
     int ret;
     int i;
 
+    if (env->runtime_reg_dirty_mask) {
+        return 0;
+    }
+
     /* get the PSW */
     env->psw.addr = cs->kvm_run->psw_addr;
     env->psw.mask = cs->kvm_run->psw_mask;
@@ -236,6 +302,7 @@ int kvm_arch_get_registers(CPUState *cs)
         /* no prefix without sync regs */
     }
 
+    env->runtime_reg_dirty_mask = KVM_S390_RUNTIME_DIRTY_PARTIAL;
     return 0;
 }
 
commit 7dc5af5545bb72e1343cc959b3f0e5cdd8758f1f
Author: Dominik Dingel <dingel at linux.vnet.ibm.com>
Date:   Fri Apr 26 02:12:49 2013 +0000

    Common: Add quick access to first boot device
    
    Instead of manually parsing the boot_list as character stream,
    we can access the nth boot device, specified by the position in the
    boot order.
    
    Signed-off-by: Dominik Dingel <dingel at linux.vnet.ibm.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 6578782..43b961c 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -181,6 +181,8 @@ void add_boot_device_path(int32_t bootindex, DeviceState *dev,
                           const char *suffix);
 char *get_boot_devices_list(size_t *size);
 
+DeviceState *get_boot_device(uint32_t position);
+
 bool usb_enabled(bool default_usb);
 
 extern QemuOptsList qemu_drive_opts;
diff --git a/vl.c b/vl.c
index 2e0d1a7..322ea80 100644
--- a/vl.c
+++ b/vl.c
@@ -1222,6 +1222,24 @@ void add_boot_device_path(int32_t bootindex, DeviceState *dev,
     QTAILQ_INSERT_TAIL(&fw_boot_order, node, link);
 }
 
+DeviceState *get_boot_device(uint32_t position)
+{
+    uint32_t counter = 0;
+    FWBootEntry *i = NULL;
+    DeviceState *res = NULL;
+
+    if (!QTAILQ_EMPTY(&fw_boot_order)) {
+        QTAILQ_FOREACH(i, &fw_boot_order, link) {
+            if (counter == position) {
+                res = i->dev;
+                break;
+            }
+            counter++;
+        }
+    }
+    return res;
+}
+
 /*
  * This function returns null terminated string that consist of new line
  * separated device paths.
commit ba747cc8f31a1de7e0a20e7f0cf97965be338e70
Author: Alexander Graf <agraf at suse.de>
Date:   Mon Apr 22 21:12:54 2013 +0200

    S390: CCW: Use new, working firmware by default
    
    Since we now have working firmware for s390-ccw in the tree, we can
    default to it on our s390-ccw machine, rendering it more useful.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 8ea193e..eb774d9 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -83,7 +83,7 @@ static void ccw_init(QEMUMachineInitArgs *args)
     css_bus = virtual_css_bus_init();
     s390_sclp_init();
     s390_init_ipl_dev(args->kernel_filename, args->kernel_cmdline,
-                      args->initrd_filename, "s390-zipl.rom");
+                      args->initrd_filename, "s390-ccw.img");
 
     /* register hypercalls */
     virtio_ccw_register_hcalls();
commit 0c1fecdd5234ba4bb0406362d38f8806a5be8fcc
Author: Alexander Graf <agraf at suse.de>
Date:   Mon Apr 22 21:10:50 2013 +0200

    S390: ccw firmware: Add compiled blob
    
    Now that we have all the source code ready, add a compiled blob into
    the QEMU source tree, so that people without access to an s390 compiler
    can run the s390-ccw firmware.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/Makefile b/Makefile
index e652764..8aca92f 100644
--- a/Makefile
+++ b/Makefile
@@ -295,6 +295,7 @@ qemu-icon.bmp \
 bamboo.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \
 multiboot.bin linuxboot.bin kvmvapic.bin \
 s390-zipl.rom \
+s390-ccw.img \
 spapr-rtas.bin slof.bin \
 palcode-clipper
 else
diff --git a/pc-bios/s390-ccw.img b/pc-bios/s390-ccw.img
new file mode 100644
index 0000000..149cf70
Binary files /dev/null and b/pc-bios/s390-ccw.img differ
commit abbbe3de4aea92319f77cc9d402e983513d08539
Author: Cornelia Huck <cornelia.huck at de.ibm.com>
Date:   Fri Apr 26 02:12:55 2013 +0000

    s390-ccw.img: Get queue config from host.
    
    Ask the host about the configuration instead of guessing it.
    
    Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c
index e0cede5..5b9e1dc 100644
--- a/pc-bios/s390-ccw/virtio.c
+++ b/pc-bios/s390-ccw/virtio.c
@@ -257,17 +257,21 @@ int virtio_read(ulong sector, void *load_addr)
 void virtio_setup_block(struct subchannel_id schid)
 {
     struct vq_info_block info;
+    struct vq_config_block config = {};
 
     virtio_reset(schid);
 
-    /* XXX need to fetch the 128 from host */
-    vring_init(&block, 128, (void*)(100 * 1024 * 1024),
+    config.index = 0;
+    if (run_ccw(schid, CCW_CMD_READ_VQ_CONF, &config, sizeof(config))) {
+        virtio_panic("Could not get block device configuration\n");
+    }
+    vring_init(&block, config.num, (void*)(100 * 1024 * 1024),
                KVM_S390_VIRTIO_RING_ALIGN);
 
     info.queue = (100ULL * 1024ULL* 1024ULL);
     info.align = KVM_S390_VIRTIO_RING_ALIGN;
     info.index = 0;
-    info.num = 128;
+    info.num = config.num;
     block.schid = schid;
 
     if (!run_ccw(schid, CCW_CMD_SET_VQ, &info, sizeof(info))) {
diff --git a/pc-bios/s390-ccw/virtio.h b/pc-bios/s390-ccw/virtio.h
index a33199d..86fdd57 100644
--- a/pc-bios/s390-ccw/virtio.h
+++ b/pc-bios/s390-ccw/virtio.h
@@ -53,6 +53,11 @@ struct vq_info_block {
     u16 num;
 } __attribute__((packed));
 
+struct vq_config_block {
+    u16 index;
+    u16 num;
+} __attribute__((packed));
+
 struct virtio_dev {
     struct virtio_dev_header *header;
     struct virtio_vqconfig *vqconfig;
commit 0f3f1f302fd2021a5ce6cb170321d0a0d35bdec5
Author: Cornelia Huck <cornelia.huck at de.ibm.com>
Date:   Fri Apr 26 02:12:54 2013 +0000

    s390-ccw.img: Rudimentary error checking.
    
    Try to handle at least some of the errors that may happen.
    
    Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c
index 1bd17d4..e0cede5 100644
--- a/pc-bios/s390-ccw/virtio.c
+++ b/pc-bios/s390-ccw/virtio.c
@@ -84,7 +84,9 @@ static int run_ccw(struct subchannel_id schid, int cmd, void *ptr, int len)
      *     assume that a simple tsch will have finished the CCW processing,
      *     but the architecture allows for asynchronous operation
      */
-    drain_irqs(schid);
+    if (!r) {
+        r = drain_irqs(schid);
+    }
     return r;
 }
 
@@ -92,7 +94,9 @@ static void virtio_set_status(struct subchannel_id schid,
                               unsigned long dev_addr)
 {
     unsigned char status = dev_addr;
-    run_ccw(schid, CCW_CMD_WRITE_STATUS, &status, sizeof(status));
+    if (run_ccw(schid, CCW_CMD_WRITE_STATUS, &status, sizeof(status))) {
+        virtio_panic("Could not write status to host!\n");
+    }
 }
 
 static void virtio_reset(struct subchannel_id schid)
@@ -193,6 +197,7 @@ static int virtio_read_many(ulong sector, void *load_addr, int sec_num)
 {
     struct virtio_blk_outhdr out_hdr;
     u8 status;
+    int r;
 
     /* Tell the host we want to read */
     out_hdr.type = VIRTIO_BLK_T_IN;
@@ -213,8 +218,11 @@ static int virtio_read_many(ulong sector, void *load_addr, int sec_num)
     /* Now we can tell the host to read */
     vring_wait_reply(&block, 0);
 
-    drain_irqs(block.schid);
-
+    r = drain_irqs(block.schid);
+    if (r) {
+        /* Well, whatever status is supposed to contain... */
+        status = 1;
+    }
     return status;
 }
 
@@ -262,8 +270,9 @@ void virtio_setup_block(struct subchannel_id schid)
     info.num = 128;
     block.schid = schid;
 
-    run_ccw(schid, CCW_CMD_SET_VQ, &info, sizeof(info));
-    virtio_set_status(schid, VIRTIO_CONFIG_S_DRIVER_OK);
+    if (!run_ccw(schid, CCW_CMD_SET_VQ, &info, sizeof(info))) {
+        virtio_set_status(schid, VIRTIO_CONFIG_S_DRIVER_OK);
+    }
 }
 
 bool virtio_is_blk(struct subchannel_id schid)
commit 776e7f0f215dd11dde85277723408fae3d319143
Author: Cornelia Huck <cornelia.huck at de.ibm.com>
Date:   Fri Apr 26 02:12:53 2013 +0000

    s390-ccw.img: Enhance drain_irqs().
    
    - Use tpi + tsch to get interrupts.
    - Return an error if the irb indicates problems.
    
    Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c
index 1968fc6..1bd17d4 100644
--- a/pc-bios/s390-ccw/virtio.c
+++ b/pc-bios/s390-ccw/virtio.c
@@ -38,12 +38,21 @@ static void virtio_notify(struct subchannel_id schid)
  *             Virtio functions                *
  ***********************************************/
 
-static void drain_irqs(struct subchannel_id schid)
+static int drain_irqs(struct subchannel_id schid)
 {
     struct irb irb = {};
+    int r = 0;
+
     while (1) {
+        /* FIXME: make use of TPI, for that enable subchannel and isc */
         if (tsch(schid, &irb)) {
-            return;
+            /* Might want to differentiate error codes later on. */
+            if (irb.scsw.cstat) {
+                r = -EIO;
+            } else if (irb.scsw.dstat != 0xc) {
+                r = -EIO;
+            }
+            return r;
         }
     }
 }
commit 22d67ab55aad82383a0e5628b902a1a0556b2fc9
Author: Cornelia Huck <cornelia.huck at de.ibm.com>
Date:   Fri Apr 26 02:12:52 2013 +0000

    s390-ccw.img: Detect devices with stsch.
    
    stsch is the canonical way to detect devices. As a bonus, we can
    abort the loop if we get cc 3, and we need to check only the valid
    devices (dnv set).
    
    Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index 67f4987..fd40fa5 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -22,7 +22,7 @@ void virtio_panic(const char *string)
 
 static void virtio_setup(void)
 {
-    struct irb irb;
+    struct schib schib;
     int i;
     int r;
     bool found = false;
@@ -31,8 +31,11 @@ static void virtio_setup(void)
 
     for (i = 0; i < 0x10000; i++) {
         blk_schid.sch_no = i;
-        r = tsch(blk_schid, &irb);
-        if (r != 3) {
+        r = stsch_err(blk_schid, &schib);
+        if (r == 3) {
+            break;
+        }
+        if (schib.pmcw.dnv) {
             if (virtio_is_blk(blk_schid)) {
                 found = true;
                 break;
commit dc03640b5851d3115448493f0eee2b7f539de81a
Author: Christian Borntraeger <borntraeger at de.ibm.com>
Date:   Tue Apr 23 01:23:04 2013 +0000

    s390-ccw.img: Fix compile warning in s390 ccw virtio code
    
    Lets fix this gcc warning:
    
    virtio.c: In function ‘vring_send_buf’:
    virtio.c:125:35: error: operation on ‘vr->next_idx’ may be undefined
    [-Werror=sequence-point]
    
    Signed-off-by: Christian Borntraeger <borntraeger at de.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c
index 79e2941..1968fc6 100644
--- a/pc-bios/s390-ccw/virtio.c
+++ b/pc-bios/s390-ccw/virtio.c
@@ -122,7 +122,9 @@ static void vring_send_buf(struct vring *vr, void *p, int len, int flags)
     vr->desc[vr->next_idx].addr = (ulong)p;
     vr->desc[vr->next_idx].len = len;
     vr->desc[vr->next_idx].flags = flags & ~VRING_HIDDEN_IS_CHAIN;
-    vr->desc[vr->next_idx].next = ++vr->next_idx;
+    vr->desc[vr->next_idx].next = vr->next_idx;
+    vr->desc[vr->next_idx].next++;
+    vr->next_idx++;
 
     /* Chains only have a single ID */
     if (!(flags & VRING_DESC_F_NEXT)) {
commit 6328801f19b08302377e812c454fd2b837f669e3
Author: Christian Borntraeger <borntraeger at de.ibm.com>
Date:   Tue Apr 23 01:23:05 2013 +0000

    s390-ccw.img: Take care of the elf->img transition
    
    We have to call strip with s390-ccw.elf as input and
    s390-ccw.img as output
    
    Signed-off-by: Christian Borntraeger <borntraeger at de.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile
index c126194..ad55a14 100644
--- a/pc-bios/s390-ccw/Makefile
+++ b/pc-bios/s390-ccw/Makefile
@@ -20,7 +20,7 @@ s390-ccw.elf: $(OBJECTS)
 	$(call quiet-command,$(CC) $(LDFLAGS) -o $@ $(OBJECTS),"  Building $(TARGET_DIR)$@")
 
 s390-ccw.img: s390-ccw.elf
-	$(call quiet-command,strip $@,"  Stripping $(TARGET_DIR)$@")
+	$(call quiet-command,strip $< -o $@,"  Stripping $(TARGET_DIR)$@")
 
 clean:
-	rm -f *.o *.d *.img *~
+	rm -f *.o *.d *.img *.elf *~
commit 9933c30509f97e04be0a348659f38b5f53c1ad5c
Author: Christian Borntraeger <borntraeger at de.ibm.com>
Date:   Tue Apr 23 01:23:03 2013 +0000

    s390-ccw.img: build s390-ccw rom on s3900 system by default
    
    Lets build the s390-ccw rom if on s390. Also fix the separate build
    folder case.
    
    Signed-off-by: Christian Borntraeger <borntraeger at de.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/configure b/configure
index 8188a7c..a07abc4 100755
--- a/configure
+++ b/configure
@@ -3460,6 +3460,10 @@ if test "$cpu" = "ppc64" -a "$targetos" != "Darwin" ; then
   roms="$roms spapr-rtas"
 fi
 
+if test "$cpu" = "s390x" ; then
+  roms="$roms s390-ccw"
+fi
+
 # add pixman flags after all config tests are done
 QEMU_CFLAGS="$QEMU_CFLAGS $pixman_cflags $fdt_cflags"
 libs_softmmu="$libs_softmmu $pixman_libs"
@@ -4511,7 +4515,7 @@ fi
 
 # build tree in object directory in case the source is not in the current directory
 DIRS="tests tests/tcg tests/tcg/cris tests/tcg/lm32 tests/libqos"
-DIRS="$DIRS pc-bios/optionrom pc-bios/spapr-rtas"
+DIRS="$DIRS pc-bios/optionrom pc-bios/spapr-rtas pc-bios/s390-ccw"
 DIRS="$DIRS roms/seabios roms/vgabios"
 DIRS="$DIRS qapi-generated"
 FILES="Makefile tests/tcg/Makefile qdict-test-data.txt"
@@ -4519,6 +4523,7 @@ FILES="$FILES tests/tcg/cris/Makefile tests/tcg/cris/.gdbinit"
 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 pc-bios/s390-ccw/Makefile"
 FILES="$FILES roms/seabios/Makefile roms/vgabios/Makefile"
 FILES="$FILES pc-bios/qemu-icon.bmp"
 for bios_file in \
commit 7f61cbc108dd16df9a53649d53f26143ad506fe1
Author: Christian Borntraeger <borntraeger at de.ibm.com>
Date:   Tue Apr 23 01:23:02 2013 +0000

    s390-ccw.img: replace while loop with a disabled wait on s390 bios
    
    dont waste cpu power on an error condition. Lets stop the guest
    with a disabled wait.
    
    Signed-off-by: Christian Borntraeger <borntraeger at de.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index 0913aac..67f4987 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -16,6 +16,7 @@ char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
 void virtio_panic(const char *string)
 {
     sclp_print(string);
+    disabled_wait();
     while (1) { }
 }
 
@@ -52,5 +53,6 @@ int main(void)
     virtio_setup();
     if (zipl_load() < 0)
         sclp_print("Failed to load OS from hard disk\n");
+    disabled_wait();
     while (1) { }
 }
diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h
index a03dbaf..8241b0a 100644
--- a/pc-bios/s390-ccw/s390-ccw.h
+++ b/pc-bios/s390-ccw/s390-ccw.h
@@ -45,6 +45,9 @@ typedef unsigned long long __u64;
 
 #include "cio.h"
 
+/* start.s */
+void disabled_wait(void);
+
 /* main.c */
 void virtio_panic(const char *string);
 
diff --git a/pc-bios/s390-ccw/start.S b/pc-bios/s390-ccw/start.S
index c2b9a19..09deee7 100644
--- a/pc-bios/s390-ccw/start.S
+++ b/pc-bios/s390-ccw/start.S
@@ -3,6 +3,7 @@
  * into the pc-bios directory of qemu.
  *
  * Copyright (c) 2013 Alexander Graf <agraf at suse.de>
+ * Copyright 2013 IBM Corp.
  *
  * 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
@@ -14,3 +15,17 @@ _start:
 
 larl	%r15, stack + 0x8000    /* Set up stack */
 j	main                    /* And call C */
+
+/*
+ * void disabled_wait(void)
+ *
+ * stops the current guest cpu.
+ */
+	.globl disabled_wait
+disabled_wait:
+        larl %r1,disabled_wait_psw
+        lpswe   0(%r1)
+
+        .align  8
+disabled_wait_psw:
+        .quad   0x0002000180000000,0x0000000000000000
commit b462fcd57c0949e4dfd457fafa91db17e0e99113
Author: Alexander Graf <agraf at suse.de>
Date:   Mon Apr 22 21:03:39 2013 +0200

    S390: ccw firmware: Add Makefile
    
    This patch adds a makefile, so we can build our ccw firmware. Also
    add the resulting binaries to .gitignore, so that nobody is annoyed
    they might be in the tree.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/.gitignore b/.gitignore
index 487813a..64e9466 100644
--- a/.gitignore
+++ b/.gitignore
@@ -100,6 +100,8 @@ pc-bios/optionrom/kvmvapic.asm
 pc-bios/optionrom/kvmvapic.bin
 pc-bios/optionrom/kvmvapic.raw
 pc-bios/optionrom/kvmvapic.img
+pc-bios/s390-ccw/s390-ccw.elf
+pc-bios/s390-ccw/s390-ccw.img
 .stgit-*
 cscope.*
 tags
diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile
new file mode 100644
index 0000000..c126194
--- /dev/null
+++ b/pc-bios/s390-ccw/Makefile
@@ -0,0 +1,26 @@
+all: build-all
+# Dummy command so that make thinks it has done something
+	@true
+
+include ../../config-host.mak
+include $(SRC_PATH)/rules.mak
+
+$(call set-vpath, $(SRC_PATH)/pc-bios/s390-ccw)
+
+.PHONY : all clean build-all
+
+OBJECTS=main.o bootmap.o sclp-ascii.o virtio.o start.o
+CFLAGS += -fno-stack-protector
+# XXX find a more clever to locate the bootloader
+LDFLAGS += -Wl,-Ttext,0x7e00000,-Tbss,0x7f00000 -nostdlib
+
+build-all: s390-ccw.img
+
+s390-ccw.elf: $(OBJECTS)
+	$(call quiet-command,$(CC) $(LDFLAGS) -o $@ $(OBJECTS),"  Building $(TARGET_DIR)$@")
+
+s390-ccw.img: s390-ccw.elf
+	$(call quiet-command,strip $@,"  Stripping $(TARGET_DIR)$@")
+
+clean:
+	rm -f *.o *.d *.img *~
commit 685d49a63e0665f609973ffe4ba34f06981e1b03
Author: Alexander Graf <agraf at suse.de>
Date:   Mon Apr 22 21:02:49 2013 +0200

    S390: ccw firmware: Add bootmap interpreter
    
    On s390, there is an architected boot map format that we can read to
    boot a certain entry off the disk. Implement a simple reader for this
    that always boots the first (default) entry.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c
new file mode 100644
index 0000000..53a460d
--- /dev/null
+++ b/pc-bios/s390-ccw/bootmap.c
@@ -0,0 +1,235 @@
+/*
+ * QEMU S390 bootmap interpreter
+ *
+ * Copyright (c) 2009 Alexander Graf <agraf at suse.de>
+ *
+ * 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 "s390-ccw.h"
+
+// #define DEBUG_FALLBACK
+
+#ifdef DEBUG_FALLBACK
+#define dputs(txt) \
+    do { sclp_print("zipl: " txt); } while (0)
+#else
+#define dputs(fmt, ...) \
+    do { } while (0)
+#endif
+
+struct scsi_blockptr {
+    uint64_t blockno;
+    uint16_t size;
+    uint16_t blockct;
+    uint8_t reserved[4];
+} __attribute__ ((packed));
+
+struct component_entry {
+    struct scsi_blockptr data;
+    uint8_t pad[7];
+    uint8_t component_type;
+    uint64_t load_address;
+} __attribute((packed));
+
+struct component_header {
+    uint8_t magic[4];
+    uint8_t type;
+    uint8_t reserved[27];
+} __attribute((packed));
+
+struct mbr {
+    uint8_t magic[4];
+    uint32_t version_id;
+    uint8_t reserved[8];
+    struct scsi_blockptr blockptr;
+} __attribute__ ((packed));
+
+#define ZIPL_MAGIC			"zIPL"
+
+#define ZIPL_COMP_HEADER_IPL		0x00
+#define ZIPL_COMP_HEADER_DUMP		0x01
+
+#define ZIPL_COMP_ENTRY_LOAD		0x02
+#define ZIPL_COMP_ENTRY_EXEC		0x01
+
+/* Scratch space */
+static uint8_t sec[SECTOR_SIZE] __attribute__((__aligned__(SECTOR_SIZE)));
+
+/* Check for ZIPL magic. Returns 0 if not matched. */
+static int zipl_magic(uint8_t *ptr)
+{
+    uint32_t *p = (void*)ptr;
+    uint32_t *z = (void*)ZIPL_MAGIC;
+
+    if (*p != *z) {
+        debug_print_int("invalid magic", *p);
+        virtio_panic("invalid magic");
+    }
+
+    return 1;
+}
+
+static int zipl_load_segment(struct component_entry *entry)
+{
+    const int max_entries = (SECTOR_SIZE / sizeof(struct scsi_blockptr));
+    struct scsi_blockptr *bprs = (void*)sec;
+    uint64_t blockno;
+    long address;
+    int i;
+
+    blockno = entry->data.blockno;
+    address = entry->load_address;
+
+    debug_print_int("loading segment at block", blockno);
+    debug_print_int("addr", address);
+
+    do {
+        if (virtio_read(blockno, (uint8_t *)bprs)) {
+            debug_print_int("failed reading bprs at", blockno);
+            goto fail;
+        }
+
+        for (i = 0;; i++) {
+            u64 *cur_desc = (void*)&bprs[i];
+
+            blockno = bprs[i].blockno;
+            if (!blockno)
+                break;
+
+            /* we need the updated blockno for the next indirect entry in the
+               chain, but don't want to advance address */
+            if (i == (max_entries - 1))
+                break;
+
+            address = virtio_load_direct(cur_desc[0], cur_desc[1], 0,
+                                         (void*)address);
+            if (address == -1)
+                goto fail;
+        }
+    } while (blockno);
+
+    return 0;
+
+fail:
+    sclp_print("failed loading segment\n");
+    return -1;
+}
+
+/* Run a zipl program */
+static int zipl_run(struct scsi_blockptr *pte)
+{
+    struct component_header *header;
+    struct component_entry *entry;
+    void (*ipl)(void);
+    uint8_t tmp_sec[SECTOR_SIZE];
+
+    virtio_read(pte->blockno, tmp_sec);
+    header = (struct component_header *)tmp_sec;
+
+    if (!zipl_magic(tmp_sec)) {
+        goto fail;
+    }
+
+    if (header->type != ZIPL_COMP_HEADER_IPL) {
+        goto fail;
+    }
+
+    dputs("start loading images\n");
+
+    /* Load image(s) into RAM */
+    entry = (struct component_entry *)(&header[1]);
+    while (entry->component_type == ZIPL_COMP_ENTRY_LOAD) {
+        if (zipl_load_segment(entry) < 0) {
+            goto fail;
+        }
+
+        entry++;
+
+        if ((uint8_t*)(&entry[1]) > (tmp_sec + SECTOR_SIZE)) {
+            goto fail;
+        }
+    }
+
+    if (entry->component_type != ZIPL_COMP_ENTRY_EXEC) {
+        goto fail;
+    }
+
+    /* Ensure the guest output starts fresh */
+    sclp_print("\n");
+
+    /* And run the OS! */
+    ipl = (void*)(entry->load_address & 0x7fffffff);
+    debug_print_addr("set IPL addr to", ipl);
+    /* should not return */
+    ipl();
+
+    return 0;
+
+fail:
+    sclp_print("failed running zipl\n");
+    return -1;
+}
+
+int zipl_load(void)
+{
+    struct mbr *mbr = (void*)sec;
+    uint8_t *ns, *ns_end;
+    int program_table_entries = 0;
+    int pte_len = sizeof(struct scsi_blockptr);
+    struct scsi_blockptr *prog_table_entry;
+    const char *error = "";
+
+    /* Grab the MBR */
+    virtio_read(0, (void*)mbr);
+
+    dputs("checking magic\n");
+
+    if (!zipl_magic(mbr->magic)) {
+        error = "zipl_magic 1";
+        goto fail;
+    }
+
+    debug_print_int("program table", mbr->blockptr.blockno);
+
+    /* Parse the program table */
+    if (virtio_read(mbr->blockptr.blockno, sec)) {
+        error = "virtio_read";
+        goto fail;
+    }
+
+    if (!zipl_magic(sec)) {
+        error = "zipl_magic 2";
+        goto fail;
+    }
+
+    ns_end = sec + SECTOR_SIZE;
+    for (ns = (sec + pte_len); (ns + pte_len) < ns_end; ns++) {
+        prog_table_entry = (struct scsi_blockptr *)ns;
+        if (!prog_table_entry->blockno) {
+            break;
+        }
+
+        program_table_entries++;
+    }
+
+    debug_print_int("program table entries", program_table_entries);
+
+    if (!program_table_entries) {
+        goto fail;
+    }
+
+    /* Run the default entry */
+
+    prog_table_entry = (struct scsi_blockptr *)(sec + pte_len);
+
+    return zipl_run(prog_table_entry);
+
+fail:
+    sclp_print("failed loading zipl: ");
+    sclp_print(error);
+    sclp_print("\n");
+    return -1;
+}
commit c9c39d3b5ea870073703141ba04813c7a8779b02
Author: Alexander Graf <agraf at suse.de>
Date:   Mon Apr 22 21:01:49 2013 +0200

    S390: ccw firmware: Add glue header
    
    Like all great programs, we have to call between different functions in
    different object files. And all of them need a common ground of defines.
    
    Provide a file that provides these defines.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h
new file mode 100644
index 0000000..a03dbaf
--- /dev/null
+++ b/pc-bios/s390-ccw/s390-ccw.h
@@ -0,0 +1,131 @@
+/*
+ * S390 CCW boot loader
+ *
+ * Copyright (c) 2013 Alexander Graf <agraf at suse.de>
+ *
+ * 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.
+ */
+
+#ifndef S390_CCW_H
+#define S390_CCW_H
+
+/* #define DEBUG */
+
+typedef unsigned char      u8;
+typedef unsigned short     u16;
+typedef unsigned int       u32;
+typedef unsigned long long u64;
+typedef unsigned long      ulong;
+typedef long               size_t;
+typedef int                bool;
+typedef unsigned char      uint8_t;
+typedef unsigned short     uint16_t;
+typedef unsigned int       uint32_t;
+typedef unsigned long long uint64_t;
+typedef unsigned char      __u8;
+typedef unsigned short     __u16;
+typedef unsigned int       __u32;
+typedef unsigned long long __u64;
+
+#define true 1
+#define false 0
+#define PAGE_SIZE 4096
+
+#ifndef EIO
+#define EIO	1
+#endif
+#ifndef EBUSY
+#define EBUSY	2
+#endif
+#ifndef NULL
+#define NULL    0
+#endif
+
+#include "cio.h"
+
+/* main.c */
+void virtio_panic(const char *string);
+
+/* sclp-ascii.c */
+void sclp_print(const char *string);
+void sclp_setup(void);
+
+/* virtio.c */
+unsigned long virtio_load_direct(ulong rec_list1, ulong rec_list2,
+				 ulong subchan_id, void *load_addr);
+bool virtio_is_blk(struct subchannel_id schid);
+void virtio_setup_block(struct subchannel_id schid);
+int virtio_read(ulong sector, void *load_addr);
+
+/* bootmap.c */
+int zipl_load(void);
+
+static inline void *memset(void *s, int c, size_t n)
+{
+    int i;
+    unsigned char *p = s;
+
+    for (i = 0; i < n; i++) {
+        p[i] = c;
+    }
+
+    return s;
+}
+
+static inline void fill_hex(char *out, unsigned char val)
+{
+    const char hex[] = "0123456789abcdef";
+
+    out[0] = hex[(val >> 4) & 0xf];
+    out[1] = hex[val & 0xf];
+}
+
+static inline void print_int(const char *desc, u64 addr)
+{
+    unsigned char *addr_c = (unsigned char*)&addr;
+    char out[] = ": 0xffffffffffffffff\n";
+    unsigned int i;
+
+    for (i = 0; i < sizeof(addr); i++) {
+        fill_hex(&out[4 + (i*2)], addr_c[i]);
+    }
+
+    sclp_print(desc);
+    sclp_print(out);
+}
+
+static inline void debug_print_int(const char *desc, u64 addr)
+{
+#ifdef DEBUG
+    print_int(desc, addr);
+#endif
+}
+
+static inline void debug_print_addr(const char *desc, void *p)
+{
+#ifdef DEBUG
+    debug_print_int(desc, (unsigned int)(unsigned long)p);
+#endif
+}
+
+/***********************************************
+ *           Hypercall functions               *
+ ***********************************************/
+
+#define KVM_S390_VIRTIO_NOTIFY		0
+#define KVM_S390_VIRTIO_RESET		1
+#define KVM_S390_VIRTIO_SET_STATUS	2
+#define KVM_S390_VIRTIO_CCW_NOTIFY      3
+
+static inline void yield(void)
+{
+	asm volatile ("diag 0,0,0x44"
+                      : :
+		      : "memory", "cc");
+}
+
+#define SECTOR_SIZE 512
+
+#endif /* S390_CCW_H */
commit 1e17c2c15b354a1e6c1d1ad41bb17f7bf146e9ba
Author: Alexander Graf <agraf at suse.de>
Date:   Mon Apr 22 21:01:00 2013 +0200

    S390: ccw firmware: Add virtio device drivers
    
    In order to boot, we need to be able to access a virtio-blk device through
    the CCW bus. Implement support for this.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/pc-bios/s390-ccw/cio.h b/pc-bios/s390-ccw/cio.h
new file mode 100644
index 0000000..cb5815a
--- /dev/null
+++ b/pc-bios/s390-ccw/cio.h
@@ -0,0 +1,322 @@
+/*
+ * Channel IO definitions
+ *
+ * Copyright (c) 2013 Alexander Graf <agraf at suse.de>
+ *
+ * Inspired by various s390 headers in Linux 3.9.
+ *
+ * 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.
+ */
+
+#ifndef CIO_H
+#define CIO_H
+
+/*
+ * path management control word
+ */
+struct pmcw {
+    __u32 intparm;        /* interruption parameter */
+    __u32 qf      : 1;    /* qdio facility */
+    __u32 w       : 1;
+    __u32 isc     : 3;    /* interruption sublass */
+    __u32 res5    : 3;    /* reserved zeros */
+    __u32 ena     : 1;    /* enabled */
+    __u32 lm      : 2;    /* limit mode */
+    __u32 mme     : 2;    /* measurement-mode enable */
+    __u32 mp      : 1;    /* multipath mode */
+    __u32 tf      : 1;    /* timing facility */
+    __u32 dnv     : 1;    /* device number valid */
+    __u32 dev     : 16;   /* device number */
+    __u8  lpm;            /* logical path mask */
+    __u8  pnom;           /* path not operational mask */
+    __u8  lpum;           /* last path used mask */
+    __u8  pim;            /* path installed mask */
+    __u16 mbi;            /* measurement-block index */
+    __u8  pom;            /* path operational mask */
+    __u8  pam;            /* path available mask */
+    __u8  chpid[8];       /* CHPID 0-7 (if available) */
+    __u32 unused1 : 8;    /* reserved zeros */
+    __u32 st      : 3;    /* subchannel type */
+    __u32 unused2 : 18;   /* reserved zeros */
+    __u32 mbfc    : 1;    /* measurement block format control */
+    __u32 xmwme   : 1;    /* extended measurement word mode enable */
+    __u32 csense  : 1;    /* concurrent sense; can be enabled ...*/
+                /*  ... per MSCH, however, if facility */
+                /*  ... is not installed, this results */
+                /*  ... in an operand exception.       */
+} __attribute__ ((packed));
+
+/* Target SCHIB configuration. */
+struct schib_config {
+    __u64 mba;
+    __u32 intparm;
+    __u16 mbi;
+    __u32 isc:3;
+    __u32 ena:1;
+    __u32 mme:2;
+    __u32 mp:1;
+    __u32 csense:1;
+    __u32 mbfc:1;
+} __attribute__ ((packed));
+
+struct scsw {
+    __u16 flags;
+    __u16 ctrl;
+    __u32 cpa;
+    __u8 dstat;
+    __u8 cstat;
+    __u16 count;
+} __attribute__ ((packed));
+
+#define SCSW_FCTL_CLEAR_FUNC 0x1000
+#define SCSW_FCTL_HALT_FUNC 0x2000
+#define SCSW_FCTL_START_FUNC 0x4000
+
+/*
+ * subchannel information block
+ */
+struct schib {
+    struct pmcw pmcw;     /* path management control word */
+    struct scsw scsw;     /* subchannel status word */
+    __u64 mba;            /* measurement block address */
+    __u8 mda[4];          /* model dependent area */
+} __attribute__ ((packed,aligned(4)));
+
+struct subchannel_id {
+        __u32 cssid  : 8;
+        __u32        : 4;
+        __u32 m      : 1;
+        __u32 ssid   : 2;
+        __u32 one    : 1;
+        __u32 sch_no : 16;
+} __attribute__ ((packed, aligned(4)));
+
+/*
+ * TPI info structure
+ */
+struct tpi_info {
+    struct subchannel_id schid;
+    __u32 intparm;         /* interruption parameter */
+    __u32 adapter_IO : 1;
+    __u32 reserved2  : 1;
+    __u32 isc        : 3;
+    __u32 reserved3  : 12;
+    __u32 int_type   : 3;
+    __u32 reserved4  : 12;
+} __attribute__ ((packed));
+
+/* channel command word (type 1) */
+struct ccw1 {
+    __u8 cmd_code;
+    __u8 flags;
+    __u16 count;
+    __u32 cda;
+} __attribute__ ((packed));
+
+#define CCW_FLAG_DC              0x80
+#define CCW_FLAG_CC              0x40
+#define CCW_FLAG_SLI             0x20
+#define CCW_FLAG_SKIP            0x10
+#define CCW_FLAG_PCI             0x08
+#define CCW_FLAG_IDA             0x04
+#define CCW_FLAG_SUSPEND         0x02
+
+#define CCW_CMD_NOOP             0x03
+#define CCW_CMD_BASIC_SENSE      0x04
+#define CCW_CMD_TIC              0x08
+#define CCW_CMD_SENSE_ID         0xe4
+
+#define CCW_CMD_SET_VQ           0x13
+#define CCW_CMD_VDEV_RESET       0x33
+#define CCW_CMD_READ_FEAT        0x12
+#define CCW_CMD_WRITE_FEAT       0x11
+#define CCW_CMD_READ_CONF        0x22
+#define CCW_CMD_WRITE_CONF       0x21
+#define CCW_CMD_WRITE_STATUS     0x31
+#define CCW_CMD_SET_IND          0x43
+#define CCW_CMD_SET_CONF_IND     0x53
+#define CCW_CMD_READ_VQ_CONF     0x32
+
+/*
+ * Command-mode operation request block
+ */
+struct cmd_orb {
+    __u32 intparm;    /* interruption parameter */
+    __u32 key:4;      /* flags, like key, suspend control, etc. */
+    __u32 spnd:1;     /* suspend control */
+    __u32 res1:1;     /* reserved */
+    __u32 mod:1;      /* modification control */
+    __u32 sync:1;     /* synchronize control */
+    __u32 fmt:1;      /* format control */
+    __u32 pfch:1;     /* prefetch control */
+    __u32 isic:1;     /* initial-status-interruption control */
+    __u32 alcc:1;     /* address-limit-checking control */
+    __u32 ssic:1;     /* suppress-suspended-interr. control */
+    __u32 res2:1;     /* reserved */
+    __u32 c64:1;      /* IDAW/QDIO 64 bit control  */
+    __u32 i2k:1;      /* IDAW 2/4kB block size control */
+    __u32 lpm:8;      /* logical path mask */
+    __u32 ils:1;      /* incorrect length */
+    __u32 zero:6;     /* reserved zeros */
+    __u32 orbx:1;     /* ORB extension control */
+    __u32 cpa;    /* channel program address */
+}  __attribute__ ((packed, aligned(4)));
+
+struct ciw {
+    __u8 type;
+    __u8 command;
+    __u16 count;
+};
+
+/*
+ * sense-id response buffer layout
+ */
+struct senseid {
+    /* common part */
+    __u8  reserved;   /* always 0x'FF' */
+    __u16 cu_type;    /* control unit type */
+    __u8  cu_model;   /* control unit model */
+    __u16 dev_type;   /* device type */
+    __u8  dev_model;  /* device model */
+    __u8  unused;     /* padding byte */
+    /* extended part */
+    struct ciw ciw[62];
+}  __attribute__ ((packed, aligned(4)));
+
+/* interruption response block */
+struct irb {
+    struct scsw scsw;
+    __u32 esw[5];
+    __u32 ecw[8];
+    __u32 emw[8];
+}  __attribute__ ((packed, aligned(4)));
+
+/*
+ * Some S390 specific IO instructions as inline
+ */
+
+static inline int stsch_err(struct subchannel_id schid, struct schib *addr)
+{
+    register struct subchannel_id reg1 asm ("1") = schid;
+    int ccode = -EIO;
+
+    asm volatile(
+        "    stsch    0(%3)\n"
+        "0:  ipm    %0\n"
+        "    srl    %0,28\n"
+        "1:\n"
+        : "+d" (ccode), "=m" (*addr)
+        : "d" (reg1), "a" (addr)
+        : "cc");
+    return ccode;
+}
+
+static inline int msch(struct subchannel_id schid, struct schib *addr)
+{
+    register struct subchannel_id reg1 asm ("1") = schid;
+    int ccode;
+
+    asm volatile(
+        "    msch    0(%2)\n"
+        "    ipm    %0\n"
+        "    srl    %0,28"
+        : "=d" (ccode)
+        : "d" (reg1), "a" (addr), "m" (*addr)
+        : "cc");
+    return ccode;
+}
+
+static inline int msch_err(struct subchannel_id schid, struct schib *addr)
+{
+    register struct subchannel_id reg1 asm ("1") = schid;
+    int ccode = -EIO;
+
+    asm volatile(
+        "    msch    0(%2)\n"
+        "0:  ipm    %0\n"
+        "    srl    %0,28\n"
+        "1:\n"
+        : "+d" (ccode)
+        : "d" (reg1), "a" (addr), "m" (*addr)
+        : "cc");
+    return ccode;
+}
+
+static inline int tsch(struct subchannel_id schid, struct irb *addr)
+{
+    register struct subchannel_id reg1 asm ("1") = schid;
+    int ccode;
+
+    asm volatile(
+        "    tsch    0(%3)\n"
+        "    ipm    %0\n"
+        "    srl    %0,28"
+        : "=d" (ccode), "=m" (*addr)
+        : "d" (reg1), "a" (addr)
+        : "cc");
+    return ccode;
+}
+
+static inline int ssch(struct subchannel_id schid, struct cmd_orb *addr)
+{
+    register struct subchannel_id reg1 asm("1") = schid;
+    int ccode = -EIO;
+
+    asm volatile(
+        "    ssch    0(%2)\n"
+        "0:  ipm    %0\n"
+        "    srl    %0,28\n"
+        "1:\n"
+        : "+d" (ccode)
+        : "d" (reg1), "a" (addr), "m" (*addr)
+        : "cc", "memory");
+    return ccode;
+}
+
+static inline int csch(struct subchannel_id schid)
+{
+    register struct subchannel_id reg1 asm("1") = schid;
+    int ccode;
+
+    asm volatile(
+        "    csch\n"
+        "    ipm    %0\n"
+        "    srl    %0,28"
+        : "=d" (ccode)
+        : "d" (reg1)
+        : "cc");
+    return ccode;
+}
+
+static inline int tpi(struct tpi_info *addr)
+{
+    int ccode;
+
+    asm volatile(
+        "    tpi    0(%2)\n"
+        "    ipm    %0\n"
+        "    srl    %0,28"
+        : "=d" (ccode), "=m" (*addr)
+        : "a" (addr)
+        : "cc");
+    return ccode;
+}
+
+static inline int chsc(void *chsc_area)
+{
+    typedef struct { char _[4096]; } addr_type;
+    int cc;
+
+    asm volatile(
+        "    .insn    rre,0xb25f0000,%2,0\n"
+        "    ipm    %0\n"
+        "    srl    %0,28\n"
+        : "=d" (cc), "=m" (*(addr_type *) chsc_area)
+        : "d" (chsc_area), "m" (*(addr_type *) chsc_area)
+        : "cc");
+    return cc;
+}
+
+#endif /* CIO_H */
diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c
new file mode 100644
index 0000000..79e2941
--- /dev/null
+++ b/pc-bios/s390-ccw/virtio.c
@@ -0,0 +1,274 @@
+/*
+ * Virtio driver bits
+ *
+ * Copyright (c) 2013 Alexander Graf <agraf at suse.de>
+ *
+ * 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 "s390-ccw.h"
+#include "virtio.h"
+
+struct vring block;
+
+static long kvm_hypercall(unsigned long nr, unsigned long param1,
+                          unsigned long param2)
+{
+	register ulong r_nr asm("1") = nr;
+	register ulong r_param1 asm("2") = param1;
+	register ulong r_param2 asm("3") = param2;
+	register long retval asm("2");
+
+	asm volatile ("diag 2,4,0x500"
+		      : "=d" (retval)
+		      : "d" (r_nr), "0" (r_param1), "r"(r_param2)
+		      : "memory", "cc");
+
+	return retval;
+}
+
+static void virtio_notify(struct subchannel_id schid)
+{
+    kvm_hypercall(KVM_S390_VIRTIO_CCW_NOTIFY, *(u32*)&schid, 0);
+}
+
+/***********************************************
+ *             Virtio functions                *
+ ***********************************************/
+
+static void drain_irqs(struct subchannel_id schid)
+{
+    struct irb irb = {};
+    while (1) {
+        if (tsch(schid, &irb)) {
+            return;
+        }
+    }
+}
+
+static int run_ccw(struct subchannel_id schid, int cmd, void *ptr, int len)
+{
+    struct ccw1 ccw = {};
+    struct cmd_orb orb = {};
+    struct schib schib;
+    int r;
+
+    /* start command processing */
+    stsch_err(schid, &schib);
+    schib.scsw.ctrl = SCSW_FCTL_START_FUNC;
+    msch(schid, &schib);
+
+    /* start subchannel command */
+    orb.fmt = 1;
+    orb.cpa = (u32)(long)&ccw;
+    orb.lpm = 0x80;
+
+    ccw.cmd_code = cmd;
+    ccw.cda = (long)ptr;
+    ccw.count = len;
+
+    r = ssch(schid, &orb);
+    /*
+     * XXX Wait until device is done processing the CCW. For now we can
+     *     assume that a simple tsch will have finished the CCW processing,
+     *     but the architecture allows for asynchronous operation
+     */
+    drain_irqs(schid);
+    return r;
+}
+
+static void virtio_set_status(struct subchannel_id schid,
+                              unsigned long dev_addr)
+{
+    unsigned char status = dev_addr;
+    run_ccw(schid, CCW_CMD_WRITE_STATUS, &status, sizeof(status));
+}
+
+static void virtio_reset(struct subchannel_id schid)
+{
+    run_ccw(schid, CCW_CMD_VDEV_RESET, NULL, 0);
+}
+
+static void vring_init(struct vring *vr, unsigned int num, void *p,
+                       unsigned long align)
+{
+    debug_print_addr("init p", p);
+    vr->num = num;
+    vr->desc = p;
+    vr->avail = p + num*sizeof(struct vring_desc);
+    vr->used = (void *)(((unsigned long)&vr->avail->ring[num] + align-1)
+                & ~(align - 1));
+
+    /* We're running with interrupts off anyways, so don't bother */
+    vr->used->flags = VRING_USED_F_NO_NOTIFY;
+
+    debug_print_addr("init vr", vr);
+}
+
+static void vring_notify(struct subchannel_id schid)
+{
+    virtio_notify(schid);
+}
+
+static void vring_send_buf(struct vring *vr, void *p, int len, int flags)
+{
+    /* For follow-up chains we need to keep the first entry point */
+    if (!(flags & VRING_HIDDEN_IS_CHAIN)) {
+        vr->avail->ring[vr->avail->idx % vr->num] = vr->next_idx;
+    }
+
+    vr->desc[vr->next_idx].addr = (ulong)p;
+    vr->desc[vr->next_idx].len = len;
+    vr->desc[vr->next_idx].flags = flags & ~VRING_HIDDEN_IS_CHAIN;
+    vr->desc[vr->next_idx].next = ++vr->next_idx;
+
+    /* Chains only have a single ID */
+    if (!(flags & VRING_DESC_F_NEXT)) {
+        vr->avail->idx++;
+    }
+
+    vr->used->idx = vr->next_idx;
+}
+
+static u64 get_clock(void)
+{
+    u64 r;
+
+    asm volatile("stck %0" : "=Q" (r) : : "cc");
+    return r;
+}
+
+static ulong get_second(void)
+{
+    return (get_clock() >> 12) / 1000000;
+}
+
+/*
+ * Wait for the host to reply.
+ *
+ * timeout is in seconds if > 0.
+ *
+ * Returns 0 on success, 1 on timeout.
+ */
+static int vring_wait_reply(struct vring *vr, int timeout)
+{
+    ulong target_second = get_second() + timeout;
+    struct subchannel_id schid = vr->schid;
+    int r = 0;
+
+    while (vr->used->idx == vr->next_idx) {
+        vring_notify(schid);
+        if (timeout && (get_second() >= target_second)) {
+            r = 1;
+            break;
+        }
+        yield();
+    }
+
+    vr->next_idx = 0;
+    vr->desc[0].len = 0;
+    vr->desc[0].flags = 0;
+
+    return r;
+}
+
+/***********************************************
+ *               Virtio block                  *
+ ***********************************************/
+
+static int virtio_read_many(ulong sector, void *load_addr, int sec_num)
+{
+    struct virtio_blk_outhdr out_hdr;
+    u8 status;
+
+    /* Tell the host we want to read */
+    out_hdr.type = VIRTIO_BLK_T_IN;
+    out_hdr.ioprio = 99;
+    out_hdr.sector = sector;
+
+    vring_send_buf(&block, &out_hdr, sizeof(out_hdr), VRING_DESC_F_NEXT);
+
+    /* This is where we want to receive data */
+    vring_send_buf(&block, load_addr, SECTOR_SIZE * sec_num,
+                   VRING_DESC_F_WRITE | VRING_HIDDEN_IS_CHAIN |
+                   VRING_DESC_F_NEXT);
+
+    /* status field */
+    vring_send_buf(&block, &status, sizeof(u8), VRING_DESC_F_WRITE |
+                   VRING_HIDDEN_IS_CHAIN);
+
+    /* Now we can tell the host to read */
+    vring_wait_reply(&block, 0);
+
+    drain_irqs(block.schid);
+
+    return status;
+}
+
+unsigned long virtio_load_direct(ulong rec_list1, ulong rec_list2,
+				 ulong subchan_id, void *load_addr)
+{
+    u8 status;
+    int sec = rec_list1;
+    int sec_num = (((rec_list2 >> 32)+ 1) & 0xffff);
+    int sec_len = rec_list2 >> 48;
+    ulong addr = (ulong)load_addr;
+
+    if (sec_len != SECTOR_SIZE) {
+        return -1;
+    }
+
+    sclp_print(".");
+    status = virtio_read_many(sec, (void*)addr, sec_num);
+    if (status) {
+        virtio_panic("I/O Error");
+    }
+    addr += sec_num * SECTOR_SIZE;
+
+    return addr;
+}
+
+int virtio_read(ulong sector, void *load_addr)
+{
+    return virtio_read_many(sector, load_addr, 1);
+}
+
+void virtio_setup_block(struct subchannel_id schid)
+{
+    struct vq_info_block info;
+
+    virtio_reset(schid);
+
+    /* XXX need to fetch the 128 from host */
+    vring_init(&block, 128, (void*)(100 * 1024 * 1024),
+               KVM_S390_VIRTIO_RING_ALIGN);
+
+    info.queue = (100ULL * 1024ULL* 1024ULL);
+    info.align = KVM_S390_VIRTIO_RING_ALIGN;
+    info.index = 0;
+    info.num = 128;
+    block.schid = schid;
+
+    run_ccw(schid, CCW_CMD_SET_VQ, &info, sizeof(info));
+    virtio_set_status(schid, VIRTIO_CONFIG_S_DRIVER_OK);
+}
+
+bool virtio_is_blk(struct subchannel_id schid)
+{
+    int r;
+    struct senseid senseid = {};
+
+    /* run sense id command */
+    r = run_ccw(schid, CCW_CMD_SENSE_ID, &senseid, sizeof(senseid));
+    if (r) {
+        return false;
+    }
+    if ((senseid.cu_type != 0x3832) || (senseid.cu_model != VIRTIO_ID_BLOCK)) {
+        return false;
+    }
+
+    return true;
+}
+
diff --git a/pc-bios/s390-ccw/virtio.h b/pc-bios/s390-ccw/virtio.h
new file mode 100644
index 0000000..a33199d
--- /dev/null
+++ b/pc-bios/s390-ccw/virtio.h
@@ -0,0 +1,158 @@
+/*
+ * Virtio driver bits
+ *
+ * Copyright (c) 2013 Alexander Graf <agraf at suse.de>
+ *
+ * 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.
+ */
+
+#ifndef VIRTIO_H
+#define VIRTIO_H
+
+#include "s390-ccw.h"
+
+/* Status byte for guest to report progress, and synchronize features. */
+/* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */
+#define VIRTIO_CONFIG_S_ACKNOWLEDGE     1
+/* We have found a driver for the device. */
+#define VIRTIO_CONFIG_S_DRIVER          2
+/* Driver has used its parts of the config, and is happy */
+#define VIRTIO_CONFIG_S_DRIVER_OK       4
+/* We've given up on this device. */
+#define VIRTIO_CONFIG_S_FAILED          0x80
+
+enum virtio_dev_type {
+    VIRTIO_ID_NET = 1,
+    VIRTIO_ID_BLOCK = 2,
+    VIRTIO_ID_CONSOLE = 3,
+    VIRTIO_ID_BALLOON = 5,
+};
+
+struct virtio_dev_header {
+    enum virtio_dev_type type : 8;
+    u8  num_vq;
+    u8  feature_len;
+    u8  config_len;
+    u8  status;
+    u8  vqconfig[];
+} __attribute__((packed));
+
+struct virtio_vqconfig {
+    u64 token;
+    u64 address;
+    u16 num;
+    u8  pad[6];
+} __attribute__((packed));
+
+struct vq_info_block {
+    u64 queue;
+    u32 align;
+    u16 index;
+    u16 num;
+} __attribute__((packed));
+
+struct virtio_dev {
+    struct virtio_dev_header *header;
+    struct virtio_vqconfig *vqconfig;
+    char *host_features;
+    char *guest_features;
+    char *config;
+};
+
+#define KVM_S390_VIRTIO_RING_ALIGN	4096
+
+#define VRING_USED_F_NO_NOTIFY  1
+
+/* This marks a buffer as continuing via the next field. */
+#define VRING_DESC_F_NEXT       1
+/* This marks a buffer as write-only (otherwise read-only). */
+#define VRING_DESC_F_WRITE      2
+/* This means the buffer contains a list of buffer descriptors. */
+#define VRING_DESC_F_INDIRECT   4
+
+/* Internal flag to mark follow-up segments as such */
+#define VRING_HIDDEN_IS_CHAIN   256
+
+/* Virtio ring descriptors: 16 bytes.  These can chain together via "next". */
+struct vring_desc {
+    /* Address (guest-physical). */
+    u64 addr;
+    /* Length. */
+    u32 len;
+    /* The flags as indicated above. */
+    u16 flags;
+    /* We chain unused descriptors via this, too */
+    u16 next;
+} __attribute__((packed));
+
+struct vring_avail {
+    u16 flags;
+    u16 idx;
+    u16 ring[];
+} __attribute__((packed));
+
+/* u32 is used here for ids for padding reasons. */
+struct vring_used_elem {
+    /* Index of start of used descriptor chain. */
+    u32 id;
+    /* Total length of the descriptor chain which was used (written to) */
+    u32 len;
+} __attribute__((packed));
+
+struct vring_used {
+    u16 flags;
+    u16 idx;
+    struct vring_used_elem ring[];
+} __attribute__((packed));
+
+struct vring {
+    unsigned int num;
+    int next_idx;
+    struct vring_desc *desc;
+    struct vring_avail *avail;
+    struct vring_used *used;
+    struct subchannel_id schid;
+};
+
+
+/***********************************************
+ *               Virtio block                  *
+ ***********************************************/
+
+/*
+ * Command types
+ *
+ * Usage is a bit tricky as some bits are used as flags and some are not.
+ *
+ * Rules:
+ *   VIRTIO_BLK_T_OUT may be combined with VIRTIO_BLK_T_SCSI_CMD or
+ *   VIRTIO_BLK_T_BARRIER.  VIRTIO_BLK_T_FLUSH is a command of its own
+ *   and may not be combined with any of the other flags.
+ */
+
+/* These two define direction. */
+#define VIRTIO_BLK_T_IN         0
+#define VIRTIO_BLK_T_OUT        1
+
+/* This bit says it's a scsi command, not an actual read or write. */
+#define VIRTIO_BLK_T_SCSI_CMD   2
+
+/* Cache flush command */
+#define VIRTIO_BLK_T_FLUSH      4
+
+/* Barrier before this op. */
+#define VIRTIO_BLK_T_BARRIER    0x80000000
+
+/* This is the first element of the read scatter-gather list. */
+struct virtio_blk_outhdr {
+        /* VIRTIO_BLK_T* */
+        u32 type;
+        /* io priority. */
+        u32 ioprio;
+        /* Sector (ie. 512 byte offset) */
+        u64 sector;
+};
+
+#endif /* VIRTIO_H */
commit 0369b2eb0707970c5f031b3ece84ccda953a8375
Author: Alexander Graf <agraf at suse.de>
Date:   Mon Apr 22 20:59:25 2013 +0200

    S390: ccw firmware: Add sclp output
    
    In order to communicate with the user, we need an I/O mechanism that he
    can read. Implement SCLP ASCII support, which happens to be the default
    in the s390 ccw machine.
    
    This file is missing read support for now. It can only print messages.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/pc-bios/s390-ccw/sclp-ascii.c b/pc-bios/s390-ccw/sclp-ascii.c
new file mode 100644
index 0000000..1c93937
--- /dev/null
+++ b/pc-bios/s390-ccw/sclp-ascii.c
@@ -0,0 +1,81 @@
+/*
+ * SCLP ASCII access driver
+ *
+ * Copyright (c) 2013 Alexander Graf <agraf at suse.de>
+ *
+ * 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 "s390-ccw.h"
+#include "sclp.h"
+
+static char _sccb[PAGE_SIZE] __attribute__((__aligned__(4096)));
+
+/* Perform service call. Return 0 on success, non-zero otherwise. */
+static int sclp_service_call(unsigned int command, void *sccb)
+{
+        int cc;
+
+        asm volatile(
+                "       .insn   rre,0xb2200000,%1,%2\n"  /* servc %1,%2 */
+                "       ipm     %0\n"
+                "       srl     %0,28"
+                : "=&d" (cc) : "d" (command), "a" (__pa(sccb))
+                : "cc", "memory");
+        if (cc == 3)
+                return -EIO;
+        if (cc == 2)
+                return -EBUSY;
+        return 0;
+}
+
+static void sclp_set_write_mask(void)
+{
+    WriteEventMask *sccb = (void*)_sccb;
+
+    sccb->h.length = sizeof(WriteEventMask);
+    sccb->mask_length = sizeof(unsigned int);
+    sccb->receive_mask = SCLP_EVENT_MASK_MSG_ASCII;
+    sccb->cp_receive_mask = SCLP_EVENT_MASK_MSG_ASCII;
+    sccb->send_mask = SCLP_EVENT_MASK_MSG_ASCII;
+    sccb->cp_send_mask = SCLP_EVENT_MASK_MSG_ASCII;
+
+    sclp_service_call(SCLP_CMD_WRITE_EVENT_MASK, sccb);
+}
+
+void sclp_setup(void)
+{
+    sclp_set_write_mask();
+}
+
+static int _strlen(const char *str)
+{
+    int i;
+    for (i = 0; *str; i++)
+        str++;
+    return i;
+}
+
+static void _memcpy(char *dest, const char *src, int len)
+{
+    int i;
+    for (i = 0; i < len; i++)
+        dest[i] = src[i];
+}
+
+void sclp_print(const char *str)
+{
+    int len = _strlen(str);
+    WriteEventData *sccb = (void*)_sccb;
+
+    sccb->h.length = sizeof(WriteEventData) + len;
+    sccb->h.function_code = SCLP_FC_NORMAL_WRITE;
+    sccb->ebh.length = sizeof(EventBufferHeader) + len;
+    sccb->ebh.type = SCLP_EVENT_ASCII_CONSOLE_DATA;
+    sccb->ebh.flags = 0;
+    _memcpy(sccb->data, str, len);
+
+    sclp_service_call(SCLP_CMD_WRITE_EVENT_DATA, sccb);
+}
diff --git a/pc-bios/s390-ccw/sclp.h b/pc-bios/s390-ccw/sclp.h
new file mode 100644
index 0000000..3cbfb78
--- /dev/null
+++ b/pc-bios/s390-ccw/sclp.h
@@ -0,0 +1,107 @@
+/*
+ * SCLP ASCII access driver
+ *
+ * Copyright (c) 2013 Alexander Graf <agraf at suse.de>
+ *
+ * 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.
+ */
+
+#ifndef SCLP_H
+#define SCLP_H
+
+/* SCLP command codes */
+#define SCLP_CMDW_READ_SCP_INFO                 0x00020001
+#define SCLP_CMDW_READ_SCP_INFO_FORCED          0x00120001
+#define SCLP_CMD_READ_EVENT_DATA                0x00770005
+#define SCLP_CMD_WRITE_EVENT_DATA               0x00760005
+#define SCLP_CMD_READ_EVENT_DATA                0x00770005
+#define SCLP_CMD_WRITE_EVENT_DATA               0x00760005
+#define SCLP_CMD_WRITE_EVENT_MASK               0x00780005
+
+/* SCLP response codes */
+#define SCLP_RC_NORMAL_READ_COMPLETION          0x0010
+#define SCLP_RC_NORMAL_COMPLETION               0x0020
+#define SCLP_RC_INVALID_SCLP_COMMAND            0x01f0
+#define SCLP_RC_CONTAINED_EQUIPMENT_CHECK       0x0340
+#define SCLP_RC_INSUFFICIENT_SCCB_LENGTH        0x0300
+#define SCLP_RC_INVALID_FUNCTION                0x40f0
+#define SCLP_RC_NO_EVENT_BUFFERS_STORED         0x60f0
+#define SCLP_RC_INVALID_SELECTION_MASK          0x70f0
+#define SCLP_RC_INCONSISTENT_LENGTHS            0x72f0
+#define SCLP_RC_EVENT_BUFFER_SYNTAX_ERROR       0x73f0
+#define SCLP_RC_INVALID_MASK_LENGTH             0x74f0
+
+/* Service Call Control Block (SCCB) and its elements */
+
+#define SCCB_SIZE 4096
+
+#define SCLP_VARIABLE_LENGTH_RESPONSE           0x80
+#define SCLP_EVENT_BUFFER_ACCEPTED              0x80
+
+#define SCLP_FC_NORMAL_WRITE                    0
+
+typedef struct SCCBHeader {
+    uint16_t length;
+    uint8_t function_code;
+    uint8_t control_mask[3];
+    uint16_t response_code;
+} __attribute__((packed)) SCCBHeader;
+
+#define SCCB_DATA_LEN (SCCB_SIZE - sizeof(SCCBHeader))
+
+typedef struct ReadInfo {
+    SCCBHeader h;
+    uint16_t rnmax;
+    uint8_t rnsize;
+} __attribute__((packed)) ReadInfo;
+
+typedef struct SCCB {
+    SCCBHeader h;
+    char data[SCCB_DATA_LEN];
+ } __attribute__((packed)) SCCB;
+
+/* SCLP event types */
+#define SCLP_EVENT_ASCII_CONSOLE_DATA           0x1a
+#define SCLP_EVENT_SIGNAL_QUIESCE               0x1d
+
+/* SCLP event masks */
+#define SCLP_EVENT_MASK_SIGNAL_QUIESCE          0x00000008
+#define SCLP_EVENT_MASK_MSG_ASCII               0x00000040
+
+#define SCLP_UNCONDITIONAL_READ                 0x00
+#define SCLP_SELECTIVE_READ                     0x01
+
+typedef struct WriteEventMask {
+    SCCBHeader h;
+    uint16_t _reserved;
+    uint16_t mask_length;
+    uint32_t cp_receive_mask;
+    uint32_t cp_send_mask;
+    uint32_t send_mask;
+    uint32_t receive_mask;
+} __attribute__((packed)) WriteEventMask;
+
+typedef struct EventBufferHeader {
+    uint16_t length;
+    uint8_t  type;
+    uint8_t  flags;
+    uint16_t _reserved;
+} __attribute__((packed)) EventBufferHeader;
+
+typedef struct WriteEventData {
+    SCCBHeader h;
+    EventBufferHeader ebh;
+    char data[0];
+} __attribute__((packed)) WriteEventData;
+
+typedef struct ReadEventData {
+    SCCBHeader h;
+    EventBufferHeader ebh;
+    uint32_t mask;
+} __attribute__((packed)) ReadEventData;
+
+#define __pa(x) (x)
+
+#endif /* SCLP_H */
commit 92f2ca38b01578075208799dd2f060fcc3638ed4
Author: Alexander Graf <agraf at suse.de>
Date:   Mon Apr 22 20:57:58 2013 +0200

    S390: ccw firmware: Add main program
    
    This C file is the main driving piece of the s390 ccw firmware. It
    provides a search for a workable block device, sets it as the default
    to boot off of and boots from it.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
new file mode 100644
index 0000000..0913aac
--- /dev/null
+++ b/pc-bios/s390-ccw/main.c
@@ -0,0 +1,56 @@
+/*
+ * S390 virtio-ccw loading program
+ *
+ * Copyright (c) 2013 Alexander Graf <agraf at suse.de>
+ *
+ * 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 "s390-ccw.h"
+
+struct subchannel_id blk_schid;
+char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
+
+void virtio_panic(const char *string)
+{
+    sclp_print(string);
+    while (1) { }
+}
+
+static void virtio_setup(void)
+{
+    struct irb irb;
+    int i;
+    int r;
+    bool found = false;
+
+    blk_schid.one = 1;
+
+    for (i = 0; i < 0x10000; i++) {
+        blk_schid.sch_no = i;
+        r = tsch(blk_schid, &irb);
+        if (r != 3) {
+            if (virtio_is_blk(blk_schid)) {
+                found = true;
+                break;
+            }
+        }
+    }
+
+    if (!found) {
+        virtio_panic("No virtio-blk device found!\n");
+    }
+
+    virtio_setup_block(blk_schid);
+}
+
+int main(void)
+{
+    sclp_setup();
+    virtio_setup();
+    if (zipl_load() < 0)
+        sclp_print("Failed to load OS from hard disk\n");
+    while (1) { }
+}
commit 80fea6e8930384d7d8adae0eb1a00acb7647f7ec
Author: Alexander Graf <agraf at suse.de>
Date:   Mon Apr 22 20:56:08 2013 +0200

    S390: ccw firmware: Add start assembly
    
    We want to write most of our code in C, so add a small assembly
    stub that jumps straight into C code for us to continue booting.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/pc-bios/s390-ccw/start.S b/pc-bios/s390-ccw/start.S
new file mode 100644
index 0000000..c2b9a19
--- /dev/null
+++ b/pc-bios/s390-ccw/start.S
@@ -0,0 +1,16 @@
+/*
+ * First stage boot loader for virtio devices. The compiled output goes
+ * into the pc-bios directory of qemu.
+ *
+ * Copyright (c) 2013 Alexander Graf <agraf at suse.de>
+ *
+ * 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.
+ */
+
+        .globl _start
+_start:
+
+larl	%r15, stack + 0x8000    /* Set up stack */
+j	main                    /* And call C */
commit d0249ce5a8d11564958262fd567d1ea770358134
Author: Alexander Graf <agraf at suse.de>
Date:   Mon Apr 22 16:52:53 2013 +0200

    S390: IPL: Use different firmware for different machines
    
    We have a virtio-s390 and a virtio-ccw machine in QEMU. Both use vastly
    different ways to do I/O. Having the same firmware blob for both doesn't
    really make any sense.
    
    Instead, let's parametrize the firmware file name, so that we can have
    different blobs for different machines.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index d1f7acd..ace5ff5 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -23,7 +23,6 @@
 #define INITRD_PARM_START               0x010408UL
 #define INITRD_PARM_SIZE                0x010410UL
 #define PARMFILE_START                  0x001000UL
-#define ZIPL_FILENAME                   "s390-zipl.rom"
 #define ZIPL_IMAGE_START                0x009000UL
 #define IPL_PSW_MASK                    (PSW_MASK_32 | PSW_MASK_64)
 
@@ -54,6 +53,7 @@ typedef struct S390IPLState {
     char *kernel;
     char *initrd;
     char *cmdline;
+    char *firmware;
 } S390IPLState;
 
 
@@ -78,7 +78,7 @@ static int s390_ipl_init(SysBusDevice *dev)
 
         /* Load zipl bootloader */
         if (bios_name == NULL) {
-            bios_name = ZIPL_FILENAME;
+            bios_name = ipl->firmware;
         }
 
         bios_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
@@ -144,6 +144,7 @@ static Property s390_ipl_properties[] = {
     DEFINE_PROP_STRING("kernel", S390IPLState, kernel),
     DEFINE_PROP_STRING("initrd", S390IPLState, initrd),
     DEFINE_PROP_STRING("cmdline", S390IPLState, cmdline),
+    DEFINE_PROP_STRING("firmware", S390IPLState, firmware),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index a49e440..8ea193e 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -83,7 +83,7 @@ static void ccw_init(QEMUMachineInitArgs *args)
     css_bus = virtual_css_bus_init();
     s390_sclp_init();
     s390_init_ipl_dev(args->kernel_filename, args->kernel_cmdline,
-                      args->initrd_filename);
+                      args->initrd_filename, "s390-zipl.rom");
 
     /* register hypercalls */
     virtio_ccw_register_hcalls();
diff --git a/hw/s390x/s390-virtio.c b/hw/s390x/s390-virtio.c
index 46aec99..30d1118 100644
--- a/hw/s390x/s390-virtio.c
+++ b/hw/s390x/s390-virtio.c
@@ -49,6 +49,7 @@
 #endif
 
 #define MAX_BLK_DEVS                    10
+#define ZIPL_FILENAME                   "s390-zipl.rom"
 
 static VirtIOS390Bus *s390_bus;
 static S390CPU **ipi_states;
@@ -158,7 +159,8 @@ unsigned s390_del_running_cpu(S390CPU *cpu)
 
 void s390_init_ipl_dev(const char *kernel_filename,
                        const char *kernel_cmdline,
-                       const char *initrd_filename)
+                       const char *initrd_filename,
+                       const char *firmware)
 {
     DeviceState *dev;
 
@@ -170,6 +172,7 @@ void s390_init_ipl_dev(const char *kernel_filename,
         qdev_prop_set_string(dev, "initrd", initrd_filename);
     }
     qdev_prop_set_string(dev, "cmdline", kernel_cmdline);
+    qdev_prop_set_string(dev, "firmware", firmware);
     qdev_init_nofail(dev);
 }
 
@@ -247,7 +250,7 @@ static void s390_init(QEMUMachineInitArgs *args)
     s390_bus = s390_virtio_bus_init(&my_ram_size);
     s390_sclp_init();
     s390_init_ipl_dev(args->kernel_filename, args->kernel_cmdline,
-                      args->initrd_filename);
+                      args->initrd_filename, ZIPL_FILENAME);
 
     /* register hypercalls */
     s390_virtio_register_hcalls();
diff --git a/hw/s390x/s390-virtio.h b/hw/s390x/s390-virtio.h
index a6c4c19..5c405e7 100644
--- a/hw/s390x/s390-virtio.h
+++ b/hw/s390x/s390-virtio.h
@@ -23,6 +23,7 @@ void s390_register_virtio_hypercall(uint64_t code, s390_virtio_fn fn);
 void s390_init_cpus(const char *cpu_model, uint8_t *storage_keys);
 void s390_init_ipl_dev(const char *kernel_filename,
                        const char *kernel_cmdline,
-                       const char *initrd_filename);
+                       const char *initrd_filename,
+                       const char *firmware);
 void s390_create_virtio_net(BusState *bus, const char *name);
 #endif
commit 3325995640e0a598c4c350a1a02357b422e90973
Author: Alexander Graf <agraf at suse.de>
Date:   Mon Apr 22 16:47:32 2013 +0200

    S390: IPL: Support ELF firmware
    
    Our firmware blob is always a raw file that we load at a fixed address today.
    Support loading an ELF blob instead that we can map high up in memory.
    
    This way we don't have to be so conscious about size constraints.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index c43dfcd..d1f7acd 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -82,17 +82,21 @@ static int s390_ipl_init(SysBusDevice *dev)
         }
 
         bios_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
-        bios_size = load_image_targphys(bios_filename, ZIPL_IMAGE_START, 4096);
-        ipl->start_addr = ZIPL_IMAGE_START;
+        bios_size = load_elf(bios_filename, NULL, NULL, &ipl->start_addr, NULL,
+                             NULL, 1, ELF_MACHINE, 0);
+        if (bios_size == -1UL) {
+            bios_size = load_image_targphys(bios_filename, ZIPL_IMAGE_START,
+                                            4096);
+            ipl->start_addr = ZIPL_IMAGE_START;
+            if (bios_size > 4096) {
+                hw_error("stage1 bootloader is > 4k\n");
+            }
+        }
         g_free(bios_filename);
 
         if ((long)bios_size < 0) {
             hw_error("could not load bootloader '%s'\n", bios_name);
         }
-
-        if (bios_size > 4096) {
-            hw_error("stage1 bootloader is > 4k\n");
-        }
         return 0;
     } else {
         kernel_size = load_elf(ipl->kernel, NULL, NULL, NULL, NULL,
commit 74ad2d22c1f6e2b24412f6b2adea7d6f9a719047
Author: Alexander Graf <agraf at suse.de>
Date:   Mon Apr 22 16:44:39 2013 +0200

    S390: Make IPL reset address dynamic
    
    We can have different load addresses for different blobs we boot with.
    Make the reset IP dynamic, so that we can handle things more flexibly.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index 206d552..c43dfcd 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -48,8 +48,9 @@ typedef struct S390IPLClass {
 typedef struct S390IPLState {
     /*< private >*/
     SysBusDevice parent_obj;
-    /*< public >*/
+    uint64_t start_addr;
 
+    /*< public >*/
     char *kernel;
     char *initrd;
     char *cmdline;
@@ -82,6 +83,7 @@ static int s390_ipl_init(SysBusDevice *dev)
 
         bios_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
         bios_size = load_image_targphys(bios_filename, ZIPL_IMAGE_START, 4096);
+        ipl->start_addr = ZIPL_IMAGE_START;
         g_free(bios_filename);
 
         if ((long)bios_size < 0) {
@@ -104,6 +106,13 @@ static int s390_ipl_init(SysBusDevice *dev)
         }
         /* we have to overwrite values in the kernel image, which are "rom" */
         strcpy(rom_ptr(KERN_PARM_AREA), ipl->cmdline);
+
+        /*
+         * we can not rely on the ELF entry point, since up to 3.2 this
+         * value was 0x800 (the SALIPL loader) and it wont work. For
+         * all (Linux) cases 0x10000 (KERN_IMAGE_START) should be fine.
+         */
+        ipl->start_addr = KERN_IMAGE_START;
     }
     if (ipl->initrd) {
         ram_addr_t initrd_offset, initrd_size;
@@ -138,16 +147,7 @@ static void s390_ipl_reset(DeviceState *dev)
 {
     S390IPLState *ipl = S390_IPL(dev);
 
-    if (ipl->kernel) {
-        /*
-         * we can not rely on the ELF entry point, since up to 3.2 this
-         * value was 0x800 (the SALIPL loader) and it wont work. For
-         * all (Linux) cases 0x10000 (KERN_IMAGE_START) should be fine.
-         */
-        return s390_ipl_cpu(KERN_IMAGE_START);
-    } else {
-        return s390_ipl_cpu(ZIPL_IMAGE_START);
-    }
+    s390_ipl_cpu(ipl->start_addr);
 }
 
 static void s390_ipl_class_init(ObjectClass *klass, void *data)
commit bf9b255f484fd61cbaa91faeff254140a0ecd18c
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Apr 26 08:48:46 2013 -0500

    gtk: refactor menu creation
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/gtk.c b/ui/gtk.c
index 42e3c0a..e12f228 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -1126,7 +1126,8 @@ static gboolean gd_vc_in(GIOChannel *chan, GIOCondition cond, void *opaque)
     return TRUE;
 }
 
-static GSList *gd_vc_init(GtkDisplayState *s, VirtualConsole *vc, int index, GSList *group)
+static GSList *gd_vc_init(GtkDisplayState *s, VirtualConsole *vc, int index, GSList *group,
+                          GtkWidget *view_menu)
 {
     const char *label;
     char buffer[32];
@@ -1193,7 +1194,7 @@ static GSList *gd_vc_init(GtkDisplayState *s, VirtualConsole *vc, int index, GSL
     g_signal_connect(vc->menu_item, "activate",
                      G_CALLBACK(gd_menu_switch_vc), s);
 
-    gtk_menu_shell_append(GTK_MENU_SHELL(s->view_menu), vc->menu_item);
+    gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), vc->menu_item);
 
     qemu_chr_be_generic_open(vc->chr);
     if (vc->chr->init) {
@@ -1268,121 +1269,139 @@ static void gd_connect_signals(GtkDisplayState *s)
                      G_CALLBACK(gd_focus_out_event), s);
 }
 
-static void gd_create_menus(GtkDisplayState *s)
+static GtkWidget *gd_create_menu_machine(GtkDisplayState *s, GtkAccelGroup *accel_group)
 {
-    GtkStockItem item;
-    GtkAccelGroup *accel_group;
-    GSList *group = NULL;
+    GtkWidget *machine_menu;
     GtkWidget *separator;
-    int i;
+    GtkStockItem item;
 
-    accel_group = gtk_accel_group_new();
-    s->machine_menu = gtk_menu_new();
-    gtk_menu_set_accel_group(GTK_MENU(s->machine_menu), accel_group);
-    s->machine_menu_item = gtk_menu_item_new_with_mnemonic(_("_Machine"));
+    machine_menu = gtk_menu_new();
+    gtk_menu_set_accel_group(GTK_MENU(machine_menu), accel_group);
 
     s->pause_item = gtk_check_menu_item_new_with_mnemonic(_("_Pause"));
-    gtk_menu_shell_append(GTK_MENU_SHELL(s->machine_menu), s->pause_item);
+    gtk_menu_shell_append(GTK_MENU_SHELL(machine_menu), s->pause_item);
 
     separator = gtk_separator_menu_item_new();
-    gtk_menu_shell_append(GTK_MENU_SHELL(s->machine_menu), separator);
+    gtk_menu_shell_append(GTK_MENU_SHELL(machine_menu), separator);
 
     s->reset_item = gtk_image_menu_item_new_with_mnemonic(_("_Reset"));
-    gtk_menu_shell_append(GTK_MENU_SHELL(s->machine_menu), s->reset_item);
+    gtk_menu_shell_append(GTK_MENU_SHELL(machine_menu), s->reset_item);
 
     s->powerdown_item = gtk_image_menu_item_new_with_mnemonic(_("Power _Down"));
-    gtk_menu_shell_append(GTK_MENU_SHELL(s->machine_menu), s->powerdown_item);
+    gtk_menu_shell_append(GTK_MENU_SHELL(machine_menu), s->powerdown_item);
 
     separator = gtk_separator_menu_item_new();
-    gtk_menu_shell_append(GTK_MENU_SHELL(s->machine_menu), separator);
+    gtk_menu_shell_append(GTK_MENU_SHELL(machine_menu), separator);
 
     s->quit_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT, NULL);
     gtk_stock_lookup(GTK_STOCK_QUIT, &item);
     gtk_menu_item_set_accel_path(GTK_MENU_ITEM(s->quit_item),
                                  "<QEMU>/Machine/Quit");
     gtk_accel_map_add_entry("<QEMU>/Machine/Quit", item.keyval, item.modifier);
-    gtk_menu_shell_append(GTK_MENU_SHELL(s->machine_menu), s->quit_item);
+    gtk_menu_shell_append(GTK_MENU_SHELL(machine_menu), s->quit_item);
 
-    s->view_menu = gtk_menu_new();
-    gtk_menu_set_accel_group(GTK_MENU(s->view_menu), accel_group);
-    s->view_menu_item = gtk_menu_item_new_with_mnemonic(_("_View"));
+    return machine_menu;
+}
+
+static GtkWidget *gd_create_menu_view(GtkDisplayState *s, GtkAccelGroup *accel_group)
+{
+    GSList *group = NULL;
+    GtkWidget *view_menu;
+    GtkWidget *separator;
+    int i;
+
+    view_menu = gtk_menu_new();
+    gtk_menu_set_accel_group(GTK_MENU(view_menu), accel_group);
 
     s->full_screen_item =
         gtk_image_menu_item_new_from_stock(GTK_STOCK_FULLSCREEN, NULL);
     gtk_menu_item_set_accel_path(GTK_MENU_ITEM(s->full_screen_item),
                                  "<QEMU>/View/Full Screen");
     gtk_accel_map_add_entry("<QEMU>/View/Full Screen", GDK_KEY_f, GDK_CONTROL_MASK | GDK_MOD1_MASK);
-    gtk_menu_shell_append(GTK_MENU_SHELL(s->view_menu), s->full_screen_item);
+    gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), s->full_screen_item);
 
     separator = gtk_separator_menu_item_new();
-    gtk_menu_shell_append(GTK_MENU_SHELL(s->view_menu), separator);
+    gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), separator);
 
     s->zoom_in_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_ZOOM_IN, NULL);
     gtk_menu_item_set_accel_path(GTK_MENU_ITEM(s->zoom_in_item),
                                  "<QEMU>/View/Zoom In");
     gtk_accel_map_add_entry("<QEMU>/View/Zoom In", GDK_KEY_plus, GDK_CONTROL_MASK | GDK_MOD1_MASK);
-    gtk_menu_shell_append(GTK_MENU_SHELL(s->view_menu), s->zoom_in_item);
+    gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), s->zoom_in_item);
 
     s->zoom_out_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_ZOOM_OUT, NULL);
     gtk_menu_item_set_accel_path(GTK_MENU_ITEM(s->zoom_out_item),
                                  "<QEMU>/View/Zoom Out");
     gtk_accel_map_add_entry("<QEMU>/View/Zoom Out", GDK_KEY_minus, GDK_CONTROL_MASK | GDK_MOD1_MASK);
-    gtk_menu_shell_append(GTK_MENU_SHELL(s->view_menu), s->zoom_out_item);
+    gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), s->zoom_out_item);
 
     s->zoom_fixed_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_ZOOM_100, NULL);
     gtk_menu_item_set_accel_path(GTK_MENU_ITEM(s->zoom_fixed_item),
                                  "<QEMU>/View/Zoom Fixed");
     gtk_accel_map_add_entry("<QEMU>/View/Zoom Fixed", GDK_KEY_0, GDK_CONTROL_MASK | GDK_MOD1_MASK);
-    gtk_menu_shell_append(GTK_MENU_SHELL(s->view_menu), s->zoom_fixed_item);
+    gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), s->zoom_fixed_item);
 
     s->zoom_fit_item = gtk_check_menu_item_new_with_mnemonic(_("Zoom To _Fit"));
-    gtk_menu_shell_append(GTK_MENU_SHELL(s->view_menu), s->zoom_fit_item);
+    gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), s->zoom_fit_item);
 
     separator = gtk_separator_menu_item_new();
-    gtk_menu_shell_append(GTK_MENU_SHELL(s->view_menu), separator);
+    gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), separator);
 
     s->grab_on_hover_item = gtk_check_menu_item_new_with_mnemonic(_("Grab On _Hover"));
-    gtk_menu_shell_append(GTK_MENU_SHELL(s->view_menu), s->grab_on_hover_item);
+    gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), s->grab_on_hover_item);
 
     s->grab_item = gtk_check_menu_item_new_with_mnemonic(_("_Grab Input"));
     gtk_menu_item_set_accel_path(GTK_MENU_ITEM(s->grab_item),
                                  "<QEMU>/View/Grab Input");
     gtk_accel_map_add_entry("<QEMU>/View/Grab Input", GDK_KEY_g, GDK_CONTROL_MASK | GDK_MOD1_MASK);
-    gtk_menu_shell_append(GTK_MENU_SHELL(s->view_menu), s->grab_item);
+    gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), s->grab_item);
 
     separator = gtk_separator_menu_item_new();
-    gtk_menu_shell_append(GTK_MENU_SHELL(s->view_menu), separator);
+    gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), separator);
 
     s->vga_item = gtk_radio_menu_item_new_with_mnemonic(group, "_VGA");
     group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(s->vga_item));
     gtk_menu_item_set_accel_path(GTK_MENU_ITEM(s->vga_item),
                                  "<QEMU>/View/VGA");
     gtk_accel_map_add_entry("<QEMU>/View/VGA", GDK_KEY_1, GDK_CONTROL_MASK | GDK_MOD1_MASK);
-    gtk_menu_shell_append(GTK_MENU_SHELL(s->view_menu), s->vga_item);
+    gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), s->vga_item);
 
     for (i = 0; i < nb_vcs; i++) {
         VirtualConsole *vc = &s->vc[i];
 
-        group = gd_vc_init(s, vc, i, group);
+        group = gd_vc_init(s, vc, i, group, view_menu);
         s->nb_vcs++;
     }
 
     separator = gtk_separator_menu_item_new();
-    gtk_menu_shell_append(GTK_MENU_SHELL(s->view_menu), separator);
+    gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), separator);
 
     s->show_tabs_item = gtk_check_menu_item_new_with_mnemonic(_("Show _Tabs"));
-    gtk_menu_shell_append(GTK_MENU_SHELL(s->view_menu), s->show_tabs_item);
+    gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), s->show_tabs_item);
 
-    g_object_set_data(G_OBJECT(s->window), "accel_group", accel_group);
-    gtk_window_add_accel_group(GTK_WINDOW(s->window), accel_group);
-    s->accel_group = accel_group;
+    return view_menu;
+}
+
+static void gd_create_menus(GtkDisplayState *s)
+{
+    GtkAccelGroup *accel_group;
 
+    accel_group = gtk_accel_group_new();
+    s->machine_menu = gd_create_menu_machine(s, accel_group);
+    s->view_menu = gd_create_menu_view(s, accel_group);
+
+    s->machine_menu_item = gtk_menu_item_new_with_mnemonic(_("_Machine"));
     gtk_menu_item_set_submenu(GTK_MENU_ITEM(s->machine_menu_item),
                               s->machine_menu);
     gtk_menu_shell_append(GTK_MENU_SHELL(s->menu_bar), s->machine_menu_item);
 
+    s->view_menu_item = gtk_menu_item_new_with_mnemonic(_("_View"));
     gtk_menu_item_set_submenu(GTK_MENU_ITEM(s->view_menu_item), s->view_menu);
     gtk_menu_shell_append(GTK_MENU_SHELL(s->menu_bar), s->view_menu_item);
+
+    g_object_set_data(G_OBJECT(s->window), "accel_group", accel_group);
+    gtk_window_add_accel_group(GTK_WINDOW(s->window), accel_group);
+    s->accel_group = accel_group;
 }
 
 static const DisplayChangeListenerOps dcl_ops = {
commit c34688f9015c5dacc81efc4f2a0df5742d9c927c
Merge: 186b027 859e555
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Apr 26 08:32:17 2013 -0500

    Merge remote-tracking branch 'stefanha/block' into staging
    
    # By Liu Yuan (4) and others
    # Via Stefan Hajnoczi
    * stefanha/block:
      sheepdog: fix loadvm operation
      sheepdog: resend write requests when SD_RES_READONLY is received
      sheepdog: add helper function to reload inode
      sheepdog: add SD_RES_READONLY result code
      sheepdog: cleanup find_vdi_name
      rbd: Fix use after free in rbd_open()
      block: Disable driver-specific options for 1.5
      sheepdog: implement .bdrv_co_is_allocated()
      sheepdog: use BDRV_SECTOR_SIZE
      sheepdog: add discard/trim support for sheepdog
      block/ssh: Require libssh2 >= 1.2.8.
    
    Message-id: 1366976682-10251-1-git-send-email-stefanha at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

commit 186b027d98a3c91c1c6dee631a027d5b2a0fce25
Merge: a1bff71 6ea8430
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Apr 26 08:32:13 2013 -0500

    Merge remote-tracking branch 'stefanha/trivial-patches' into staging
    
    # By Ed Maste (2) and others
    # Via Stefan Hajnoczi
    * stefanha/trivial-patches:
      bsd-user: Track change in FreeBSD SYSCTL(9) types
      virtio: Fix compilation without CONFIG_VHOST_SCSI
      qemu-doc: Option -ignore-environment removed.
      s390x: use CONFIG_INT128 to detect __uint128_t
      linux-user: fix compile error due to stray colon at end of #ifdef line
    
    Message-id: 1366975563-16216-1-git-send-email-stefanha at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

commit 859e5553a428225de6b8ef302cdcfd68d140b926
Author: Liu Yuan <tailai.ly at taobao.com>
Date:   Thu Apr 25 20:49:39 2013 +0800

    sheepdog: fix loadvm operation
    
    Currently the 'loadvm' opertaion works as following:
    1. switch to the snapshot
    2. mark current working VDI as a snapshot
    3. rely on sd_create_branch to create a new working VDI based on the snapshot
    
    This works not the same as other format as QCOW2. For e.g,
    
    qemu > savevm # get a live snapshot snap1
    qemu > savevm # snap2
    qemu > loadvm 1 # This will steally create snap3 of the working VDI
    
    Which will result in following snapshot chain:
    
    base <-- snap1 <-- snap2 <-- snap3
              ^
              |
          working VDI
    
    snap3 was unnecessarily created and might be annoying users.
    
    This patch discard the unnecessary 'snap3' creation. and implement
    rollback(loadvm) operation to the specified snapshot by
    1. switch to the snapshot
    2. delete working VDI
    3. rely on sd_create_branch to create a new working VDI based on the snapshot
    
    The snapshot chain for above example will be:
    
    base <-- snap1 <-- snap2
              ^
              |
          working VDI
    
    Cc: qemu-devel at nongnu.org
    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: 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 77e21fd..21a4edf 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -36,6 +36,7 @@
 #define SD_OP_GET_VDI_INFO   0x14
 #define SD_OP_READ_VDIS      0x15
 #define SD_OP_FLUSH_VDI      0x16
+#define SD_OP_DEL_VDI        0x17
 
 #define SD_FLAG_CMD_WRITE    0x01
 #define SD_FLAG_CMD_COW      0x02
@@ -1666,6 +1667,43 @@ out:
     sd_finish_aiocb(acb);
 }
 
+/* Delete current working VDI on the snapshot chain */
+static bool sd_delete(BDRVSheepdogState *s)
+{
+    unsigned int wlen = SD_MAX_VDI_LEN, rlen = 0;
+    SheepdogVdiReq hdr = {
+        .opcode = SD_OP_DEL_VDI,
+        .vdi_id = s->inode.vdi_id,
+        .data_length = wlen,
+        .flags = SD_FLAG_CMD_WRITE,
+    };
+    SheepdogVdiRsp *rsp = (SheepdogVdiRsp *)&hdr;
+    int fd, ret;
+
+    fd = connect_to_sdog(s);
+    if (fd < 0) {
+        return false;
+    }
+
+    ret = do_req(fd, (SheepdogReq *)&hdr, s->name, &wlen, &rlen);
+    closesocket(fd);
+    if (ret) {
+        return false;
+    }
+    switch (rsp->result) {
+    case SD_RES_NO_VDI:
+        error_report("%s was already deleted", s->name);
+        /* fall through */
+    case SD_RES_SUCCESS:
+        break;
+    default:
+        error_report("%s, %s", sd_strerror(rsp->result), s->name);
+        return false;
+    }
+
+    return true;
+}
+
 /*
  * Create a writable VDI from a snapshot
  */
@@ -1674,12 +1712,20 @@ static int sd_create_branch(BDRVSheepdogState *s)
     int ret, fd;
     uint32_t vid;
     char *buf;
+    bool deleted;
 
     dprintf("%" PRIx32 " is snapshot.\n", s->inode.vdi_id);
 
     buf = g_malloc(SD_INODE_SIZE);
 
-    ret = do_sd_create(s, s->name, s->inode.vdi_size, s->inode.vdi_id, &vid, 1);
+    /*
+     * Even If deletion fails, we will just create extra snapshot based on
+     * the workding VDI which was supposed to be deleted. So no need to
+     * false bail out.
+     */
+    deleted = sd_delete(s);
+    ret = do_sd_create(s, s->name, s->inode.vdi_size, s->inode.vdi_id, &vid,
+                       !deleted);
     if (ret) {
         goto out;
     }
@@ -1995,6 +2041,12 @@ cleanup:
     return ret;
 }
 
+/*
+ * We implement rollback(loadvm) operation to the specified snapshot by
+ * 1) switch to the snapshot
+ * 2) rely on sd_create_branch to delete working VDI and
+ * 3) create a new working VDI based on the speicified snapshot
+ */
 static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
 {
     BDRVSheepdogState *s = bs->opaque;
commit 13c31de2fdd534c065ce4710f6e8df3921e98c4f
Author: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
Date:   Fri Apr 26 01:19:54 2013 +0900

    sheepdog: resend write requests when SD_RES_READONLY is received
    
    When a snapshot is taken from out side of qemu (e.g. qemu-img
    snapshot), write requests to the current vdi return SD_RES_READONLY.
    In this case, the sheepdog block driver needs to update the current
    inode to the latest one and resend the write requests.
    
    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 0eaf4c3..77e21fd 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -605,6 +605,7 @@ static int do_req(int sockfd, SheepdogReq *hdr, void *data,
 static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
                            struct iovec *iov, int niov, bool create,
                            enum AIOCBState aiocb_type);
+static int coroutine_fn resend_aioreq(BDRVSheepdogState *s, AIOReq *aio_req);
 
 
 static AIOReq *find_pending_req(BDRVSheepdogState *s, uint64_t oid)
@@ -749,9 +750,19 @@ static void coroutine_fn aio_read_response(void *opaque)
         }
     }
 
-    if (rsp.result != SD_RES_SUCCESS) {
+    switch (rsp.result) {
+    case SD_RES_SUCCESS:
+        break;
+    case SD_RES_READONLY:
+        ret = resend_aioreq(s, aio_req);
+        if (ret == SD_RES_SUCCESS) {
+            goto out;
+        }
+        /* fall through */
+    default:
         acb->ret = -EIO;
         error_report("%s", sd_strerror(rsp.result));
+        break;
     }
 
     free_aio_req(s, aio_req);
@@ -1186,6 +1197,53 @@ out:
     return ret;
 }
 
+static int coroutine_fn resend_aioreq(BDRVSheepdogState *s, AIOReq *aio_req)
+{
+    SheepdogAIOCB *acb = aio_req->aiocb;
+    bool create = false;
+    int ret;
+
+    ret = reload_inode(s, 0, "");
+    if (ret < 0) {
+        return ret;
+    }
+
+    aio_req->oid = vid_to_data_oid(s->inode.vdi_id,
+                                   data_oid_to_idx(aio_req->oid));
+
+    /* check whether this request becomes a CoW one */
+    if (acb->aiocb_type == AIOCB_WRITE_UDATA) {
+        int idx = data_oid_to_idx(aio_req->oid);
+        AIOReq *areq;
+
+        if (s->inode.data_vdi_id[idx] == 0) {
+            create = true;
+            goto out;
+        }
+        if (is_data_obj_writable(&s->inode, idx)) {
+            goto out;
+        }
+
+        /* link to the pending list if there is another CoW request to
+         * the same object */
+        QLIST_FOREACH(areq, &s->inflight_aio_head, aio_siblings) {
+            if (areq != aio_req && areq->oid == aio_req->oid) {
+                dprintf("simultaneous CoW to %" PRIx64 "\n", aio_req->oid);
+                QLIST_REMOVE(aio_req, aio_siblings);
+                QLIST_INSERT_HEAD(&s->pending_aio_head, aio_req, aio_siblings);
+                return SD_RES_SUCCESS;
+            }
+        }
+
+        aio_req->base_oid = vid_to_data_oid(s->inode.data_vdi_id[idx], idx);
+        aio_req->flags |= SD_FLAG_CMD_COW;
+        create = true;
+    }
+out:
+    return add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov,
+                           create, acb->aiocb_type);
+}
+
 /* TODO Convert to fine grained options */
 static QemuOptsList runtime_opts = {
     .name = "sheepdog",
commit 9ff53a0eb89afacfa1ba56b009d40be942d3bd63
Author: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
Date:   Fri Apr 26 01:19:53 2013 +0900

    sheepdog: add helper function to reload inode
    
    This adds a helper function to update the current inode state with the
    specified vdi object.
    
    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 f4e7204..0eaf4c3 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -1150,6 +1150,42 @@ static int write_object(int fd, char *buf, uint64_t oid, int copies,
                              create, cache_flags);
 }
 
+/* update inode with the latest state */
+static int reload_inode(BDRVSheepdogState *s, uint32_t snapid, const char *tag)
+{
+    SheepdogInode *inode;
+    int ret = 0, fd;
+    uint32_t vid = 0;
+
+    fd = connect_to_sdog(s);
+    if (fd < 0) {
+        return -EIO;
+    }
+
+    inode = g_malloc(sizeof(s->inode));
+
+    ret = find_vdi_name(s, s->name, snapid, tag, &vid, false);
+    if (ret) {
+        goto out;
+    }
+
+    ret = read_object(fd, (char *)inode, vid_to_vdi_oid(vid),
+                      s->inode.nr_copies, sizeof(*inode), 0, s->cache_flags);
+    if (ret < 0) {
+        goto out;
+    }
+
+    if (inode->vdi_id != s->inode.vdi_id) {
+        memcpy(&s->inode, inode, sizeof(s->inode));
+    }
+
+out:
+    g_free(inode);
+    closesocket(fd);
+
+    return ret;
+}
+
 /* TODO Convert to fine grained options */
 static QemuOptsList runtime_opts = {
     .name = "sheepdog",
@@ -1905,18 +1941,14 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
 {
     BDRVSheepdogState *s = bs->opaque;
     BDRVSheepdogState *old_s;
-    char vdi[SD_MAX_VDI_LEN], tag[SD_MAX_VDI_TAG_LEN];
-    char *buf = NULL;
-    uint32_t vid;
+    char tag[SD_MAX_VDI_TAG_LEN];
     uint32_t snapid = 0;
-    int ret = 0, fd;
+    int ret = 0;
 
     old_s = g_malloc(sizeof(BDRVSheepdogState));
 
     memcpy(old_s, s, sizeof(BDRVSheepdogState));
 
-    pstrcpy(vdi, sizeof(vdi), s->name);
-
     snapid = strtoul(snapshot_id, NULL, 10);
     if (snapid) {
         tag[0] = 0;
@@ -1924,30 +1956,11 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
         pstrcpy(tag, sizeof(tag), s->name);
     }
 
-    ret = find_vdi_name(s, vdi, snapid, tag, &vid, false);
+    ret = reload_inode(s, snapid, tag);
     if (ret) {
-        error_report("Failed to find_vdi_name");
         goto out;
     }
 
-    fd = connect_to_sdog(s);
-    if (fd < 0) {
-        ret = fd;
-        goto out;
-    }
-
-    buf = g_malloc(SD_INODE_SIZE);
-    ret = read_object(fd, buf, vid_to_vdi_oid(vid), s->inode.nr_copies,
-                      SD_INODE_SIZE, 0, s->cache_flags);
-
-    closesocket(fd);
-
-    if (ret) {
-        goto out;
-    }
-
-    memcpy(&s->inode, buf, sizeof(s->inode));
-
     if (!s->inode.vm_state_size) {
         error_report("Invalid snapshot");
         ret = -ENOENT;
@@ -1956,14 +1969,12 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
 
     s->is_snapshot = true;
 
-    g_free(buf);
     g_free(old_s);
 
     return 0;
 out:
     /* recover bdrv_sd_state */
     memcpy(s, old_s, sizeof(BDRVSheepdogState));
-    g_free(buf);
     g_free(old_s);
 
     error_report("failed to open. recover old bdrv_sd_state.");
commit 6a0b5490338ed0fdf55c43062c88dd7638f05d6d
Author: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
Date:   Fri Apr 26 01:19:52 2013 +0900

    sheepdog: add SD_RES_READONLY result code
    
    Sheepdog returns SD_RES_READONLY when qemu sends write requests to the
    snapshot vdi.  This adds the result code and makes sd_strerror() print
    its error reason.
    
    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 4326664..f4e7204 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -68,6 +68,7 @@
 #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 */
+#define SD_RES_READONLY      0x1A /* Object is read-only */
 
 /*
  * Object ID rules
@@ -349,6 +350,7 @@ static const char * sd_strerror(int err)
         {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"},
+        {SD_RES_READONLY, "Object is read-only"},
     };
 
     for (i = 0; i < ARRAY_SIZE(errors); ++i) {
commit 982dcbf4cbe80fa362c1edc37b2ced1cb8bcf37b
Author: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
Date:   Fri Apr 26 01:19:51 2013 +0900

    sheepdog: cleanup find_vdi_name
    
    This makes 'filename' and 'tag' constant variables, and renames
    'for_snapshot' to 'lock' to clear how it works.
    
    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 9f30a87..4326664 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -941,8 +941,9 @@ static int parse_vdiname(BDRVSheepdogState *s, const char *filename,
     return ret;
 }
 
-static int find_vdi_name(BDRVSheepdogState *s, char *filename, uint32_t snapid,
-                         char *tag, uint32_t *vid, int for_snapshot)
+static int find_vdi_name(BDRVSheepdogState *s, const char *filename,
+                         uint32_t snapid, const char *tag, uint32_t *vid,
+                         bool lock)
 {
     int ret, fd;
     SheepdogVdiReq hdr;
@@ -963,10 +964,10 @@ static int find_vdi_name(BDRVSheepdogState *s, char *filename, uint32_t snapid,
     strncpy(buf + SD_MAX_VDI_LEN, tag, SD_MAX_VDI_TAG_LEN);
 
     memset(&hdr, 0, sizeof(hdr));
-    if (for_snapshot) {
-        hdr.opcode = SD_OP_GET_VDI_INFO;
-    } else {
+    if (lock) {
         hdr.opcode = SD_OP_LOCK_VDI;
+    } else {
+        hdr.opcode = SD_OP_GET_VDI_INFO;
     }
     wlen = SD_MAX_VDI_LEN + SD_MAX_VDI_TAG_LEN;
     hdr.proto_ver = SD_PROTO_VER;
@@ -1205,7 +1206,7 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags)
         goto out;
     }
 
-    ret = find_vdi_name(s, vdi, snapid, tag, &vid, 0);
+    ret = find_vdi_name(s, vdi, snapid, tag, &vid, true);
     if (ret) {
         goto out;
     }
@@ -1921,7 +1922,7 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
         pstrcpy(tag, sizeof(tag), s->name);
     }
 
-    ret = find_vdi_name(s, vdi, snapid, tag, &vid, 1);
+    ret = find_vdi_name(s, vdi, snapid, tag, &vid, false);
     if (ret) {
         error_report("Failed to find_vdi_name");
         goto out;
commit c3ca988d2b0ee94dc8d53eff4b1c2de4ac06a270
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Thu Apr 25 15:59:27 2013 +0200

    rbd: Fix use after free in rbd_open()
    
    Commit a9ccedc3 frees the QemuOpts for the driver-specific options
    immediately, even though it still needs the filename string that is
    contained there. This doesn't work. Move the deletion of the QemuOpts to
    the end of the function where its content isn't needed any more.
    
    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/rbd.c b/block/rbd.c
index 1826411..0f2608b 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -478,20 +478,20 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags)
     }
 
     filename = qemu_opt_get(opts, "filename");
-    qemu_opts_del(opts);
 
     if (qemu_rbd_parsename(filename, pool, sizeof(pool),
                            snap_buf, sizeof(snap_buf),
                            s->name, sizeof(s->name),
                            conf, sizeof(conf)) < 0) {
-        return -EINVAL;
+        r = -EINVAL;
+        goto failed_opts;
     }
 
     clientname = qemu_rbd_parse_clientname(conf, clientname_buf);
     r = rados_create(&s->cluster, clientname);
     if (r < 0) {
         error_report("error initializing");
-        return r;
+        goto failed_opts;
     }
 
     s->snap = NULL;
@@ -557,6 +557,7 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags)
                             NULL, qemu_rbd_aio_flush_cb, s);
 
 
+    qemu_opts_del(opts);
     return 0;
 
 failed:
@@ -566,6 +567,8 @@ failed_open:
 failed_shutdown:
     rados_shutdown(s->cluster);
     g_free(s->snap);
+failed_opts:
+    qemu_opts_del(opts);
     return r;
 }
 
commit 8ec7d390b0d50b5e5b4b1d8dba7ba40d64a70875
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Apr 24 15:29:29 2013 +0200

    block: Disable driver-specific options for 1.5
    
    We don't want to commit to the API yet before everything is worked out.
    Disable it for the 1.5 release. This commit is meant to be reverted
    after the 1.5 release.
    
    The disabling of the driver-specific options is achieved by applying the
    old checks while parsing the command line.
    
    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/blockdev.c b/blockdev.c
index 8a1652b..6e293e9 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1656,10 +1656,120 @@ QemuOptsList qemu_drive_opts = {
     .name = "drive",
     .head = QTAILQ_HEAD_INITIALIZER(qemu_drive_opts.head),
     .desc = {
-        /*
-         * no elements => accept any params
-         * validation will happen later
-         */
+        {
+            .name = "bus",
+            .type = QEMU_OPT_NUMBER,
+            .help = "bus number",
+        },{
+            .name = "unit",
+            .type = QEMU_OPT_NUMBER,
+            .help = "unit number (i.e. lun for scsi)",
+        },{
+            .name = "if",
+            .type = QEMU_OPT_STRING,
+            .help = "interface (ide, scsi, sd, mtd, floppy, pflash, virtio)",
+        },{
+            .name = "index",
+            .type = QEMU_OPT_NUMBER,
+            .help = "index number",
+        },{
+            .name = "cyls",
+            .type = QEMU_OPT_NUMBER,
+            .help = "number of cylinders (ide disk geometry)",
+        },{
+            .name = "heads",
+            .type = QEMU_OPT_NUMBER,
+            .help = "number of heads (ide disk geometry)",
+        },{
+            .name = "secs",
+            .type = QEMU_OPT_NUMBER,
+            .help = "number of sectors (ide disk geometry)",
+        },{
+            .name = "trans",
+            .type = QEMU_OPT_STRING,
+            .help = "chs translation (auto, lba. none)",
+        },{
+            .name = "media",
+            .type = QEMU_OPT_STRING,
+            .help = "media type (disk, cdrom)",
+        },{
+            .name = "snapshot",
+            .type = QEMU_OPT_BOOL,
+            .help = "enable/disable snapshot mode",
+        },{
+            .name = "file",
+            .type = QEMU_OPT_STRING,
+            .help = "disk image",
+        },{
+            .name = "discard",
+            .type = QEMU_OPT_STRING,
+            .help = "discard operation (ignore/off, unmap/on)",
+        },{
+            .name = "cache",
+            .type = QEMU_OPT_STRING,
+            .help = "host cache usage (none, writeback, writethrough, "
+                    "directsync, unsafe)",
+        },{
+            .name = "aio",
+            .type = QEMU_OPT_STRING,
+            .help = "host AIO implementation (threads, native)",
+        },{
+            .name = "format",
+            .type = QEMU_OPT_STRING,
+            .help = "disk format (raw, qcow2, ...)",
+        },{
+            .name = "serial",
+            .type = QEMU_OPT_STRING,
+            .help = "disk serial number",
+        },{
+            .name = "rerror",
+            .type = QEMU_OPT_STRING,
+            .help = "read error action",
+        },{
+            .name = "werror",
+            .type = QEMU_OPT_STRING,
+            .help = "write error action",
+        },{
+            .name = "addr",
+            .type = QEMU_OPT_STRING,
+            .help = "pci address (virtio only)",
+        },{
+            .name = "readonly",
+            .type = QEMU_OPT_BOOL,
+            .help = "open drive file as read-only",
+        },{
+            .name = "iops",
+            .type = QEMU_OPT_NUMBER,
+            .help = "limit total I/O operations per second",
+        },{
+            .name = "iops_rd",
+            .type = QEMU_OPT_NUMBER,
+            .help = "limit read operations per second",
+        },{
+            .name = "iops_wr",
+            .type = QEMU_OPT_NUMBER,
+            .help = "limit write operations per second",
+        },{
+            .name = "bps",
+            .type = QEMU_OPT_NUMBER,
+            .help = "limit total bytes per second",
+        },{
+            .name = "bps_rd",
+            .type = QEMU_OPT_NUMBER,
+            .help = "limit read bytes per second",
+        },{
+            .name = "bps_wr",
+            .type = QEMU_OPT_NUMBER,
+            .help = "limit write bytes per second",
+        },{
+            .name = "copy-on-read",
+            .type = QEMU_OPT_BOOL,
+            .help = "copy read data from backing file into image file",
+        },{
+            .name = "boot",
+            .type = QEMU_OPT_BOOL,
+            .help = "(deprecated, ignored)",
+        },
         { /* end of list */ }
     },
 };
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index 68eabda..bf944d9 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -57,6 +57,6 @@
 048 img auto quick
 049 rw auto
 050 rw auto backing quick
-051 rw auto
+#051 rw auto
 052 rw auto backing
 053 rw auto
commit 8d71c63137600a41b5b959217c0492278536b3dc
Author: Liu Yuan <tailai.ly at taobao.com>
Date:   Tue Apr 23 14:03:35 2013 +0800

    sheepdog: implement .bdrv_co_is_allocated()
    
    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>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/sheepdog.c b/block/sheepdog.c
index 2772e8e..9f30a87 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -2165,6 +2165,40 @@ static coroutine_fn int sd_co_discard(BlockDriverState *bs, int64_t sector_num,
     return acb->ret;
 }
 
+static coroutine_fn int
+sd_co_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
+                   int *pnum)
+{
+    BDRVSheepdogState *s = bs->opaque;
+    SheepdogInode *inode = &s->inode;
+    unsigned long start = sector_num * BDRV_SECTOR_SIZE / SD_DATA_OBJ_SIZE,
+                  end = DIV_ROUND_UP((sector_num + nb_sectors) *
+                                     BDRV_SECTOR_SIZE, SD_DATA_OBJ_SIZE);
+    unsigned long idx;
+    int ret = 1;
+
+    for (idx = start; idx < end; idx++) {
+        if (inode->data_vdi_id[idx] == 0) {
+            break;
+        }
+    }
+    if (idx == start) {
+        /* Get the longest length of unallocated sectors */
+        ret = 0;
+        for (idx = start + 1; idx < end; idx++) {
+            if (inode->data_vdi_id[idx] != 0) {
+                break;
+            }
+        }
+    }
+
+    *pnum = (idx - start) * SD_DATA_OBJ_SIZE / BDRV_SECTOR_SIZE;
+    if (*pnum > nb_sectors) {
+        *pnum = nb_sectors;
+    }
+    return ret;
+}
+
 static QEMUOptionParameter sd_create_options[] = {
     {
         .name = BLOCK_OPT_SIZE,
@@ -2198,6 +2232,7 @@ static BlockDriver bdrv_sheepdog = {
     .bdrv_co_writev = sd_co_writev,
     .bdrv_co_flush_to_disk  = sd_co_flush_to_disk,
     .bdrv_co_discard = sd_co_discard,
+    .bdrv_co_is_allocated = sd_co_is_allocated,
 
     .bdrv_snapshot_create   = sd_snapshot_create,
     .bdrv_snapshot_goto     = sd_snapshot_goto,
@@ -2224,6 +2259,7 @@ static BlockDriver bdrv_sheepdog_tcp = {
     .bdrv_co_writev = sd_co_writev,
     .bdrv_co_flush_to_disk  = sd_co_flush_to_disk,
     .bdrv_co_discard = sd_co_discard,
+    .bdrv_co_is_allocated = sd_co_is_allocated,
 
     .bdrv_snapshot_create   = sd_snapshot_create,
     .bdrv_snapshot_goto     = sd_snapshot_goto,
@@ -2250,6 +2286,7 @@ static BlockDriver bdrv_sheepdog_unix = {
     .bdrv_co_writev = sd_co_writev,
     .bdrv_co_flush_to_disk  = sd_co_flush_to_disk,
     .bdrv_co_discard = sd_co_discard,
+    .bdrv_co_is_allocated = sd_co_is_allocated,
 
     .bdrv_snapshot_create   = sd_snapshot_create,
     .bdrv_snapshot_goto     = sd_snapshot_goto,
commit e8bfaa2faeb7c9585a5586aafaad5f3affc37814
Author: Liu Yuan <tailai.ly at taobao.com>
Date:   Tue Apr 23 14:03:34 2013 +0800

    sheepdog: use BDRV_SECTOR_SIZE
    
    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>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/sheepdog.c b/block/sheepdog.c
index 6a72c1e..2772e8e 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -89,7 +89,6 @@
 #define SD_NR_VDIS   (1U << 24)
 #define SD_DATA_OBJ_SIZE (UINT64_C(1) << 22)
 #define SD_MAX_VDI_SIZE (SD_DATA_OBJ_SIZE * MAX_DATA_OBJS)
-#define SECTOR_SIZE 512
 
 #define SD_INODE_SIZE (sizeof(SheepdogInode))
 #define CURRENT_VDI_ID 0
@@ -1246,7 +1245,7 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags)
     s->min_dirty_data_idx = UINT32_MAX;
     s->max_dirty_data_idx = 0;
 
-    bs->total_sectors = s->inode.vdi_size / SECTOR_SIZE;
+    bs->total_sectors = s->inode.vdi_size / BDRV_SECTOR_SIZE;
     pstrcpy(s->name, sizeof(s->name), vdi);
     qemu_co_mutex_init(&s->lock);
     qemu_opts_del(opts);
@@ -1633,10 +1632,10 @@ static int coroutine_fn sd_co_rw_vector(void *p)
 {
     SheepdogAIOCB *acb = p;
     int ret = 0;
-    unsigned long len, done = 0, total = acb->nb_sectors * SECTOR_SIZE;
-    unsigned long idx = acb->sector_num * SECTOR_SIZE / SD_DATA_OBJ_SIZE;
+    unsigned long len, done = 0, total = acb->nb_sectors * BDRV_SECTOR_SIZE;
+    unsigned long idx = acb->sector_num * BDRV_SECTOR_SIZE / SD_DATA_OBJ_SIZE;
     uint64_t oid;
-    uint64_t offset = (acb->sector_num * SECTOR_SIZE) % SD_DATA_OBJ_SIZE;
+    uint64_t offset = (acb->sector_num * BDRV_SECTOR_SIZE) % SD_DATA_OBJ_SIZE;
     BDRVSheepdogState *s = acb->common.bs->opaque;
     SheepdogInode *inode = &s->inode;
     AIOReq *aio_req;
@@ -1755,7 +1754,7 @@ static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
     int ret;
 
     if (bs->growable && sector_num + nb_sectors > bs->total_sectors) {
-        ret = sd_truncate(bs, (sector_num + nb_sectors) * SECTOR_SIZE);
+        ret = sd_truncate(bs, (sector_num + nb_sectors) * BDRV_SECTOR_SIZE);
         if (ret < 0) {
             return ret;
         }
commit cac8f4a60fc5c372bacd59eeff0646955fb4f246
Author: Liu Yuan <tailai.ly at taobao.com>
Date:   Tue Apr 23 14:03:33 2013 +0800

    sheepdog: add discard/trim support for sheepdog
    
    The 'TRIM' command from VM that is to release underlying data storage for
    better thin-provision is already supported by the Sheepdog.
    
    This patch adds the TRIM support at QEMU part.
    
    For older Sheepdog that doesn't support it, we return 0(success) to upper layer.
    
    Cc: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
    Cc: Kevin Wolf <kwolf at redhat.com>
    Cc: Stefan Hajnoczi <stefanha at redhat.com>
    Cc: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Liu Yuan <tailai.ly at taobao.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/sheepdog.c b/block/sheepdog.c
index 20b5d06..6a72c1e 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -27,6 +27,8 @@
 #define SD_OP_CREATE_AND_WRITE_OBJ  0x01
 #define SD_OP_READ_OBJ       0x02
 #define SD_OP_WRITE_OBJ      0x03
+/* 0x04 is used internally by Sheepdog */
+#define SD_OP_DISCARD_OBJ    0x05
 
 #define SD_OP_NEW_VDI        0x11
 #define SD_OP_LOCK_VDI       0x12
@@ -269,6 +271,7 @@ enum AIOCBState {
     AIOCB_WRITE_UDATA,
     AIOCB_READ_UDATA,
     AIOCB_FLUSH_CACHE,
+    AIOCB_DISCARD_OBJ,
 };
 
 struct SheepdogAIOCB {
@@ -298,6 +301,7 @@ typedef struct BDRVSheepdogState {
     char name[SD_MAX_VDI_LEN];
     bool is_snapshot;
     uint32_t cache_flags;
+    bool discard_supported;
 
     char *host_spec;
     bool is_unix;
@@ -656,7 +660,7 @@ static void coroutine_fn aio_read_response(void *opaque)
     int ret;
     AIOReq *aio_req = NULL;
     SheepdogAIOCB *acb;
-    unsigned long idx;
+    uint64_t idx;
 
     if (QLIST_EMPTY(&s->inflight_aio_head)) {
         goto out;
@@ -727,6 +731,21 @@ static void coroutine_fn aio_read_response(void *opaque)
             rsp.result = SD_RES_SUCCESS;
         }
         break;
+    case AIOCB_DISCARD_OBJ:
+        switch (rsp.result) {
+        case SD_RES_INVALID_PARMS:
+            error_report("sheep(%s) doesn't support discard command",
+                         s->host_spec);
+            rsp.result = SD_RES_SUCCESS;
+            s->discard_supported = false;
+            break;
+        case SD_RES_SUCCESS:
+            idx = data_oid_to_idx(aio_req->oid);
+            s->inode.data_vdi_id[idx] = 0;
+            break;
+        default:
+            break;
+        }
     }
 
     if (rsp.result != SD_RES_SUCCESS) {
@@ -1016,6 +1035,9 @@ static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
         wlen = datalen;
         hdr.flags = SD_FLAG_CMD_WRITE | flags;
         break;
+    case AIOCB_DISCARD_OBJ:
+        hdr.opcode = SD_OP_DISCARD_OBJ;
+        break;
     }
 
     if (s->cache_flags) {
@@ -1197,6 +1219,7 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags)
     if (flags & BDRV_O_NOCACHE) {
         s->cache_flags = SD_FLAG_CMD_DIRECT;
     }
+    s->discard_supported = true;
 
     if (snapid || tag[0] != '\0') {
         dprintf("%" PRIx32 " snapshot inode was open.\n", vid);
@@ -1662,6 +1685,15 @@ static int coroutine_fn sd_co_rw_vector(void *p)
                 flags = SD_FLAG_CMD_COW;
             }
             break;
+        case AIOCB_DISCARD_OBJ:
+            /*
+             * We discard the object only when the whole object is
+             * 1) allocated 2) trimmed. Otherwise, simply skip it.
+             */
+            if (len != SD_DATA_OBJ_SIZE || inode->data_vdi_id[idx] == 0) {
+                goto done;
+            }
+            break;
         default:
             break;
         }
@@ -2107,6 +2139,33 @@ static int sd_load_vmstate(BlockDriverState *bs, uint8_t *data,
 }
 
 
+static coroutine_fn int sd_co_discard(BlockDriverState *bs, int64_t sector_num,
+                                      int nb_sectors)
+{
+    SheepdogAIOCB *acb;
+    QEMUIOVector dummy;
+    BDRVSheepdogState *s = bs->opaque;
+    int ret;
+
+    if (!s->discard_supported) {
+            return 0;
+    }
+
+    acb = sd_aio_setup(bs, &dummy, sector_num, nb_sectors);
+    acb->aiocb_type = AIOCB_DISCARD_OBJ;
+    acb->aio_done_func = sd_finish_aiocb;
+
+    ret = sd_co_rw_vector(acb);
+    if (ret <= 0) {
+        qemu_aio_release(acb);
+        return ret;
+    }
+
+    qemu_coroutine_yield();
+
+    return acb->ret;
+}
+
 static QEMUOptionParameter sd_create_options[] = {
     {
         .name = BLOCK_OPT_SIZE,
@@ -2139,6 +2198,7 @@ static BlockDriver bdrv_sheepdog = {
     .bdrv_co_readv  = sd_co_readv,
     .bdrv_co_writev = sd_co_writev,
     .bdrv_co_flush_to_disk  = sd_co_flush_to_disk,
+    .bdrv_co_discard = sd_co_discard,
 
     .bdrv_snapshot_create   = sd_snapshot_create,
     .bdrv_snapshot_goto     = sd_snapshot_goto,
@@ -2164,6 +2224,7 @@ static BlockDriver bdrv_sheepdog_tcp = {
     .bdrv_co_readv  = sd_co_readv,
     .bdrv_co_writev = sd_co_writev,
     .bdrv_co_flush_to_disk  = sd_co_flush_to_disk,
+    .bdrv_co_discard = sd_co_discard,
 
     .bdrv_snapshot_create   = sd_snapshot_create,
     .bdrv_snapshot_goto     = sd_snapshot_goto,
@@ -2189,6 +2250,7 @@ static BlockDriver bdrv_sheepdog_unix = {
     .bdrv_co_readv  = sd_co_readv,
     .bdrv_co_writev = sd_co_writev,
     .bdrv_co_flush_to_disk  = sd_co_flush_to_disk,
+    .bdrv_co_discard = sd_co_discard,
 
     .bdrv_snapshot_create   = sd_snapshot_create,
     .bdrv_snapshot_goto     = sd_snapshot_goto,
commit 4fc16838b8392a29644d4d2c01495e6ff447a6f0
Author: Richard W.M. Jones <rjones at redhat.com>
Date:   Fri Apr 19 09:16:39 2013 +0100

    block/ssh: Require libssh2 >= 1.2.8.
    
    libssh2 >= 1.2.8 is required to enable this block device (because
    that version introduced the libssh2_session_handshake call).
    
    Change the test to use pkg-config exclusively.  If the user requests
    --enable-libssh2 and the minimum version is not available, then the
    following error is displayed:
    
      $ ./configure --enable-libssh2
    
      ERROR: libssh2 >= 1.2.8 required for --enable-libssh2
    
    If --enable-libssh2 is not specified, then the feature is silently
    disabled if sufficiently new libssh2 is not available.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/configure b/configure
index ee2e7e8..8188a7c 100755
--- a/configure
+++ b/configure
@@ -2364,35 +2364,19 @@ fi
 
 ##########################################
 # libssh2 probe
+min_libssh2_version=1.2.8
 if test "$libssh2" != "no" ; then
-  cat > $TMPC <<EOF
-#include <stdio.h>
-#include <libssh2.h>
-#include <libssh2_sftp.h>
-int main(void) {
-    LIBSSH2_SESSION *session;
-    session = libssh2_session_init ();
-    (void) libssh2_sftp_init (session);
-    return 0;
-}
-EOF
-
-  if $pkg_config libssh2 --modversion >/dev/null 2>&1; then
+  if $pkg_config --atleast-version=$min_libssh2_version libssh2 >/dev/null 2>&1
+  then
     libssh2_cflags=`$pkg_config libssh2 --cflags`
     libssh2_libs=`$pkg_config libssh2 --libs`
-  else
-    libssh2_cflags=
-    libssh2_libs="-lssh2"
-  fi
-
-  if compile_prog "$libssh2_cflags" "$libssh2_libs" ; then
     libssh2=yes
     libs_tools="$libssh2_libs $libs_tools"
     libs_softmmu="$libssh2_libs $libs_softmmu"
     QEMU_CFLAGS="$QEMU_CFLAGS $libssh2_cflags"
   else
     if test "$libssh2" = "yes" ; then
-      feature_not_found "libssh2"
+      error_exit "libssh2 >= $min_libssh2_version required for --enable-libssh2"
     fi
     libssh2=no
   fi
commit 6ea8430d98c48eb67e47d14dfe8c0fdb86413555
Author: Ed Maste <emaste at freebsd.org>
Date:   Thu Apr 25 13:59:41 2013 -0400

    bsd-user: Track change in FreeBSD SYSCTL(9) types
    
    Originally from Garrett Cooper in FreeBSD PR ports/155558
    http://www.freebsd.org/cgi/query-pr.cgi?pr=155558
    
    Signed-off-by: Ed Maste <emaste at freebsd.org>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c
index 18b43f1..69e3466 100644
--- a/bsd-user/syscall.c
+++ b/bsd-user/syscall.c
@@ -211,7 +211,11 @@ static int sysctl_oldcvt(void *holdp, size_t holdlen, uint32_t kind)
         *(uint64_t *)holdp = tswap64(*(unsigned long *)holdp);
         break;
 #endif
+#if !defined(__FreeBSD_version) || __FreeBSD_version < 900031
     case CTLTYPE_QUAD:
+#else
+    case CTLTYPE_U64:
+#endif
         *(uint64_t *)holdp = tswap64(*(uint64_t *)holdp);
         break;
     case CTLTYPE_STRING:
commit b702d2aebeb6b1392f42262f537f70e6890233a7
Author: Ed Maste <emaste at freebsd.org>
Date:   Thu Apr 25 13:38:28 2013 -0400

    virtio: Fix compilation without CONFIG_VHOST_SCSI
    
    Signed-off-by: Ed Maste <emaste at freebsd.org>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c
index cf51a85..a7e81d1 100644
--- a/hw/s390x/s390-virtio-bus.c
+++ b/hw/s390x/s390-virtio-bus.c
@@ -691,7 +691,9 @@ static void s390_virtio_register_types(void)
     type_register_static(&s390_virtio_blk);
     type_register_static(&s390_virtio_net);
     type_register_static(&s390_virtio_scsi);
+#ifdef CONFIG_VHOST_SCSI
     type_register_static(&s390_vhost_scsi);
+#endif
     type_register_static(&s390_virtio_rng);
     type_register_static(&s390_virtio_bridge_info);
 }
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index b857413..c0f2646 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -1095,7 +1095,9 @@ static void virtio_ccw_register(void)
     type_register_static(&virtio_ccw_net);
     type_register_static(&virtio_ccw_balloon);
     type_register_static(&virtio_ccw_scsi);
+#ifdef CONFIG_VHOST_SCSI
     type_register_static(&vhost_ccw_scsi);
+#endif
     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 04ba1b9..121a5f8 100644
--- a/hw/s390x/virtio-ccw.h
+++ b/hw/s390x/virtio-ccw.h
@@ -101,6 +101,7 @@ typedef struct VirtIOSCSICcw {
     VirtIOSCSI vdev;
 } VirtIOSCSICcw;
 
+#ifdef CONFIG_VHOST_SCSI
 /* vhost-scsi-ccw */
 
 #define TYPE_VHOST_SCSI_CCW "vhost-scsi-ccw"
@@ -111,6 +112,7 @@ typedef struct VHostSCSICcw {
     VirtioCcwDevice parent_obj;
     VHostSCSI vdev;
 } VHostSCSICcw;
+#endif
 
 /* virtio-blk-ccw */
 
commit 48c75f484de13d59df6ae0e6becfe4ad4cd41ad5
Author: Thomas Schwinge <thomas at codesourcery.com>
Date:   Thu Apr 25 18:41:16 2013 +0200

    qemu-doc: Option -ignore-environment removed.
    
    Has been removed in commit fc9c54124d134dbd76338a92a91804dab2df8166.
    
    Signed-off-by: Thomas Schwinge <thomas at codesourcery.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/qemu-doc.texi b/qemu-doc.texi
index dfea4d3..64493eb 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -2683,9 +2683,6 @@ Set the x86 elf interpreter prefix (default=/usr/local/qemu-i386)
 Set the x86 stack size in bytes (default=524288)
 @item -cpu model
 Select CPU model (-cpu help for list and additional feature selection)
- at item -ignore-environment
-Start with an empty environment. Without this option,
-the initial environment is a copy of the caller's environment.
 @item -E @var{var}=@var{value}
 Set environment @var{var} to @var{value}.
 @item -U @var{var}
commit d49b8e0b299df3f0472945eb6d33b8413d102046
Author: Gabriel Kerneis <gabriel at kerneis.info>
Date:   Tue Apr 23 18:15:12 2013 +0100

    s390x: use CONFIG_INT128 to detect __uint128_t
    
    Target s390x uses ad-hoc macro magic to guess if the compiler
    supports the GCC extension __uint128_t.  This patch uses the
    the dedicated macro CONFIG_INT128 defined by configure instead.
    
    This fixes compilation with the CIL source code analyzer, which
    uses GCC as a preprocessor but does not support __uint128_t.
    
    Signed-off-by: Gabriel Kerneis <gabriel at kerneis.info>
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/target-s390x/int_helper.c b/target-s390x/int_helper.c
index af16b21..85e49aa 100644
--- a/target-s390x/int_helper.c
+++ b/target-s390x/int_helper.c
@@ -97,8 +97,7 @@ uint64_t HELPER(divu64)(CPUS390XState *env, uint64_t ah, uint64_t al,
         ret = al / b;
     } else {
         /* ??? Move i386 idivq helper to host-utils.  */
-#if HOST_LONG_BITS == 64 && defined(__GNUC__)
-        /* assuming 64-bit hosts have __uint128_t */
+#ifdef CONFIG_INT128
         __uint128_t a = ((__uint128_t)ah << 64) | al;
         __uint128_t q = a / b;
         env->retxl = a % b;
commit 7edd2cf1a2eace84e3f8753e912449ae8871802f
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sun Apr 21 13:30:03 2013 +0100

    linux-user: fix compile error due to stray colon at end of #ifdef line
    
    Remove a stray colon from the end of a #ifdef line. Some versions
    of gcc complain about this:
     linux-user/syscall.c: In function ‘do_syscall’:
     linux-user/syscall.c:7606:28: error: extra tokens at end of #ifdef directive [-Werror]
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Acked-By: Riku Voipio <riku.voipio at linaro.org>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index c705960..30e93bc 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -7603,7 +7603,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 #endif
 #else
     case TARGET_NR_sendfile:
-#ifdef TARGET_NR_sendfile64:
+#ifdef TARGET_NR_sendfile64
     case TARGET_NR_sendfile64:
 #endif
         goto unimplemented;
commit a1bff71c56f2d1048244c829b63797940dd4ba0e
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date:   Tue Apr 23 14:27:09 2013 +0200

    microblaze: Add internal base vectors reg
    
    Configurable at CPU synthesis/instantiation.
    
    Reviewed-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/target-microblaze/cpu-qom.h b/target-microblaze/cpu-qom.h
index aa51cf6..ce92a4e 100644
--- a/target-microblaze/cpu-qom.h
+++ b/target-microblaze/cpu-qom.h
@@ -56,6 +56,7 @@ typedef struct MicroBlazeCPUClass {
 typedef struct MicroBlazeCPU {
     /*< private >*/
     CPUState parent_obj;
+    uint32_t base_vectors;
     /*< public >*/
 
     CPUMBState env;
diff --git a/target-microblaze/cpu.c b/target-microblaze/cpu.c
index 0f4293d..404f82c 100644
--- a/target-microblaze/cpu.c
+++ b/target-microblaze/cpu.c
@@ -22,6 +22,7 @@
 
 #include "cpu.h"
 #include "qemu-common.h"
+#include "hw/qdev-properties.h"
 #include "migration/vmstate.h"
 
 
@@ -119,6 +120,11 @@ static const VMStateDescription vmstate_mb_cpu = {
     .unmigratable = 1,
 };
 
+static Property mb_properties[] = {
+    DEFINE_PROP_UINT32("xlnx.base-vectors", MicroBlazeCPU, base_vectors, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
 static void mb_cpu_class_init(ObjectClass *oc, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(oc);
@@ -133,6 +139,8 @@ static void mb_cpu_class_init(ObjectClass *oc, void *data)
 
     cc->do_interrupt = mb_cpu_do_interrupt;
     dc->vmsd = &vmstate_mb_cpu;
+
+    dc->props = mb_properties;
 }
 
 static const TypeInfo mb_cpu_type_info = {
diff --git a/target-microblaze/helper.c b/target-microblaze/helper.c
index a0416d0..0dd669d 100644
--- a/target-microblaze/helper.c
+++ b/target-microblaze/helper.c
@@ -152,7 +152,7 @@ void mb_cpu_do_interrupt(CPUState *cs)
                           env->sregs[SR_ESR], env->iflags);
             log_cpu_state_mask(CPU_LOG_INT, env, 0);
             env->iflags &= ~(IMM_FLAG | D_FLAG);
-            env->sregs[SR_PC] = 0x20;
+            env->sregs[SR_PC] = cpu->base_vectors + 0x20;
             break;
 
         case EXCP_MMU:
@@ -192,7 +192,7 @@ void mb_cpu_do_interrupt(CPUState *cs)
                           env->sregs[SR_PC], env->sregs[SR_EAR], env->iflags);
             log_cpu_state_mask(CPU_LOG_INT, env, 0);
             env->iflags &= ~(IMM_FLAG | D_FLAG);
-            env->sregs[SR_PC] = 0x20;
+            env->sregs[SR_PC] = cpu->base_vectors + 0x20;
             break;
 
         case EXCP_IRQ:
@@ -233,7 +233,7 @@ void mb_cpu_do_interrupt(CPUState *cs)
             env->sregs[SR_MSR] |= t;
 
             env->regs[14] = env->sregs[SR_PC];
-            env->sregs[SR_PC] = 0x10;
+            env->sregs[SR_PC] = cpu->base_vectors + 0x10;
             //log_cpu_state_mask(CPU_LOG_INT, env, 0);
             break;
 
@@ -252,7 +252,7 @@ void mb_cpu_do_interrupt(CPUState *cs)
             if (env->exception_index == EXCP_HW_BREAK) {
                 env->regs[16] = env->sregs[SR_PC];
                 env->sregs[SR_MSR] |= MSR_BIP;
-                env->sregs[SR_PC] = 0x18;
+                env->sregs[SR_PC] = cpu->base_vectors + 0x18;
             } else
                 env->sregs[SR_PC] = env->btarget;
             break;
commit e3351000cd682200835763caca87adf708ed1c65
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Mon Apr 22 14:41:28 2013 +1000

    Makefile: Use QEMU_FLAGS for DTC compilation
    
    Build DTC as QEMU is built. Fixes the issue with mingw build which can't
    handles DTC's default CFLAGS.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/Makefile b/Makefile
index 5140c19..e652764 100644
--- a/Makefile
+++ b/Makefile
@@ -146,10 +146,10 @@ $(SRC_PATH)/pixman/configure:
 	(cd $(SRC_PATH)/pixman; autoreconf -v --install)
 
 DTC_MAKE_ARGS=-I$(SRC_PATH)/dtc VPATH=$(SRC_PATH)/dtc -C dtc V="$(V)" LIBFDT_srcdir=$(SRC_PATH)/dtc/libfdt
-DTC_CFLAGS=$(CFLAGS) $(extra_cflags) -I$(BUILD_DIR)/dtc -I$(SRC_PATH)/dtc -I$(SRC_PATH)/dtc/libfdt
+DTC_CFLAGS=$(CFLAGS) $(QEMU_CFLAGS) -I$(BUILD_DIR)/dtc -I$(SRC_PATH)/dtc -I$(SRC_PATH)/dtc/libfdt
 
 subdir-dtc:dtc/libfdt dtc/tests
-	$(call quiet-command,$(MAKE) $(DTC_MAKE_ARGS) CPPFLAGS="$(DTC_CFLAGS)" LDFLAGS="$(LDFLAGS)" ARFLAGS="$(ARFLAGS)" CC="$(CC)" AR="$(AR)" LD="$(LD)" $(SUBDIR_MAKEFLAGS) libfdt/libfdt.a,)
+	$(call quiet-command,$(MAKE) $(DTC_MAKE_ARGS) CFLAGS="$(DTC_CFLAGS)" LDFLAGS="$(LDFLAGS)" ARFLAGS="$(ARFLAGS)" CC="$(CC)" AR="$(AR)" LD="$(LD)" $(SUBDIR_MAKEFLAGS) libfdt/libfdt.a,)
 
 dtc/%:
 	mkdir -p $@
commit 9005a51b096272e1834638f8e184706548ee7364
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Mon Apr 22 14:40:49 2013 +1000

    Makefile: Don't build shared libfdt
    
    The submodule DTC should just build and use DTC as static (the whole
    motivation for using submod is lack of widespread distro support).
    
    The .so causes build failures on some platforms, so adjust the make
    target to just build the static lib.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/Makefile b/Makefile
index efb1c44..5140c19 100644
--- a/Makefile
+++ b/Makefile
@@ -149,7 +149,7 @@ DTC_MAKE_ARGS=-I$(SRC_PATH)/dtc VPATH=$(SRC_PATH)/dtc -C dtc V="$(V)" LIBFDT_src
 DTC_CFLAGS=$(CFLAGS) $(extra_cflags) -I$(BUILD_DIR)/dtc -I$(SRC_PATH)/dtc -I$(SRC_PATH)/dtc/libfdt
 
 subdir-dtc:dtc/libfdt dtc/tests
-	$(call quiet-command,$(MAKE) $(DTC_MAKE_ARGS) CPPFLAGS="$(DTC_CFLAGS)" LDFLAGS="$(LDFLAGS)" ARFLAGS="$(ARFLAGS)" CC="$(CC)" AR="$(AR)" LD="$(LD)" $(SUBDIR_MAKEFLAGS) libfdt,)
+	$(call quiet-command,$(MAKE) $(DTC_MAKE_ARGS) CPPFLAGS="$(DTC_CFLAGS)" LDFLAGS="$(LDFLAGS)" ARFLAGS="$(ARFLAGS)" CC="$(CC)" AR="$(AR)" LD="$(LD)" $(SUBDIR_MAKEFLAGS) libfdt/libfdt.a,)
 
 dtc/%:
 	mkdir -p $@
commit 5257144a7860313c8cf19271c85f76fcbd123c39
Merge: 79f2007 1f8f987
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Apr 25 15:57:27 2013 -0500

    Merge remote-tracking branch 'luiz/queue/qmp' into staging
    
    # By Amos Kong
    # Via Luiz Capitulino
    * luiz/queue/qmp:
      monitor: introduce query-command-line-options
    
    Message-id: 1366922656-32545-1-git-send-email-lcapitulino at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

commit 79f2007578a0a205e25a6f299cc52d6732337089
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Thu Apr 25 13:53:02 2013 +0200

    qemu-char: Set foo_tag = 0 when returning FALSE from callbacks
    
    While reviewing some patches I found this problem where tcp_chr_accept
    does not clear listen_tag when returning FALSE, leading to a double
    g_source_remove of the underlying source. Not really a problem unless the id
    gets re-used in between, but still something we should fix.
    
    While at it I've also reviewed all the other code in qemu-char.c for
    similar problems and found that pty_chr_timer has the same problem.
    
    Cc: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Message-id: 1366890782-10311-1-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 f29f9b1..64e824d 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -1077,6 +1077,7 @@ static gboolean pty_chr_timer(gpointer opaque)
     pty_chr_update_read_handler(chr);
 
 out:
+    s->timer_tag = 0;
     return FALSE;
 }
 
@@ -2642,6 +2643,7 @@ static gboolean tcp_chr_accept(GIOChannel *channel, GIOCondition cond, void *opa
 	}
         fd = qemu_accept(s->listen_fd, addr, &len);
         if (fd < 0 && errno != EINTR) {
+            s->listen_tag = 0;
             return FALSE;
         } else if (fd >= 0) {
             if (s->do_telnetopt)
commit e4dcd8ace175a1a6bfb8945d8ae1906be051b36b
Author: Ed Maste <emaste at freebsd.org>
Date:   Thu Apr 25 12:17:11 2013 -0400

    Remove unnecessary FreeBSD #include
    
    sys/param.h was included to define __FreeBSD_version, but the conditional
    using it was removed by commit d05ef160453e98546a4197496dc8a3cb2defac53
    (Brad Smith, "Allow clock_gettime() monotonic clock to be utilized on more
    OS's"), so the include is no longer needed here.
    
    Signed-off-by: Ed Maste <emaste at freebsd.org>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 1366906631-2680-1-git-send-email-emaste at freebsd.org
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/include/qemu/timer.h b/include/qemu/timer.h
index c363190..9dd206c 100644
--- a/include/qemu/timer.h
+++ b/include/qemu/timer.h
@@ -5,10 +5,6 @@
 #include "qemu/main-loop.h"
 #include "qemu/notify.h"
 
-#ifdef __FreeBSD__
-#include <sys/param.h>
-#endif
-
 /* timers */
 
 #define SCALE_MS 1000000
commit d3002b0463727bf8110833b9d1a6efaa28990c28
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Apr 25 09:33:19 2013 +0200

    console: add dummy surface for guests without graphic card
    
    So users get a notification instead of a crash.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/ui/console.c b/ui/console.c
index a13fb64..b30853f 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1300,6 +1300,28 @@ DisplaySurface *qemu_create_displaysurface_from(int width, int height, int bpp,
     return surface;
 }
 
+static DisplaySurface *qemu_create_dummy_surface(void)
+{
+    static const char msg[] =
+        "This VM has no graphic display device.";
+    DisplaySurface *surface = qemu_create_displaysurface(640, 480);
+    pixman_color_t bg = color_table_rgb[0][COLOR_BLACK];
+    pixman_color_t fg = color_table_rgb[0][COLOR_WHITE];
+    pixman_image_t *glyph;
+    int len, x, y, i;
+
+    len = strlen(msg);
+    x = (640/FONT_WIDTH  - len) / 2;
+    y = (480/FONT_HEIGHT - 1)   / 2;
+    for (i = 0; i < len; i++) {
+        glyph = qemu_pixman_glyph_from_vgafont(FONT_HEIGHT, vgafont16, msg[i]);
+        qemu_pixman_glyph_render(glyph, surface->image, &fg, &bg,
+                                 x+i, y, FONT_WIDTH, FONT_HEIGHT);
+        qemu_pixman_image_unref(glyph);
+    }
+    return surface;
+}
+
 void qemu_free_displaysurface(DisplaySurface *surface)
 {
     if (surface == NULL) {
@@ -1312,6 +1334,7 @@ void qemu_free_displaysurface(DisplaySurface *surface)
 
 void register_displaychangelistener(DisplayChangeListener *dcl)
 {
+    static DisplaySurface *dummy;
     QemuConsole *con;
 
     trace_displaychangelistener_register(dcl, dcl->ops->dpy_name);
@@ -1324,8 +1347,15 @@ void register_displaychangelistener(DisplayChangeListener *dcl)
     } else {
         con = active_console;
     }
-    if (dcl->ops->dpy_gfx_switch && con) {
-        dcl->ops->dpy_gfx_switch(dcl, con->surface);
+    if (dcl->ops->dpy_gfx_switch) {
+        if (con) {
+            dcl->ops->dpy_gfx_switch(dcl, con->surface);
+        } else {
+            if (!dummy) {
+                dummy = qemu_create_dummy_surface();
+            }
+            dcl->ops->dpy_gfx_switch(dcl, dummy);
+        }
     }
 }
 
commit 5209089fcd1373c363dc424827593ffaced12203
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Apr 23 15:44:31 2013 +0200

    console: zap ds arg from register_displaychangelistener
    
    We don't have multiple DisplayStates any more,
    so passing it in as argument is not needed.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index f8bd7ff..2d49e9a 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -2058,7 +2058,6 @@ 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;
@@ -2079,8 +2078,7 @@ static int qxl_init_primary(PCIDevice *dev)
 
     qxl->ssd.dcl.ops = &display_listener_ops;
     qxl->ssd.dcl.con = vga->con;
-    ds = qemu_console_displaystate(vga->con);
-    register_displaychangelistener(ds, &qxl->ssd.dcl);
+    register_displaychangelistener(&qxl->ssd.dcl);
     return rc;
 }
 
diff --git a/include/ui/console.h b/include/ui/console.h
index c65940f..4307b5f 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -208,8 +208,7 @@ static inline int is_buffer_shared(DisplaySurface *surface)
     return !(surface->flags & QEMU_ALLOCATED_FLAG);
 }
 
-void register_displaychangelistener(DisplayState *ds,
-                                    DisplayChangeListener *dcl);
+void register_displaychangelistener(DisplayChangeListener *dcl);
 void update_displaychangelistener(DisplayChangeListener *dcl,
                                   uint64_t interval);
 void unregister_displaychangelistener(DisplayChangeListener *dcl);
diff --git a/ui/cocoa.m b/ui/cocoa.m
index d51462a..1971d9c 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -1030,7 +1030,7 @@ void cocoa_display_init(DisplayState *ds, int full_screen)
 
     // register vga output callbacks
     dcl->ops = &dcl_ops;
-    register_displaychangelistener(ds, dcl);
+    register_displaychangelistener(dcl);
 
     // register cleanup function
     atexit(cocoa_cleanup);
diff --git a/ui/console.c b/ui/console.c
index 3835316..a13fb64 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -178,6 +178,7 @@ static int nb_consoles = 0;
 
 static void text_console_do_init(CharDriverState *chr, DisplayState *ds);
 static void dpy_refresh(DisplayState *s);
+static DisplayState *get_alloc_displaystate(void);
 
 static void gui_update(void *opaque)
 {
@@ -1309,15 +1310,14 @@ void qemu_free_displaysurface(DisplaySurface *surface)
     g_free(surface);
 }
 
-void register_displaychangelistener(DisplayState *ds,
-                                    DisplayChangeListener *dcl)
+void register_displaychangelistener(DisplayChangeListener *dcl)
 {
     QemuConsole *con;
 
     trace_displaychangelistener_register(dcl, dcl->ops->dpy_name);
-    dcl->ds = ds;
-    QLIST_INSERT_HEAD(&ds->listeners, dcl, next);
-    gui_setup_refresh(ds);
+    dcl->ds = get_alloc_displaystate();
+    QLIST_INSERT_HEAD(&dcl->ds->listeners, dcl, next);
+    gui_setup_refresh(dcl->ds);
     if (dcl->con) {
         dcl->con->dcls++;
         con = dcl->con;
diff --git a/ui/curses.c b/ui/curses.c
index a85a7da..289a955 100644
--- a/ui/curses.c
+++ b/ui/curses.c
@@ -359,7 +359,7 @@ void curses_display_init(DisplayState *ds, int full_screen)
 
     dcl = (DisplayChangeListener *) g_malloc0(sizeof(DisplayChangeListener));
     dcl->ops = &dcl_ops;
-    register_displaychangelistener(ds, dcl);
+    register_displaychangelistener(dcl);
 
     invalidate = 1;
 }
diff --git a/ui/gtk.c b/ui/gtk.c
index 4110342..42e3c0a 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -1470,7 +1470,7 @@ void gtk_display_init(DisplayState *ds)
 
     gtk_widget_show_all(s->window);
 
-    register_displaychangelistener(ds, &s->dcl);
+    register_displaychangelistener(&s->dcl);
 
     global_state = s;
 }
diff --git a/ui/sdl.c b/ui/sdl.c
index c9f2928..39a42d6 100644
--- a/ui/sdl.c
+++ b/ui/sdl.c
@@ -937,7 +937,7 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
 
     dcl = g_malloc0(sizeof(DisplayChangeListener));
     dcl->ops = &dcl_ops;
-    register_displaychangelistener(ds, dcl);
+    register_displaychangelistener(dcl);
 
     mouse_mode_notifier.notify = sdl_mouse_mode_change;
     qemu_add_mouse_mode_change_notifier(&mouse_mode_notifier);
diff --git a/ui/spice-display.c b/ui/spice-display.c
index 53c19be..82d8b9f 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -625,7 +625,7 @@ void qemu_spice_display_init(DisplayState *ds)
 
     ssd->dcl.ops = &display_listener_ops;
     ssd->dcl.con = qemu_console_lookup_by_index(0);
-    register_displaychangelistener(ds, &ssd->dcl);
+    register_displaychangelistener(&ssd->dcl);
 
     qemu_spice_create_host_primary(ssd);
 }
diff --git a/ui/vnc.c b/ui/vnc.c
index 8ee66b7..86fe1dd 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -2832,7 +2832,7 @@ void vnc_display_init(DisplayState *ds)
     vnc_start_worker_thread();
 
     vs->dcl.ops = &dcl_ops;
-    register_displaychangelistener(ds, &vs->dcl);
+    register_displaychangelistener(&vs->dcl);
 }
 
 
commit cdd5b9375744130e2f49548a3cac7be176a931ca
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Apr 23 13:26:59 2013 +0200

    console: switch ppm_save to qemu_open
    
    ... so it works with fdset.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/ui/console.c b/ui/console.c
index e3ab985..3835316 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -269,18 +269,20 @@ static void ppm_save(const char *filename, struct DisplaySurface *ds,
 {
     int width = pixman_image_get_width(ds->image);
     int height = pixman_image_get_height(ds->image);
+    int fd;
     FILE *f;
     int y;
     int ret;
     pixman_image_t *linebuf;
 
     trace_ppm_save(filename, ds);
-    f = fopen(filename, "wb");
-    if (!f) {
+    fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
+    if (fd == -1) {
         error_setg(errp, "failed to open file '%s': %s", filename,
                    strerror(errno));
         return;
     }
+    f = fdopen(fd, "wb");
     ret = fprintf(f, "P6\n%d %d\n%d\n", width, height, 255);
     if (ret < 0) {
         linebuf = NULL;
commit 14a936490bf90df32ab83d13563efe4b4c768c3c
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Apr 18 07:30:40 2013 +0200

    console: add qemu_console_lookup_by_device
    
    Look up the QemuConsole for a given device, using the new link.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/include/ui/console.h b/include/ui/console.h
index 6e69f7f..c65940f 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -287,6 +287,7 @@ void graphic_hw_invalidate(QemuConsole *con);
 void graphic_hw_text_update(QemuConsole *con, console_ch_t *chardata);
 
 QemuConsole *qemu_console_lookup_by_index(unsigned int index);
+QemuConsole *qemu_console_lookup_by_device(DeviceState *dev);
 bool qemu_console_is_visible(QemuConsole *con);
 bool qemu_console_is_graphic(QemuConsole *con);
 bool qemu_console_is_fixedsize(QemuConsole *con);
diff --git a/ui/console.c b/ui/console.c
index 4102e8c..e3ab985 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1596,6 +1596,25 @@ QemuConsole *qemu_console_lookup_by_index(unsigned int index)
     return consoles[index];
 }
 
+QemuConsole *qemu_console_lookup_by_device(DeviceState *dev)
+{
+    Error *local_err = NULL;
+    Object *obj;
+    int i;
+
+    for (i = 0; i < nb_consoles; i++) {
+        if (!consoles[i]) {
+            continue;
+        }
+        obj = object_property_get_link(OBJECT(consoles[i]),
+                                       "device", &local_err);
+        if (DEVICE(obj) == dev) {
+            return consoles[i];
+        }
+    }
+    return NULL;
+}
+
 bool qemu_console_is_visible(QemuConsole *con)
 {
     return (con == active_console) || (con->dcls > 0);
commit aa2beaa1f57ca329cfceece08cc19d52368e6a8f
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Apr 17 10:21:27 2013 +0200

    console: add device link to QemuConsoles
    
    So it is possible to figure which qemu console displays which device.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
index f33ba9a..fbaf2be 100644
--- a/hw/arm/musicpal.c
+++ b/hw/arm/musicpal.c
@@ -616,7 +616,7 @@ static int musicpal_lcd_init(SysBusDevice *dev)
                           "musicpal-lcd", MP_LCD_SIZE);
     sysbus_init_mmio(dev, &s->iomem);
 
-    s->con = graphic_console_init(&musicpal_gfx_ops, s);
+    s->con = graphic_console_init(DEVICE(dev), &musicpal_gfx_ops, 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/display/blizzard.c b/hw/display/blizzard.c
index 1ca3355..4a466c8 100644
--- a/hw/display/blizzard.c
+++ b/hw/display/blizzard.c
@@ -956,7 +956,7 @@ void *s1d13745_init(qemu_irq gpio_int)
 
     s->fb = g_malloc(0x180000);
 
-    s->con = graphic_console_init(&blizzard_ops, s);
+    s->con = graphic_console_init(NULL, &blizzard_ops, s);
     surface = qemu_console_surface(s->con);
 
     switch (surface_bits_per_pixel(surface)) {
diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
index db232af..6e47956 100644
--- a/hw/display/cirrus_vga.c
+++ b/hw/display/cirrus_vga.c
@@ -2910,7 +2910,7 @@ 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->con = graphic_console_init(s->hw_ops, s);
+    s->con = graphic_console_init(DEVICE(dev), s->hw_ops, s);
     rom_add_vga(VGABIOS_CIRRUS_FILENAME);
     /* XXX ISA-LFB support */
     /* FIXME not qdev yet */
@@ -2957,7 +2957,7 @@ 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.con = graphic_console_init(s->vga.hw_ops, &s->vga);
+     s->vga.con = graphic_console_init(DEVICE(dev), s->vga.hw_ops, &s->vga);
 
      /* setup PCI */
 
diff --git a/hw/display/exynos4210_fimd.c b/hw/display/exynos4210_fimd.c
index e6e7b27..6cb5016 100644
--- a/hw/display/exynos4210_fimd.c
+++ b/hw/display/exynos4210_fimd.c
@@ -1905,7 +1905,7 @@ static int exynos4210_fimd_init(SysBusDevice *dev)
     memory_region_init_io(&s->iomem, &exynos4210_fimd_mmio_ops, s,
             "exynos4210.fimd", FIMD_REGS_SIZE);
     sysbus_init_mmio(dev, &s->iomem);
-    s->console = graphic_console_init(&exynos4210_fimd_ops, s);
+    s->console = graphic_console_init(DEVICE(dev), &exynos4210_fimd_ops, s);
 
     return 0;
 }
diff --git a/hw/display/g364fb.c b/hw/display/g364fb.c
index 03810e9..2a4047e 100644
--- a/hw/display/g364fb.c
+++ b/hw/display/g364fb.c
@@ -484,7 +484,7 @@ static void g364fb_init(DeviceState *dev, G364State *s)
 {
     s->vram = g_malloc0(s->vram_size);
 
-    s->con = graphic_console_init(&g364fb_ops, s);
+    s->con = graphic_console_init(dev, &g364fb_ops, 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/display/jazz_led.c b/hw/display/jazz_led.c
index 6306d8c..52035fc 100644
--- a/hw/display/jazz_led.c
+++ b/hw/display/jazz_led.c
@@ -267,7 +267,7 @@ 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->con = graphic_console_init(&jazz_led_ops, s);
+    s->con = graphic_console_init(DEVICE(dev), &jazz_led_ops, s);
 
     return 0;
 }
diff --git a/hw/display/milkymist-vgafb.c b/hw/display/milkymist-vgafb.c
index 716997c..3828296 100644
--- a/hw/display/milkymist-vgafb.c
+++ b/hw/display/milkymist-vgafb.c
@@ -283,7 +283,7 @@ static int milkymist_vgafb_init(SysBusDevice *dev)
             "milkymist-vgafb", R_MAX * 4);
     sysbus_init_mmio(dev, &s->regs_region);
 
-    s->con = graphic_console_init(&vgafb_ops, s);
+    s->con = graphic_console_init(DEVICE(dev), &vgafb_ops, s);
 
     return 0;
 }
diff --git a/hw/display/omap_lcdc.c b/hw/display/omap_lcdc.c
index e4a5595..fb72ebe 100644
--- a/hw/display/omap_lcdc.c
+++ b/hw/display/omap_lcdc.c
@@ -406,7 +406,7 @@ 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->con = graphic_console_init(&omap_ops, s);
+    s->con = graphic_console_init(NULL, &omap_ops, s);
 
     return s;
 }
diff --git a/hw/display/pl110.c b/hw/display/pl110.c
index d232431..f259955 100644
--- a/hw/display/pl110.c
+++ b/hw/display/pl110.c
@@ -457,7 +457,7 @@ 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->con = graphic_console_init(&pl110_gfx_ops, s);
+    s->con = graphic_console_init(DEVICE(dev), &pl110_gfx_ops, s);
     return 0;
 }
 
diff --git a/hw/display/pxa2xx_lcd.c b/hw/display/pxa2xx_lcd.c
index 76276cf..3b68f26 100644
--- a/hw/display/pxa2xx_lcd.c
+++ b/hw/display/pxa2xx_lcd.c
@@ -1013,7 +1013,7 @@ PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem,
                           "pxa2xx-lcd-controller", 0x00100000);
     memory_region_add_subregion(sysmem, base, &s->iomem);
 
-    s->con = graphic_console_init(&pxa2xx_ops, s);
+    s->con = graphic_console_init(NULL, &pxa2xx_ops, s);
     surface = qemu_console_surface(s->con);
 
     switch (surface_bits_per_pixel(surface)) {
diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index e679830..f8bd7ff 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -2069,7 +2069,7 @@ 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->con = graphic_console_init(&qxl_ops, qxl);
+    vga->con = graphic_console_init(DEVICE(dev), &qxl_ops, qxl);
     qemu_spice_display_init_common(&qxl->ssd);
 
     rc = qxl_init_common(qxl);
@@ -2094,7 +2094,7 @@ static int qxl_init_secondary(PCIDevice *dev)
     memory_region_init_ram(&qxl->vga.vram, "qxl.vgavram", qxl->vga.vram_size);
     vmstate_register_ram(&qxl->vga.vram, &qxl->pci.qdev);
     qxl->vga.vram_ptr = memory_region_get_ram_ptr(&qxl->vga.vram);
-    qxl->vga.con = graphic_console_init(&qxl_ops, qxl);
+    qxl->vga.con = graphic_console_init(DEVICE(dev), &qxl_ops, qxl);
 
     return qxl_init_common(qxl);
 }
diff --git a/hw/display/sm501.c b/hw/display/sm501.c
index 916816f..f72e488 100644
--- a/hw/display/sm501.c
+++ b/hw/display/sm501.c
@@ -1448,5 +1448,5 @@ void sm501_init(MemoryRegion *address_space_mem, uint32_t base,
     }
 
     /* create qemu graphic console */
-    s->con = graphic_console_init(&sm501_ops, s);
+    s->con = graphic_console_init(DEVICE(dev), &sm501_ops, s);
 }
diff --git a/hw/display/ssd0303.c b/hw/display/ssd0303.c
index 3d7ebbe..beea5bf 100644
--- a/hw/display/ssd0303.c
+++ b/hw/display/ssd0303.c
@@ -293,7 +293,7 @@ static int ssd0303_init(I2CSlave *i2c)
 {
     ssd0303_state *s = FROM_I2C_SLAVE(ssd0303_state, i2c);
 
-    s->con = graphic_console_init(&ssd0303_ops, s);
+    s->con = graphic_console_init(DEVICE(i2c), &ssd0303_ops, s);
     qemu_console_resize(s->con, 96 * MAGNIFY, 16 * MAGNIFY);
     return 0;
 }
diff --git a/hw/display/ssd0323.c b/hw/display/ssd0323.c
index 45e8dc1..c3231c6 100644
--- a/hw/display/ssd0323.c
+++ b/hw/display/ssd0323.c
@@ -342,7 +342,7 @@ static int ssd0323_init(SSISlave *dev)
 
     s->col_end = 63;
     s->row_end = 79;
-    s->con = graphic_console_init(&ssd0323_ops, s);
+    s->con = graphic_console_init(DEVICE(dev), &ssd0323_ops, s);
     qemu_console_resize(s->con, 128 * MAGNIFY, 64 * MAGNIFY);
 
     qdev_init_gpio_in(&dev->qdev, ssd0323_cd, 1);
diff --git a/hw/display/tc6393xb.c b/hw/display/tc6393xb.c
index b5b255c..0cb87bc 100644
--- a/hw/display/tc6393xb.c
+++ b/hw/display/tc6393xb.c
@@ -587,7 +587,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->con = graphic_console_init(&tc6393xb_gfx_ops, s);
+    s->con = graphic_console_init(NULL, &tc6393xb_gfx_ops, s);
 
     return s;
 }
diff --git a/hw/display/tcx.c b/hw/display/tcx.c
index d7465c6..fc27f45 100644
--- a/hw/display/tcx.c
+++ b/hw/display/tcx.c
@@ -571,14 +571,14 @@ static int tcx_init1(SysBusDevice *dev)
                                  &s->vram_mem, vram_offset, size);
         sysbus_init_mmio(dev, &s->vram_cplane);
 
-        s->con = graphic_console_init(&tcx24_ops, s);
+        s->con = graphic_console_init(DEVICE(dev), &tcx24_ops, 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->con = graphic_console_init(&tcx_ops, s);
+        s->con = graphic_console_init(DEVICE(dev), &tcx_ops, s);
     }
 
     qemu_console_resize(s->con, s->width, s->height);
diff --git a/hw/display/vga-isa-mm.c b/hw/display/vga-isa-mm.c
index 2da08a1..ceeb92f 100644
--- a/hw/display/vga-isa-mm.c
+++ b/hw/display/vga-isa-mm.c
@@ -135,7 +135,7 @@ 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.con = graphic_console_init(s->vga.hw_ops, s);
+    s->vga.con = graphic_console_init(NULL, s->vga.hw_ops, s);
 
     vga_init_vbe(&s->vga, address_space);
     return 0;
diff --git a/hw/display/vga-isa.c b/hw/display/vga-isa.c
index d2c548e..2b3cc9b 100644
--- a/hw/display/vga-isa.c
+++ b/hw/display/vga-isa.c
@@ -62,7 +62,7 @@ static int vga_initfn(ISADevice *dev)
                                         isa_mem_base + 0x000a0000,
                                         vga_io_memory, 1);
     memory_region_set_coalescing(vga_io_memory);
-    s->con = graphic_console_init(s->hw_ops, s);
+    s->con = graphic_console_init(DEVICE(dev), s->hw_ops, s);
 
     vga_init_vbe(s, isa_address_space(dev));
     /* ROM BIOS */
diff --git a/hw/display/vga-pci.c b/hw/display/vga-pci.c
index dc73f28..cea8db7 100644
--- a/hw/display/vga-pci.c
+++ b/hw/display/vga-pci.c
@@ -150,7 +150,7 @@ 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->con = graphic_console_init(s->hw_ops, s);
+    s->con = graphic_console_init(DEVICE(dev), s->hw_ops, 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/display/vmware_vga.c b/hw/display/vmware_vga.c
index 263bf09..fd3569d 100644
--- a/hw/display/vmware_vga.c
+++ b/hw/display/vmware_vga.c
@@ -1185,13 +1185,13 @@ static const GraphicHwOps vmsvga_ops = {
     .text_update = vmsvga_text_update,
 };
 
-static void vmsvga_init(struct vmsvga_state_s *s,
+static void vmsvga_init(DeviceState *dev, struct vmsvga_state_s *s,
                         MemoryRegion *address_space, MemoryRegion *io)
 {
     s->scratch_size = SVGA_SCRATCH_SIZE;
     s->scratch = g_malloc(s->scratch_size * 4);
 
-    s->vga.con = graphic_console_init(&vmsvga_ops, s);
+    s->vga.con = graphic_console_init(dev, &vmsvga_ops, s);
 
     s->fifo_size = SVGA_FIFO_SIZE;
     memory_region_init_ram(&s->fifo_ram, "vmsvga.fifo", s->fifo_size);
@@ -1258,7 +1258,8 @@ static int pci_vmsvga_initfn(PCIDevice *dev)
     memory_region_set_flush_coalesced(&s->io_bar);
     pci_register_bar(&s->card, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io_bar);
 
-    vmsvga_init(&s->chip, pci_address_space(dev), pci_address_space_io(dev));
+    vmsvga_init(DEVICE(dev), &s->chip,
+                pci_address_space(dev), pci_address_space_io(dev));
 
     pci_register_bar(&s->card, 1, PCI_BASE_ADDRESS_MEM_PREFETCH,
                      &s->chip.vga.vram);
diff --git a/hw/unicore32/puv3.c b/hw/unicore32/puv3.c
index f8d32bc..56d1afa 100644
--- a/hw/unicore32/puv3.c
+++ b/hw/unicore32/puv3.c
@@ -94,7 +94,7 @@ static void puv3_load_kernel(const char *kernel_filename)
     }
 
     /* cheat curses that we have a graphic console, only under ocd console */
-    graphic_console_init(&no_ops, NULL);
+    graphic_console_init(NULL, &no_ops, NULL);
 }
 
 static void puv3_init(QEMUMachineInitArgs *args)
diff --git a/include/ui/console.h b/include/ui/console.h
index b8b0441..6e69f7f 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -278,7 +278,8 @@ typedef struct GraphicHwOps {
     void (*update_interval)(void *opaque, uint64_t interval);
 } GraphicHwOps;
 
-QemuConsole *graphic_console_init(const GraphicHwOps *ops,
+QemuConsole *graphic_console_init(DeviceState *dev,
+                                  const GraphicHwOps *ops,
                                   void *opaque);
 
 void graphic_hw_update(QemuConsole *con);
diff --git a/ui/console.c b/ui/console.c
index e9f3080..4102e8c 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -23,6 +23,7 @@
  */
 #include "qemu-common.h"
 #include "ui/console.h"
+#include "hw/qdev-core.h"
 #include "qemu/timer.h"
 #include "qmp-commands.h"
 #include "sysemu/char.h"
@@ -122,6 +123,7 @@ struct QemuConsole {
     int dcls;
 
     /* Graphic console state.  */
+    Object *device;
     const GraphicHwOps *hw_ops;
     void *hw;
 
@@ -1199,14 +1201,19 @@ static void text_console_update(void *opaque, console_ch_t *chardata)
 
 static QemuConsole *new_console(DisplayState *ds, console_type_t console_type)
 {
+    Error *local_err = NULL;
     Object *obj;
     QemuConsole *s;
     int i;
 
     if (nb_consoles >= MAX_CONSOLES)
         return NULL;
+
     obj = object_new(TYPE_QEMU_CONSOLE);
     s = QEMU_CONSOLE(obj);
+    object_property_add_link(obj, "device", TYPE_DEVICE,
+                             (Object **)&s->device, &local_err);
+
     if (!active_console || ((active_console->console_type != GRAPHIC_CONSOLE) &&
         (console_type == GRAPHIC_CONSOLE))) {
         active_console = s;
@@ -1557,9 +1564,11 @@ DisplayState *init_displaystate(void)
     return display_state;
 }
 
-QemuConsole *graphic_console_init(const GraphicHwOps *hw_ops,
+QemuConsole *graphic_console_init(DeviceState *dev,
+                                  const GraphicHwOps *hw_ops,
                                   void *opaque)
 {
+    Error *local_err = NULL;
     int width = 640;
     int height = 480;
     QemuConsole *s;
@@ -1570,6 +1579,10 @@ QemuConsole *graphic_console_init(const GraphicHwOps *hw_ops,
     s = new_console(ds, GRAPHIC_CONSOLE);
     s->hw_ops = hw_ops;
     s->hw = opaque;
+    if (dev) {
+        object_property_set_link(OBJECT(s), OBJECT(dev),
+                                 "device", &local_err);
+    }
 
     s->surface = qemu_create_displaysurface(width, height);
     return s;
commit 95be0669a353d7f4093876a8fe94474e39c7af9d
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Apr 17 09:45:10 2013 +0200

    console: qom-ify QemuConsole
    
    Just the minimal bits to turn QemuConsoles into Objects.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/display/xenfb.c b/hw/display/xenfb.c
index f2eb89f..f0333a0 100644
--- a/hw/display/xenfb.c
+++ b/hw/display/xenfb.c
@@ -987,7 +987,7 @@ wait_more:
 
     /* vfb */
     fb = container_of(xfb, struct XenFB, c.xendev);
-    fb->c.con = graphic_console_init(&xenfb_ops, fb);
+    fb->c.con = graphic_console_init(NULL, &xenfb_ops, fb);
     fb->have_console = 1;
 
     /* vkbd */
diff --git a/include/ui/console.h b/include/ui/console.h
index 1c82f51..b8b0441 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -2,6 +2,7 @@
 #define CONSOLE_H
 
 #include "ui/qemu-pixman.h"
+#include "qom/object.h"
 #include "qapi/qmp/qdict.h"
 #include "qemu/notify.h"
 #include "monitor/monitor.h"
@@ -93,6 +94,20 @@ void kbd_put_keysym(int keysym);
 
 /* consoles */
 
+#define TYPE_QEMU_CONSOLE "qemu-console"
+#define QEMU_CONSOLE(obj) \
+    OBJECT_CHECK(QemuConsole, (obj), TYPE_QEMU_CONSOLE)
+#define QEMU_CONSOLE_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(QemuConsoleClass, (obj), TYPE_QEMU_CONSOLE)
+#define QEMU_CONSOLE_CLASS(klass) \
+    OBJECT_CLASS_CHECK(QemuConsoleClass, (klass), TYPE_QEMU_CONSOLE)
+
+typedef struct QemuConsoleClass QemuConsoleClass;
+
+struct QemuConsoleClass {
+    ObjectClass parent_class;
+};
+
 #define QEMU_BIG_ENDIAN_FLAG    0x01
 #define QEMU_ALLOCATED_FLAG     0x02
 
diff --git a/ui/console.c b/ui/console.c
index 4f9219e..e9f3080 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -113,6 +113,8 @@ typedef enum {
 } console_type_t;
 
 struct QemuConsole {
+    Object parent;
+
     int index;
     console_type_t console_type;
     DisplayState *ds;
@@ -1197,12 +1199,14 @@ static void text_console_update(void *opaque, console_ch_t *chardata)
 
 static QemuConsole *new_console(DisplayState *ds, console_type_t console_type)
 {
+    Object *obj;
     QemuConsole *s;
     int i;
 
     if (nb_consoles >= MAX_CONSOLES)
         return NULL;
-    s = g_malloc0(sizeof(QemuConsole));
+    obj = object_new(TYPE_QEMU_CONSOLE);
+    s = QEMU_CONSOLE(obj);
     if (!active_console || ((active_console->console_type != GRAPHIC_CONSOLE) &&
         (console_type == GRAPHIC_CONSOLE))) {
         active_console = s;
@@ -1920,8 +1924,17 @@ static void qemu_chr_parse_vc(QemuOpts *opts, ChardevBackend *backend,
     }
 }
 
+static const TypeInfo qemu_console_info = {
+    .name = TYPE_QEMU_CONSOLE,
+    .parent = TYPE_OBJECT,
+    .instance_size = sizeof(QemuConsole),
+    .class_size = sizeof(QemuConsoleClass),
+};
+
+
 static void register_types(void)
 {
+    type_register_static(&qemu_console_info);
     register_char_driver_qapi("vc", CHARDEV_BACKEND_KIND_VC,
                               qemu_chr_parse_vc);
 }
commit 1f8f987d349f8f1bace4b47a83323b68ab0e084c
Author: Amos Kong <akong at redhat.com>
Date:   Thu Apr 25 17:50:35 2013 +0800

    monitor: introduce query-command-line-options
    
    Libvirt has no way to probe if an option or property is supported,
    This patch introduces a new qmp command to query command line
    option information. hmp command isn't added because it's not needed.
    
    Signed-off-by: Amos Kong <akong at redhat.com>
    CC: Luiz Capitulino <lcapitulino at redhat.com>
    CC: Osier Yang <jyang at redhat.com>
    CC: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/qapi-schema.json b/qapi-schema.json
index 751d3c2..5b0fb3b 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3505,3 +3505,69 @@
     '*asl_compiler_rev':  'uint32',
     '*file':              'str',
     '*data':              'str' }}
+
+##
+# @CommandLineParameterType:
+#
+# Possible types for an option parameter.
+#
+# @string: accepts a character string
+#
+# @boolean: accepts "on" or "off"
+#
+# @number: accepts a number
+#
+# @size: accepts a number followed by an optional suffix (K)ilo,
+#        (M)ega, (G)iga, (T)era
+#
+# Since 1.5
+##
+{ 'enum': 'CommandLineParameterType',
+  'data': ['string', 'boolean', 'number', 'size'] }
+
+##
+# @CommandLineParameterInfo:
+#
+# Details about a single parameter of a command line option.
+#
+# @name: parameter name
+#
+# @type: parameter @CommandLineParameterType
+#
+# @help: #optional human readable text string, not suitable for parsing.
+#
+# Since 1.5
+##
+{ 'type': 'CommandLineParameterInfo',
+  'data': { 'name': 'str',
+            'type': 'CommandLineParameterType',
+            '*help': 'str' } }
+
+##
+# @CommandLineOptionInfo:
+#
+# Details about a command line option, including its list of parameter details
+#
+# @option: option name
+#
+# @parameters: an array of @CommandLineParameterInfo
+#
+# Since 1.5
+##
+{ 'type': 'CommandLineOptionInfo',
+  'data': { 'option': 'str', 'parameters': ['CommandLineParameterInfo'] } }
+
+##
+# @query-command-line-options:
+#
+# Query command line option schema.
+#
+# @option: #optional option name
+#
+# Returns: list of @CommandLineOptionInfo for all options (or for the given
+#          @option).  Returns an error if the given @option doesn't exist.
+#
+# Since 1.5
+##
+{'command': 'query-command-line-options', 'data': { '*option': 'str' },
+ 'returns': ['CommandLineOptionInfo'] }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 4d65422..0e89132 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -2416,6 +2416,53 @@ EQMP
     },
 
 SQMP
+query-command-line-options
+--------------------------
+
+Show command line option schema.
+
+Return a json-array of command line option schema for all options (or for
+the given option), returning an error if the given option doesn't exist.
+
+Each array entry contains the following:
+
+- "option": option name (json-string)
+- "parameters": a json-array describes all parameters of the option:
+    - "name": parameter name (json-string)
+    - "type": parameter type (one of 'string', 'boolean', 'number',
+              or 'size')
+    - "help": human readable description of the parameter
+              (json-string, optional)
+
+Example:
+
+-> { "execute": "query-command-line-options", "arguments": { "option": "option-rom" } }
+<- { "return": [
+        {
+            "parameters": [
+                {
+                    "name": "romfile",
+                    "type": "string"
+                },
+                {
+                    "name": "bootindex",
+                    "type": "number"
+                }
+            ],
+            "option": "option-rom"
+        }
+     ]
+   }
+
+EQMP
+
+    {
+        .name       = "query-command-line-options",
+        .args_type  = "option:s?",
+        .mhandler.cmd_new = qmp_marshal_input_query_command_line_options,
+    },
+
+SQMP
 query-migrate
 -------------
 
diff --git a/util/qemu-config.c b/util/qemu-config.c
index 01ca890..a59568d 100644
--- a/util/qemu-config.c
+++ b/util/qemu-config.c
@@ -5,6 +5,7 @@
 #include "qapi/qmp/qerror.h"
 #include "hw/qdev.h"
 #include "qapi/error.h"
+#include "qmp-commands.h"
 
 static QemuOptsList *vm_config_groups[32];
 
@@ -37,6 +38,72 @@ QemuOptsList *qemu_find_opts(const char *group)
     return ret;
 }
 
+static CommandLineParameterInfoList *query_option_descs(const QemuOptDesc *desc)
+{
+    CommandLineParameterInfoList *param_list = NULL, *entry;
+    CommandLineParameterInfo *info;
+    int i;
+
+    for (i = 0; desc[i].name != NULL; i++) {
+        info = g_malloc0(sizeof(*info));
+        info->name = g_strdup(desc[i].name);
+
+        switch (desc[i].type) {
+        case QEMU_OPT_STRING:
+            info->type = COMMAND_LINE_PARAMETER_TYPE_STRING;
+            break;
+        case QEMU_OPT_BOOL:
+            info->type = COMMAND_LINE_PARAMETER_TYPE_BOOLEAN;
+            break;
+        case QEMU_OPT_NUMBER:
+            info->type = COMMAND_LINE_PARAMETER_TYPE_NUMBER;
+            break;
+        case QEMU_OPT_SIZE:
+            info->type = COMMAND_LINE_PARAMETER_TYPE_SIZE;
+            break;
+        }
+
+        if (desc[i].help) {
+            info->has_help = true;
+            info->help = g_strdup(desc[i].help);
+        }
+
+        entry = g_malloc0(sizeof(*entry));
+        entry->value = info;
+        entry->next = param_list;
+        param_list = entry;
+    }
+
+    return param_list;
+}
+
+CommandLineOptionInfoList *qmp_query_command_line_options(bool has_option,
+                                                          const char *option,
+                                                          Error **errp)
+{
+    CommandLineOptionInfoList *conf_list = NULL, *entry;
+    CommandLineOptionInfo *info;
+    int i;
+
+    for (i = 0; vm_config_groups[i] != NULL; i++) {
+        if (!has_option || !strcmp(option, vm_config_groups[i]->name)) {
+            info = g_malloc0(sizeof(*info));
+            info->option = g_strdup(vm_config_groups[i]->name);
+            info->parameters = query_option_descs(vm_config_groups[i]->desc);
+            entry = g_malloc0(sizeof(*entry));
+            entry->value = info;
+            entry->next = conf_list;
+            conf_list = entry;
+        }
+    }
+
+    if (conf_list == NULL) {
+        error_setg(errp, "invalid option name: %s", option);
+    }
+
+    return conf_list;
+}
+
 QemuOptsList *qemu_find_opts_err(const char *group, Error **errp)
 {
     return find_list(vm_config_groups, group, errp);
commit 7c4869761d7f2e0a3f806a5359eea5d2473ec5d5
Author: Cornelia Huck <cornelia.huck at de.ibm.com>
Date:   Tue Apr 23 17:15:19 2013 +0200

    virtio-ccw: Check indicators location.
    
    If a guest neglected to register (secondary) indicators but still runs
    with notifications enabled, we might end up writing to guest zero;
    avoid this by checking for valid indicators and only writing to the
    guest and generating an interrupt if indicators have been setup.
    
    Cc: qemu-stable at nongnu.org
    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 56e4872..b857413 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -742,10 +742,16 @@ static void virtio_ccw_notify(DeviceState *d, uint16_t vector)
     }
 
     if (vector < VIRTIO_PCI_QUEUE_MAX) {
+        if (!dev->indicators) {
+            return;
+        }
         indicators = ldq_phys(dev->indicators);
         indicators |= 1ULL << vector;
         stq_phys(dev->indicators, indicators);
     } else {
+        if (!dev->indicators2) {
+            return;
+        }
         vector = 0;
         indicators = ldq_phys(dev->indicators2);
         indicators |= 1ULL << vector;
commit 9953f8822cc316eec9962f0a2858c3439a80adec
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Apr 12 17:25:03 2013 +0200

    pc: Kill the "use flash device for BIOS unless KVM" misfeature
    
    Use of a flash memory device for the BIOS was added in series "[PATCH
    v10 0/8] PC system flash support", commit 4732dca..1b89faf, v1.1.
    
    Flash vs. ROM is a guest-visible difference.  Thus, flash use had to
    be suppressed for machine types pc-1.0 and older.  This was
    accomplished by adding a dummy device "pc-sysfw" with property
    "rom_only":
    
    * Non-zero rom_only means "use ROM".  Default for pc-1.0 and older.
    * Zero rom_only means "maybe use flash".  Default for newer machines.
    
    Not only is the dummy device ugly, it was also retroactively added to
    the older machine types!  Fortunately, it's not guest-visible (thus no
    immediate guest ABI breakage), and has no vmstate (thus no immediate
    migration breakage).  Breakage occurs only if the user unwisely
    enables flash by setting rom_only to zero.  Patch review FAIL #1.
    
    Why "maybe use flash"?  Flash didn't (and still doesn't) work with
    KVM.  Therefore, rom_only=0 really means "use flash, except when KVM
    is enabled, use ROM".  This is a Bad Idea, because it makes enabling/
    disabling KVM guest-visible.  Patch review FAIL #2.
    
    Aside: it also precludes migrating between KVM on and off, but that's
    not possible for other reasons anyway.
    
    Fix as follows:
    
    1. Change the meaning of rom_only=0 to mean "use flash, no ifs, buts,
    or maybes" for pc-i440fx-1.5 and pc-q35-1.5.  Don't change anything
    for older machines (to remain bug-compatible).
    
    2. Change the default value from 0 to 1 for these machines.
    Necessary, because 0 doesn't work with KVM.  Once it does, we can flip
    the default back to 0.
    
    3. Don't revert the retroactive addition of device "pc-sysfw" to older
    machine types.  Seems not worth the trouble.
    
    4. Add a TODO comment asking for device "pc-sysfw" to be dropped once
    flash works with KVM.
    
    Net effect is that you get a BIOS ROM again even when KVM is disabled,
    just like for machines predating the introduction of flash.
    
    To get flash instead, use "--global pc-sysfw.rom_only=0".
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Message-id: 1365780303-26398-4-git-send-email-armbru at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/block/pc_sysfw.c b/hw/block/pc_sysfw.c
index 0d95c8a..aad8614 100644
--- a/hw/block/pc_sysfw.c
+++ b/hw/block/pc_sysfw.c
@@ -194,11 +194,23 @@ static void old_pc_system_rom_init(MemoryRegion *rom_memory)
                                 bios);
 }
 
+/*
+ * Bug-compatible flash vs. ROM selection enabled?
+ * A few older machines enable this.
+ */
+bool pc_sysfw_flash_vs_rom_bug_compatible;
+
 void pc_system_firmware_init(MemoryRegion *rom_memory)
 {
     DriveInfo *pflash_drv;
     PcSysFwDevice *sysfw_dev;
 
+    /*
+     * TODO This device exists only so that users can switch between
+     * use of flash and ROM for the BIOS.  The ability to switch was
+     * created because flash doesn't work with KVM.  Once it does, we
+     * should drop this device for new machine types.
+     */
     sysfw_dev = (PcSysFwDevice*) qdev_create(NULL, "pc-sysfw");
 
     qdev_init_nofail(DEVICE(sysfw_dev));
@@ -212,7 +224,11 @@ void pc_system_firmware_init(MemoryRegion *rom_memory)
 
     /* Currently KVM cannot execute from device memory.
        Use old rom based firmware initialization for KVM. */
-    if (kvm_enabled()) {
+    /*
+     * This is a Bad Idea, because it makes enabling/disabling KVM
+     * guest-visible.  Do it only in bug-compatibility mode.
+     */
+    if (pc_sysfw_flash_vs_rom_bug_compatible && kvm_enabled()) {
         if (pflash_drv != NULL) {
             fprintf(stderr, "qemu: pflash cannot be used with kvm enabled\n");
             exit(1);
@@ -239,7 +255,7 @@ void pc_system_firmware_init(MemoryRegion *rom_memory)
 }
 
 static Property pcsysfw_properties[] = {
-    DEFINE_PROP_UINT8("rom_only", PcSysFwDevice, rom_only, 0),
+    DEFINE_PROP_UINT8("rom_only", PcSysFwDevice, rom_only, 1),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 13e1d50..89b4cb4 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -235,9 +235,16 @@ static void pc_init_pci(QEMUMachineInitArgs *args)
              initrd_filename, cpu_model, 1, 1);
 }
 
+static void pc_init_pci_1_4(QEMUMachineInitArgs *args)
+{
+    pc_sysfw_flash_vs_rom_bug_compatible = true;
+    pc_init_pci(args);
+}
+
 static void pc_init_pci_1_3(QEMUMachineInitArgs *args)
 {
     enable_compat_apic_id_mode();
+    pc_sysfw_flash_vs_rom_bug_compatible = true;
     pc_init_pci(args);
 }
 
@@ -246,6 +253,7 @@ static void pc_init_pci_1_2(QEMUMachineInitArgs *args)
 {
     disable_kvm_pv_eoi();
     enable_compat_apic_id_mode();
+    pc_sysfw_flash_vs_rom_bug_compatible = true;
     pc_init_pci(args);
 }
 
@@ -318,7 +326,7 @@ static QEMUMachine pc_i440fx_machine_v1_5 = {
 static QEMUMachine pc_i440fx_machine_v1_4 = {
     .name = "pc-i440fx-1.4",
     .desc = "Standard PC (i440FX + PIIX, 1996)",
-    .init = pc_init_pci,
+    .init = pc_init_pci_1_4,
     .max_cpus = 255,
     .compat_props = (GlobalProperty[]) {
         PC_COMPAT_1_4,
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index e5f417e..f160893 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -196,6 +196,12 @@ static void pc_q35_init(QEMUMachineInitArgs *args)
     }
 }
 
+static void pc_q35_init_1_4(QEMUMachineInitArgs *args)
+{
+    pc_sysfw_flash_vs_rom_bug_compatible = true;
+    pc_q35_init(args);
+}
+
 static QEMUMachine pc_q35_machine_v1_5 = {
     .name = "pc-q35-1.5",
     .alias = "q35",
@@ -208,7 +214,7 @@ static QEMUMachine pc_q35_machine_v1_5 = {
 static QEMUMachine pc_q35_machine_v1_4 = {
     .name = "pc-q35-1.4",
     .desc = "Standard PC (Q35 + ICH9, 2009)",
-    .init = pc_q35_init,
+    .init = pc_q35_init_1_4,
     .max_cpus = 255,
     .compat_props = (GlobalProperty[]) {
         PC_COMPAT_1_4,
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 9bcc819..14b504c 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -168,6 +168,7 @@ static inline bool isa_ne2000_init(ISABus *bus, int base, int irq, NICInfo *nd)
 }
 
 /* pc_sysfw.c */
+extern bool pc_sysfw_flash_vs_rom_bug_compatible;
 void pc_system_firmware_init(MemoryRegion *rom_memory);
 
 /* e820 types */
@@ -233,6 +234,10 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t);
             .driver   = "virtio-net-pci",\
             .property = "romfile",\
             .value    = "pxe-virtio.rom",\
+        },{\
+            .driver   = "pc-sysfw",\
+            .property = "rom_only",\
+            .value    = stringify(0),\
         }
 
 #endif
commit 6fd028f64f662c801fd5a54d0e3a1d2baeee93ea
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Apr 12 17:25:02 2013 +0200

    pc: Split pc_init_pci_1_0() off pc_init_pci_1_2()
    
    Just to make the next commit easier to review.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Message-id: 1365780303-26398-3-git-send-email-armbru at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 030e634..13e1d50 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -241,7 +241,7 @@ static void pc_init_pci_1_3(QEMUMachineInitArgs *args)
     pc_init_pci(args);
 }
 
-/* PC machine init function for pc-0.14 to pc-1.2 */
+/* PC machine init function for pc-1.1 to pc-1.2 */
 static void pc_init_pci_1_2(QEMUMachineInitArgs *args)
 {
     disable_kvm_pv_eoi();
@@ -249,6 +249,14 @@ static void pc_init_pci_1_2(QEMUMachineInitArgs *args)
     pc_init_pci(args);
 }
 
+/* PC machine init function for pc-0.14 to pc-1.0 */
+static void pc_init_pci_1_0(QEMUMachineInitArgs *args)
+{
+    disable_kvm_pv_eoi();
+    enable_compat_apic_id_mode();
+    pc_init_pci(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)
 {
@@ -462,7 +470,7 @@ static QEMUMachine pc_machine_v1_1 = {
 static QEMUMachine pc_machine_v1_0 = {
     .name = "pc-1.0",
     .desc = "Standard PC",
-    .init = pc_init_pci_1_2,
+    .init = pc_init_pci_1_0,
     .max_cpus = 255,
     .compat_props = (GlobalProperty[]) {
         PC_COMPAT_1_0,
@@ -478,7 +486,7 @@ static QEMUMachine pc_machine_v1_0 = {
 static QEMUMachine pc_machine_v0_15 = {
     .name = "pc-0.15",
     .desc = "Standard PC",
-    .init = pc_init_pci_1_2,
+    .init = pc_init_pci_1_0,
     .max_cpus = 255,
     .compat_props = (GlobalProperty[]) {
         PC_COMPAT_0_15,
@@ -511,7 +519,7 @@ static QEMUMachine pc_machine_v0_15 = {
 static QEMUMachine pc_machine_v0_14 = {
     .name = "pc-0.14",
     .desc = "Standard PC",
-    .init = pc_init_pci_1_2,
+    .init = pc_init_pci_1_0,
     .max_cpus = 255,
     .compat_props = (GlobalProperty[]) {
         PC_COMPAT_0_14, 
commit 36afbc5135062ccd7d0166ffc3ddbca052d05c71
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Apr 12 17:25:01 2013 +0200

    pc: Inline pc_init_pci_1_3() into pc_init_pci_1_2()
    
    Just to make the commit after next easier to review.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Message-id: 1365780303-26398-2-git-send-email-armbru at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 943758a..030e634 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -245,7 +245,8 @@ static void pc_init_pci_1_3(QEMUMachineInitArgs *args)
 static void pc_init_pci_1_2(QEMUMachineInitArgs *args)
 {
     disable_kvm_pv_eoi();
-    pc_init_pci_1_3(args);
+    enable_compat_apic_id_mode();
+    pc_init_pci(args);
 }
 
 /* PC init function for pc-0.10 to pc-0.13, and reused by xenfv */
commit 1bfffe21a686ab273abce5ef12e8d2a3de320023
Merge: f3aa844 57f9783
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Apr 24 13:23:26 2013 -0500

    Merge remote-tracking branch 'alon/libcacard_ccid.1' into staging
    
    # By Alon Levy (15) and others
    # Via Alon Levy
    * alon/libcacard_ccid.1: (28 commits)
      libcacard/cac: change big switch functions to single return point
      dev-smartcard-reader: empty implementation for Mechanical (fail correctly)
      libcacard: move atr setting from macro to function
      libcacard/vreader: add debugging messages for apdu
      dev-smartcard-reader: copy atr protocol to ccid parameters
      dev-smartcard-reader: change default protocol to T=0
      dev-smartcard-reader: define structs for CCID_Parameter internals
      ccid-card-passthru, dev-smartcard-reader: add debug environment variables
      ccid-card-passthru: add atr check
      libcacard: change default ATR
      dev-smartcard-reader: reuse usb.h definitions
      dev-smartcard-reader: support windows guest
      dev-smartcard-reader: remove aborts (never triggered, but just in case)
      dev-smartcard-reader: nicer debug messages
      dev-smartcard-reader: white space fixes
      libcacard: remove default libcoolkey loading
      libcacard: remove sql: prefix
      libcacard: teach vscclient to use GMainLoop for portability
      libcacard: vscclient to use QemuThread for portability
      libcacard: split vscclient main() from socket reading
      ...
    
    Message-id: 921423767.1475937.1366790789930.JavaMail.root at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

commit f3aa844bbb2922a5b8393d17620eca7d7e921ab3
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Apr 16 10:50:38 2013 +0200

    build: include config-{, all-}devices.mak after defining CONFIG_SOFTMMU and CONFIG_USER_ONLY
    
    Moving the inclusions closer to Makefile, and before rules.mak, makes
    Makefile and Makefile.target more consistent with each other.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Tested-by: Markus Armbruster <armbru at redhat.com>
    Message-id: 1366102238-12374-1-git-send-email-pbonzini at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/Makefile b/Makefile
index 88375dc..54ef242 100644
--- a/Makefile
+++ b/Makefile
@@ -19,6 +19,12 @@ seems to have been used for an in-tree build. You can fix this by running \
 endif
 endif
 
+CONFIG_SOFTMMU := $(if $(filter %-softmmu,$(TARGET_DIRS)),y)
+CONFIG_USER_ONLY := $(if $(filter %-user,$(TARGET_DIRS)),y)
+CONFIG_ALL=y
+-include config-all-devices.mak
+-include config-all-disas.mak
+
 include $(SRC_PATH)/rules.mak
 config-host.mak: $(SRC_PATH)/configure
 	@echo $@ is out-of-date, running configure
@@ -107,12 +113,6 @@ endif
 defconfig:
 	rm -f config-all-devices.mak $(SUBDIR_DEVICES_MAK)
 
--include config-all-devices.mak
--include config-all-disas.mak
-CONFIG_SOFTMMU := $(if $(filter %-softmmu,$(TARGET_DIRS)),y)
-CONFIG_USER_ONLY := $(if $(filter %-user,$(TARGET_DIRS)),y)
-CONFIG_ALL=y
-
 ifneq ($(wildcard config-host.mak),)
 include $(SRC_PATH)/Makefile.objs
 include $(SRC_PATH)/tests/Makefile
diff --git a/Makefile.target b/Makefile.target
index 2636103..7e4c77a 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -1,8 +1,8 @@
 # -*- Mode: makefile -*-
 
 include ../config-host.mak
-include config-devices.mak
 include config-target.mak
+include config-devices.mak
 include $(SRC_PATH)/rules.mak
 
 $(call set-vpath, $(SRC_PATH))
commit fca0a70cdb629b1184f80a7531def457f528b4ca
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Wed Apr 24 10:21:23 2013 +0200

    virtio: drop unused function prototypes.
    
    This removes the unused prototypes in virtio.h.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Message-id: 1366791683-5350-8-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index 0f240c7..ae7a4c4 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -210,18 +210,8 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
                               struct virtio_net_conf *net,
                               uint32_t host_features);
 typedef struct virtio_serial_conf virtio_serial_conf;
-VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *serial);
 typedef struct VirtIOSCSIConf VirtIOSCSIConf;
-VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *conf);
 typedef struct VirtIORNGConf VirtIORNGConf;
-#ifdef CONFIG_VIRTFS
-VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf);
-#endif
-
-
-void virtio_net_exit(VirtIODevice *vdev);
-void virtio_serial_exit(VirtIODevice *vdev);
-void virtio_scsi_exit(VirtIODevice *vdev);
 
 #define DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) \
 	DEFINE_PROP_BIT("indirect_desc", _state, _field, \
commit 6a1a8cc7af5741a4221e1c5bc80c41390d896ff5
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Wed Apr 24 10:21:22 2013 +0200

    virtio: cleanup: init and exit function.
    
    This clean the init and the exit functions and rename virtio_common_cleanup
    to virtio_cleanup.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Message-id: 1366791683-5350-7-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index efad690..cf12469 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -661,7 +661,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_common_cleanup(vdev);
+        virtio_cleanup(vdev);
         return -1;
     }
 #endif
@@ -689,7 +689,7 @@ static int virtio_blk_device_exit(DeviceState *dev)
     qemu_del_vm_change_state_handler(s->change);
     unregister_savevm(dev, "virtio-blk", s);
     blockdev_mark_auto_del(s->bs);
-    virtio_common_cleanup(vdev);
+    virtio_cleanup(vdev);
     return 0;
 }
 
diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
index 6a5b8b6..3787ad2 100644
--- a/hw/char/virtio-serial-bus.c
+++ b/hw/char/virtio-serial-bus.c
@@ -1001,7 +1001,7 @@ static int virtio_serial_device_exit(DeviceState *dev)
         qemu_free_timer(vser->post_load->timer);
         g_free(vser->post_load);
     }
-    virtio_common_cleanup(vdev);
+    virtio_cleanup(vdev);
     return 0;
 }
 
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 0a0d516..2aea5a1 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -1374,7 +1374,7 @@ static int virtio_net_device_exit(DeviceState *qdev)
 
     g_free(n->vqs);
     qemu_del_nic(n->nic);
-    virtio_common_cleanup(vdev);
+    virtio_cleanup(vdev);
 
     return 0;
 }
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index 630e459..84b3ac7 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -640,7 +640,7 @@ int virtio_scsi_common_exit(VirtIOSCSICommon *vs)
     VirtIODevice *vdev = VIRTIO_DEVICE(vs);
 
     g_free(vs->cmd_vqs);
-    virtio_common_cleanup(vdev);
+    virtio_cleanup(vdev);
     return 0;
 }
 
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index 95fb3b0..d669756 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -348,7 +348,7 @@ static int virtio_balloon_device_init(VirtIODevice *vdev)
                                    virtio_balloon_stat, s);
 
     if (ret < 0) {
-        virtio_common_cleanup(VIRTIO_DEVICE(s));
+        virtio_cleanup(VIRTIO_DEVICE(s));
         return -1;
     }
 
@@ -377,7 +377,7 @@ static int virtio_balloon_device_exit(DeviceState *qdev)
     balloon_stats_destroy_timer(s);
     qemu_remove_balloon_handler(s);
     unregister_savevm(qdev, "virtio-balloon", s);
-    virtio_common_cleanup(vdev);
+    virtio_cleanup(vdev);
     return 0;
 }
 
diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c
index 82d7a74..cb787c7 100644
--- a/hw/virtio/virtio-rng.c
+++ b/hw/virtio/virtio-rng.c
@@ -192,7 +192,7 @@ static int virtio_rng_device_exit(DeviceState *qdev)
     qemu_del_timer(vrng->rate_limit_timer);
     qemu_free_timer(vrng->rate_limit_timer);
     unregister_savevm(qdev, "virtio-rng", vrng);
-    virtio_common_cleanup(vdev);
+    virtio_cleanup(vdev);
     return 0;
 }
 
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index e66dab1..0f88c25 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -910,19 +910,13 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
     return 0;
 }
 
-void virtio_common_cleanup(VirtIODevice *vdev)
+void virtio_cleanup(VirtIODevice *vdev)
 {
     qemu_del_vm_change_state_handler(vdev->vmstate);
     g_free(vdev->config);
     g_free(vdev->vq);
 }
 
-void virtio_cleanup(VirtIODevice *vdev)
-{
-    virtio_common_cleanup(vdev);
-    g_free(vdev);
-}
-
 static void virtio_vmstate_change(void *opaque, int running, RunState state)
 {
     VirtIODevice *vdev = opaque;
@@ -972,15 +966,6 @@ void virtio_init(VirtIODevice *vdev, const char *name,
                                                      vdev);
 }
 
-VirtIODevice *virtio_common_init(const char *name, uint16_t device_id,
-                                 size_t config_size, size_t struct_size)
-{
-    VirtIODevice *vdev;
-    vdev = g_malloc0(struct_size);
-    virtio_init(vdev, name, device_id, config_size);
-    return vdev;
-}
-
 hwaddr virtio_queue_get_desc_addr(VirtIODevice *vdev, int n)
 {
     return vdev->vq[n].vring.desc;
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index e72e348..0f240c7 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -147,7 +147,7 @@ typedef struct VirtioDeviceClass {
 
 void virtio_init(VirtIODevice *vdev, const char *name,
                          uint16_t device_id, size_t config_size);
-void virtio_common_cleanup(VirtIODevice *vdev);
+void virtio_cleanup(VirtIODevice *vdev);
 
 VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size,
                             void (*handle_output)(VirtIODevice *,
@@ -176,8 +176,6 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f);
 
 int virtio_load(VirtIODevice *vdev, QEMUFile *f);
 
-void virtio_cleanup(VirtIODevice *vdev);
-
 void virtio_notify_config(VirtIODevice *vdev);
 
 void virtio_queue_set_notification(VirtQueue *vq, int enable);
@@ -188,8 +186,6 @@ int virtio_queue_empty(VirtQueue *vq);
 
 /* Host binding interface.  */
 
-VirtIODevice *virtio_common_init(const char *name, uint16_t device_id,
-                                 size_t config_size, size_t struct_size);
 uint32_t virtio_config_readb(VirtIODevice *vdev, uint32_t addr);
 uint32_t virtio_config_readw(VirtIODevice *vdev, uint32_t addr);
 uint32_t virtio_config_readl(VirtIODevice *vdev, uint32_t addr);
commit 1c819449836b926d6f9db860127211ef092da88e
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Wed Apr 24 10:21:21 2013 +0200

    virtio: remove virtiobindings.
    
    This remove virtio-bindings, and use class instead.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Message-id: 1366791683-5350-6-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
index 5baef23..0356665 100644
--- a/hw/block/dataplane/virtio-blk.c
+++ b/hw/block/dataplane/virtio-blk.c
@@ -23,6 +23,7 @@
 #include "hw/virtio/virtio-blk.h"
 #include "virtio-blk.h"
 #include "block/aio.h"
+#include "hw/virtio/virtio-bus.h"
 
 enum {
     SEG_MAX = 126,                  /* maximum number of I/O segments */
@@ -455,6 +456,8 @@ void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s)
 
 void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
 {
+    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s->vdev)));
+    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
     VirtQueue *vq;
     int i;
 
@@ -470,8 +473,7 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
     s->ctx = aio_context_new();
 
     /* Set up guest notifier (irq) */
-    if (s->vdev->binding->set_guest_notifiers(s->vdev->binding_opaque, 1,
-                                              true) != 0) {
+    if (k->set_guest_notifiers(qbus->parent, 1, true) != 0) {
         fprintf(stderr, "virtio-blk failed to set guest notifier, "
                 "ensure -enable-kvm is set\n");
         exit(1);
@@ -479,8 +481,7 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
     s->guest_notifier = virtio_queue_get_guest_notifier(vq);
 
     /* Set up virtqueue notify */
-    if (s->vdev->binding->set_host_notifier(s->vdev->binding_opaque,
-                                            0, true) != 0) {
+    if (k->set_host_notifier(qbus->parent, 0, true) != 0) {
         fprintf(stderr, "virtio-blk failed to set host notifier\n");
         exit(1);
     }
@@ -508,6 +509,8 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
 
 void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s)
 {
+    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s->vdev)));
+    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
     if (!s->started || s->stopping) {
         return;
     }
@@ -527,12 +530,12 @@ void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s)
     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);
+    k->set_host_notifier(qbus->parent, 0, false);
 
     aio_context_unref(s->ctx);
 
     /* Clean up guest notifier (irq) */
-    s->vdev->binding->set_guest_notifiers(s->vdev->binding_opaque, 1, false);
+    k->set_guest_notifiers(qbus->parent, 1, false);
 
     vring_teardown(&s->vring);
     s->started = false;
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 8c5384c..006576d 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -37,6 +37,7 @@
 #include <stdio.h>
 
 #include "hw/virtio/vhost.h"
+#include "hw/virtio/virtio-bus.h"
 
 struct vhost_net {
     struct vhost_dev dev;
@@ -211,9 +212,12 @@ static void vhost_net_stop_one(struct vhost_net *net,
 int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
                     int total_queues)
 {
+    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev)));
+    VirtioBusState *vbus = VIRTIO_BUS(qbus);
+    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
     int r, i = 0;
 
-    if (!dev->binding->set_guest_notifiers) {
+    if (!k->set_guest_notifiers) {
         error_report("binding does not support guest notifiers");
         r = -ENOSYS;
         goto err;
@@ -227,9 +231,7 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
         }
     }
 
-    r = dev->binding->set_guest_notifiers(dev->binding_opaque,
-                                          total_queues * 2,
-                                          true);
+    r = k->set_guest_notifiers(qbus->parent, total_queues * 2, true);
     if (r < 0) {
         error_report("Error binding guest notifier: %d", -r);
         goto err;
@@ -247,11 +249,12 @@ err:
 void vhost_net_stop(VirtIODevice *dev, NetClientState *ncs,
                     int total_queues)
 {
+    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev)));
+    VirtioBusState *vbus = VIRTIO_BUS(qbus);
+    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
     int i, r;
 
-    r = dev->binding->set_guest_notifiers(dev->binding_opaque,
-                                          total_queues * 2,
-                                          false);
+    r = k->set_guest_notifiers(qbus->parent, total_queues * 2, false);
     if (r < 0) {
         fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", r);
         fflush(stderr);
diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c
index f7a2f4b..cf51a85 100644
--- a/hw/s390x/s390-virtio-bus.c
+++ b/hw/s390x/s390-virtio-bus.c
@@ -55,8 +55,6 @@ static const TypeInfo s390_virtio_bus_info = {
     .instance_size = sizeof(VirtIOS390Bus),
 };
 
-static const VirtIOBindings virtio_s390_bindings;
-
 static ram_addr_t s390_virtio_device_num_vq(VirtIOS390Device *dev);
 
 /* length of VirtIO device pages */
@@ -140,7 +138,6 @@ static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev)
 
     bus->dev_offs += dev_len;
 
-    virtio_bind_device(vdev, &virtio_s390_bindings, DEVICE(dev));
     dev->host_features = virtio_bus_get_vdev_features(&dev->bus,
                                                       dev->host_features);
     s390_virtio_device_sync(dev);
@@ -466,11 +463,6 @@ static unsigned virtio_s390_get_features(DeviceState *d)
 
 /**************** S390 Virtio Bus Device Descriptions *******************/
 
-static const VirtIOBindings virtio_s390_bindings = {
-    .notify = virtio_s390_notify,
-    .get_features = virtio_s390_get_features,
-};
-
 static Property s390_virtio_net_properties[] = {
     DEFINE_NIC_PROPERTIES(VirtIONetS390, vdev.nic_conf),
     DEFINE_VIRTIO_NET_FEATURES(VirtIOS390Device, host_features),
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index e14351c..56e4872 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -53,8 +53,6 @@ static const TypeInfo virtual_css_bus_info = {
     .class_init = virtual_css_bus_class_init,
 };
 
-static const VirtIOBindings virtio_ccw_bindings;
-
 VirtIODevice *virtio_ccw_get_vdev(SubchDev *sch)
 {
     VirtIODevice *vdev = NULL;
@@ -521,7 +519,6 @@ static int virtio_ccw_device_init(VirtioCcwDevice *dev, VirtIODevice *vdev)
     sch->id.cu_type = VIRTIO_CCW_CU_TYPE;
     sch->id.cu_model = dev->vdev->device_id;
 
-    virtio_bind_device(vdev, &virtio_ccw_bindings, DEVICE(dev));
     /* Only the first 32 feature bits are used. */
     dev->host_features[0] = virtio_bus_get_vdev_features(&dev->bus,
                                                          dev->host_features[0]);
@@ -777,11 +774,6 @@ static void virtio_ccw_reset(DeviceState *d)
 
 /**************** Virtio-ccw Bus Device Descriptions *******************/
 
-static const VirtIOBindings virtio_ccw_bindings = {
-    .notify = virtio_ccw_notify,
-    .get_features = virtio_ccw_get_features,
-};
-
 static Property virtio_ccw_net_properties[] = {
     DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
     DEFINE_VIRTIO_NET_FEATURES(VirtioCcwDevice, host_features[0]),
diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c
index 3c93172..d7a1c33 100644
--- a/hw/scsi/vhost-scsi.c
+++ b/hw/scsi/vhost-scsi.c
@@ -22,6 +22,7 @@
 #include "hw/virtio/vhost-scsi.h"
 #include "hw/virtio/vhost.h"
 #include "hw/virtio/virtio-scsi.h"
+#include "hw/virtio/virtio-bus.h"
 
 static int vhost_scsi_set_endpoint(VHostSCSI *s)
 {
@@ -52,8 +53,10 @@ static int vhost_scsi_start(VHostSCSI *s)
 {
     int ret, abi_version, i;
     VirtIODevice *vdev = VIRTIO_DEVICE(s);
+    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
+    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
 
-    if (!vdev->binding->set_guest_notifiers) {
+    if (!k->set_guest_notifiers) {
         error_report("binding does not support guest notifiers");
         return -ENOSYS;
     }
@@ -88,7 +91,7 @@ static int vhost_scsi_start(VHostSCSI *s)
         goto err_vhost_stop;
     }
 
-    ret = vdev->binding->set_guest_notifiers(vdev->binding_opaque, s->dev.nvqs, true);
+    ret = k->set_guest_notifiers(qbus->parent, s->dev.nvqs, true);
     if (ret < 0) {
         error_report("Error binding guest notifier");
         goto err_endpoint;
@@ -116,11 +119,12 @@ err_notifiers:
 static void vhost_scsi_stop(VHostSCSI *s)
 {
     VirtIODevice *vdev = VIRTIO_DEVICE(s);
+    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
+    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
     int ret = 0;
 
-    if (!vdev->binding->set_guest_notifiers) {
-        ret = vdev->binding->set_guest_notifiers(vdev->binding_opaque,
-                                                 s->dev.nvqs, false);
+    if (!k->set_guest_notifiers) {
+        ret = k->set_guest_notifiers(qbus->parent, s->dev.nvqs, false);
         if (ret < 0) {
                 error_report("vhost guest notifier cleanup failed: %d\n", ret);
         }
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 40feab4..fbabf99 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -19,6 +19,7 @@
 #include "qemu/range.h"
 #include <linux/vhost.h>
 #include "exec/address-spaces.h"
+#include "hw/virtio/virtio-bus.h"
 
 static void vhost_dev_sync_region(struct vhost_dev *dev,
                                   MemoryRegionSection *section,
@@ -892,9 +893,13 @@ void vhost_dev_cleanup(struct vhost_dev *hdev)
 
 bool vhost_dev_query(struct vhost_dev *hdev, VirtIODevice *vdev)
 {
-    return !vdev->binding->query_guest_notifiers ||
-        vdev->binding->query_guest_notifiers(vdev->binding_opaque) ||
-        hdev->force;
+    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
+    VirtioBusState *vbus = VIRTIO_BUS(qbus);
+    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
+
+    return !k->query_guest_notifiers ||
+           k->query_guest_notifiers(qbus->parent) ||
+           hdev->force;
 }
 
 /* Stop processing guest IO notifications in qemu.
@@ -902,17 +907,18 @@ bool vhost_dev_query(struct vhost_dev *hdev, VirtIODevice *vdev)
  */
 int vhost_dev_enable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev)
 {
+    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
+    VirtioBusState *vbus = VIRTIO_BUS(qbus);
+    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
     int i, r;
-    if (!vdev->binding->set_host_notifier) {
+    if (!k->set_host_notifier) {
         fprintf(stderr, "binding does not support host notifiers\n");
         r = -ENOSYS;
         goto fail;
     }
 
     for (i = 0; i < hdev->nvqs; ++i) {
-        r = vdev->binding->set_host_notifier(vdev->binding_opaque,
-                                             hdev->vq_index + i,
-                                             true);
+        r = k->set_host_notifier(qbus->parent, hdev->vq_index + i, true);
         if (r < 0) {
             fprintf(stderr, "vhost VQ %d notifier binding failed: %d\n", i, -r);
             goto fail_vq;
@@ -922,9 +928,7 @@ int vhost_dev_enable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev)
     return 0;
 fail_vq:
     while (--i >= 0) {
-        r = vdev->binding->set_host_notifier(vdev->binding_opaque,
-                                             hdev->vq_index + i,
-                                             false);
+        r = k->set_host_notifier(qbus->parent, hdev->vq_index + i, false);
         if (r < 0) {
             fprintf(stderr, "vhost VQ %d notifier cleanup error: %d\n", i, -r);
             fflush(stderr);
@@ -942,12 +946,13 @@ fail:
  */
 void vhost_dev_disable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev)
 {
+    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
+    VirtioBusState *vbus = VIRTIO_BUS(qbus);
+    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
     int i, r;
 
     for (i = 0; i < hdev->nvqs; ++i) {
-        r = vdev->binding->set_host_notifier(vdev->binding_opaque,
-                                             hdev->vq_index + i,
-                                             false);
+        r = k->set_host_notifier(qbus->parent, hdev->vq_index + i, false);
         if (r < 0) {
             fprintf(stderr, "vhost VQ %d notifier cleanup failed: %d\n", i, -r);
             fflush(stderr);
diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c
index dd10849..aab72ff 100644
--- a/hw/virtio/virtio-bus.c
+++ b/hw/virtio/virtio-bus.c
@@ -48,23 +48,6 @@ int virtio_bus_plug_device(VirtIODevice *vdev)
 
     bus->vdev = vdev;
 
-    /*
-     * The lines below will disappear when we drop VirtIOBindings, at the end
-     * of the series.
-     */
-    bus->bindings.notify = klass->notify;
-    bus->bindings.save_config = klass->save_config;
-    bus->bindings.save_queue = klass->save_queue;
-    bus->bindings.load_config = klass->load_config;
-    bus->bindings.load_queue = klass->load_queue;
-    bus->bindings.load_done = klass->load_done;
-    bus->bindings.get_features = klass->get_features;
-    bus->bindings.query_guest_notifiers = klass->query_guest_notifiers;
-    bus->bindings.set_guest_notifiers = klass->set_guest_notifiers;
-    bus->bindings.set_host_notifier = klass->set_host_notifier;
-    bus->bindings.vmstate_change = klass->vmstate_change;
-    virtio_bind_device(bus->vdev, &bus->bindings, qbus->parent);
-
     if (klass->device_plugged != NULL) {
         klass->device_plugged(qbus->parent);
     }
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index a624b03..41bb41e 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -879,19 +879,6 @@ static void virtio_pci_vmstate_change(DeviceState *d, bool running)
     }
 }
 
-static const VirtIOBindings virtio_pci_bindings = {
-    .notify = virtio_pci_notify,
-    .save_config = virtio_pci_save_config,
-    .load_config = virtio_pci_load_config,
-    .save_queue = virtio_pci_save_queue,
-    .load_queue = virtio_pci_load_queue,
-    .get_features = virtio_pci_get_features,
-    .query_guest_notifiers = virtio_pci_query_guest_notifiers,
-    .set_host_notifier = virtio_pci_set_host_notifier,
-    .set_guest_notifiers = virtio_pci_set_guest_notifiers,
-    .vmstate_change = virtio_pci_vmstate_change,
-};
-
 #ifdef CONFIG_VIRTFS
 static int virtio_9p_init_pci(VirtIOPCIProxy *vpci_dev)
 {
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index de54b41..e66dab1 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -507,8 +507,11 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
 /* virtio device */
 static void virtio_notify_vector(VirtIODevice *vdev, uint16_t vector)
 {
-    if (vdev->binding->notify) {
-        vdev->binding->notify(vdev->binding_opaque, vector);
+    BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
+    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
+
+    if (k->notify) {
+        k->notify(qbus->parent, vector);
     }
 }
 
@@ -789,10 +792,13 @@ void virtio_notify_config(VirtIODevice *vdev)
 
 void virtio_save(VirtIODevice *vdev, QEMUFile *f)
 {
+    BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
+    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
     int i;
 
-    if (vdev->binding->save_config)
-        vdev->binding->save_config(vdev->binding_opaque, f);
+    if (k->save_config) {
+        k->save_config(qbus->parent, f);
+    }
 
     qemu_put_8s(f, &vdev->status);
     qemu_put_8s(f, &vdev->isr);
@@ -815,16 +821,18 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f)
         qemu_put_be32(f, vdev->vq[i].vring.num);
         qemu_put_be64(f, vdev->vq[i].pa);
         qemu_put_be16s(f, &vdev->vq[i].last_avail_idx);
-        if (vdev->binding->save_queue)
-            vdev->binding->save_queue(vdev->binding_opaque, i, f);
+        if (k->save_queue) {
+            k->save_queue(qbus->parent, i, f);
+        }
     }
 }
 
 int virtio_set_features(VirtIODevice *vdev, uint32_t val)
 {
+    BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
+    VirtioBusClass *vbusk = VIRTIO_BUS_GET_CLASS(qbus);
     VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
-    uint32_t supported_features =
-        vdev->binding->get_features(vdev->binding_opaque);
+    uint32_t supported_features = vbusk->get_features(qbus->parent);
     bool bad = (val & ~supported_features) != 0;
 
     val &= supported_features;
@@ -840,9 +848,11 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
     int num, i, ret;
     uint32_t features;
     uint32_t supported_features;
+    BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
+    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
 
-    if (vdev->binding->load_config) {
-        ret = vdev->binding->load_config(vdev->binding_opaque, f);
+    if (k->load_config) {
+        ret = k->load_config(qbus->parent, f);
         if (ret)
             return ret;
     }
@@ -853,7 +863,7 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
     qemu_get_be32s(f, &features);
 
     if (virtio_set_features(vdev, features) < 0) {
-        supported_features = vdev->binding->get_features(vdev->binding_opaque);
+        supported_features = k->get_features(qbus->parent);
         error_report("Features 0x%x unsupported. Allowed features: 0x%x",
                      features, supported_features);
         return -1;
@@ -889,8 +899,8 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
                          i, vdev->vq[i].last_avail_idx);
                 return -1;
 	}
-        if (vdev->binding->load_queue) {
-            ret = vdev->binding->load_queue(vdev->binding_opaque, i, f);
+        if (k->load_queue) {
+            ret = k->load_queue(qbus->parent, i, f);
             if (ret)
                 return ret;
         }
@@ -916,6 +926,8 @@ void virtio_cleanup(VirtIODevice *vdev)
 static void virtio_vmstate_change(void *opaque, int running, RunState state)
 {
     VirtIODevice *vdev = opaque;
+    BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
+    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
     bool backend_run = running && (vdev->status & VIRTIO_CONFIG_S_DRIVER_OK);
     vdev->vm_running = running;
 
@@ -923,8 +935,8 @@ static void virtio_vmstate_change(void *opaque, int running, RunState state)
         virtio_set_status(vdev, vdev->status);
     }
 
-    if (vdev->binding->vmstate_change) {
-        vdev->binding->vmstate_change(vdev->binding_opaque, backend_run);
+    if (k->vmstate_change) {
+        k->vmstate_change(qbus->parent, backend_run);
     }
 
     if (!backend_run) {
@@ -969,13 +981,6 @@ VirtIODevice *virtio_common_init(const char *name, uint16_t device_id,
     return vdev;
 }
 
-void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding,
-                        DeviceState *opaque)
-{
-    vdev->binding = binding;
-    vdev->binding_opaque = opaque;
-}
-
 hwaddr virtio_queue_get_desc_addr(VirtIODevice *vdev, int n)
 {
     return vdev->vq[n].vring.desc;
diff --git a/include/hw/virtio/virtio-bus.h b/include/hw/virtio/virtio-bus.h
index ec82238..9ed60f9 100644
--- a/include/hw/virtio/virtio-bus.h
+++ b/include/hw/virtio/virtio-bus.h
@@ -70,10 +70,6 @@ struct VirtioBusState {
      * Only one VirtIODevice can be plugged on the bus.
      */
     VirtIODevice *vdev;
-    /*
-     * This will be removed at the end of the series.
-     */
-    VirtIOBindings bindings;
 };
 
 int virtio_bus_plug_device(VirtIODevice *vdev);
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index 25ec4a3..e72e348 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -90,20 +90,6 @@ typedef struct VirtQueueElement
     struct iovec out_sg[VIRTQUEUE_MAX_SIZE];
 } VirtQueueElement;
 
-typedef struct {
-    void (*notify)(DeviceState *d, uint16_t vector);
-    void (*save_config)(DeviceState *d, QEMUFile *f);
-    void (*save_queue)(DeviceState *d, int n, QEMUFile *f);
-    int (*load_config)(DeviceState *d, QEMUFile *f);
-    int (*load_queue)(DeviceState *d, int n, QEMUFile *f);
-    int (*load_done)(DeviceState *d, QEMUFile *f);
-    unsigned (*get_features)(DeviceState *d);
-    bool (*query_guest_notifiers)(DeviceState *d);
-    int (*set_guest_notifiers)(DeviceState *d, int nvqs, bool assigned);
-    int (*set_host_notifier)(DeviceState *d, int n, bool assigned);
-    void (*vmstate_change)(DeviceState *d, bool running);
-} VirtIOBindings;
-
 #define VIRTIO_PCI_QUEUE_MAX 64
 
 #define VIRTIO_NO_VECTOR 0xffff
@@ -129,8 +115,6 @@ struct VirtIODevice
     uint16_t config_vector;
     int nvectors;
     VirtQueue *vq;
-    const VirtIOBindings *binding;
-    DeviceState *binding_opaque;
     uint16_t device_id;
     bool vm_running;
     VMChangeStateEntry *vmstate;
@@ -223,9 +207,6 @@ void virtio_reset(void *opaque);
 void virtio_update_irq(VirtIODevice *vdev);
 int virtio_set_features(VirtIODevice *vdev, uint32_t val);
 
-void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding,
-                        DeviceState *opaque);
-
 /* Base devices.  */
 typedef struct VirtIOBlkConf VirtIOBlkConf;
 struct virtio_net_conf;
commit 181103cd52710b987799ae980bb92407994243bc
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Wed Apr 24 10:21:20 2013 +0200

    virtio: remove the function pointer.
    
    This remove the function pointer in VirtIODevice, and use only
    VirtioDeviceClass function pointer.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Message-id: 1366791683-5350-5-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index 62a291b..dc6f4e4 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -92,9 +92,7 @@ static int virtio_9p_device_init(VirtIODevice *vdev)
     s->ctx.uid = -1;
 
     s->ops = fse->ops;
-    vdev->get_features = virtio_9p_get_features;
     s->config_size = sizeof(struct virtio_9p_config) + len;
-    vdev->get_config = virtio_9p_get_config;
     s->fid_list = NULL;
     qemu_co_rwlock_init(&s->rename_lock);
 
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index 9fdf009..efad690 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -652,11 +652,6 @@ static int virtio_blk_device_init(VirtIODevice *vdev)
     virtio_init(vdev, "virtio-blk", VIRTIO_ID_BLOCK,
                 sizeof(struct virtio_blk_config));
 
-    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));
diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
index 35c996d..6a5b8b6 100644
--- a/hw/char/virtio-serial-bus.c
+++ b/hw/char/virtio-serial-bus.c
@@ -954,12 +954,6 @@ static int virtio_serial_device_init(VirtIODevice *vdev)
      */
     mark_port_added(vser, 0);
 
-    vdev->get_features = get_features;
-    vdev->get_config = get_config;
-    vdev->set_config = set_config;
-    vdev->set_status = set_status;
-    vdev->reset = vser_reset;
-
     vser->post_load = NULL;
 
     /*
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 4d2cdd2..0a0d516 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -1283,15 +1283,6 @@ static int virtio_net_device_init(VirtIODevice *vdev)
     virtio_init(VIRTIO_DEVICE(n), "virtio-net", VIRTIO_ID_NET,
                                   n->config_size);
 
-    vdev->get_config = virtio_net_get_config;
-    vdev->set_config = virtio_net_set_config;
-    vdev->get_features = virtio_net_get_features;
-    vdev->set_features = virtio_net_set_features;
-    vdev->bad_features = virtio_net_bad_features;
-    vdev->reset = virtio_net_reset;
-    vdev->set_status = virtio_net_set_status;
-    vdev->guest_notifier_mask = virtio_net_guest_notifier_mask;
-    vdev->guest_notifier_pending = virtio_net_guest_notifier_pending;
     n->max_queues = MAX(n->nic_conf.queues, 1);
     n->vqs = g_malloc0(sizeof(VirtIONetQueue) * n->max_queues);
     n->vqs[0].rx_vq = virtio_add_queue(vdev, 256, virtio_net_handle_rx);
diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c
index 0cfbff6..f7a2f4b 100644
--- a/hw/s390x/s390-virtio-bus.c
+++ b/hw/s390x/s390-virtio-bus.c
@@ -136,12 +136,13 @@ static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev)
     dev_len = VIRTIO_DEV_OFFS_CONFIG;
     dev_len += s390_virtio_device_num_vq(dev) * VIRTIO_VQCONFIG_LEN;
     dev_len += dev->feat_len * 2;
-    dev_len += vdev->config_len;
+    dev_len += virtio_bus_get_vdev_config_len(&dev->bus);
 
     bus->dev_offs += dev_len;
 
     virtio_bind_device(vdev, &virtio_s390_bindings, DEVICE(dev));
-    dev->host_features = vdev->get_features(vdev, dev->host_features);
+    dev->host_features = virtio_bus_get_vdev_features(&dev->bus,
+                                                      dev->host_features);
     s390_virtio_device_sync(dev);
     s390_virtio_reset_idx(dev);
     if (dev->qdev.hotplugged) {
@@ -368,9 +369,7 @@ void s390_virtio_device_sync(VirtIOS390Device *dev)
     cur_offs += dev->feat_len * 2;
 
     /* Sync config space */
-    if (dev->vdev->get_config) {
-        dev->vdev->get_config(dev->vdev, dev->vdev->config);
-    }
+    virtio_bus_get_vdev_config(&dev->bus, dev->vdev->config);
 
     cpu_physical_memory_write(cur_offs,
                               dev->vdev->config, dev->vdev->config_len);
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 0591dc2..e14351c 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -235,9 +235,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
             features.index = ldub_phys(ccw.cda + sizeof(features.features));
             features.features = ldl_le_phys(ccw.cda);
             if (features.index < ARRAY_SIZE(dev->host_features)) {
-                if (dev->vdev->set_features) {
-                    dev->vdev->set_features(dev->vdev, features.features);
-                }
+                virtio_bus_set_vdev_features(&dev->bus, features.features);
                 dev->vdev->guest_features = features.features;
             } else {
                 /*
@@ -265,7 +263,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
         if (!ccw.cda) {
             ret = -EFAULT;
         } else {
-            dev->vdev->get_config(dev->vdev, dev->vdev->config);
+            virtio_bus_get_vdev_config(&dev->bus, dev->vdev->config);
             /* XXX config space endianness */
             cpu_physical_memory_write(ccw.cda, dev->vdev->config, len);
             sch->curr_status.scsw.count = ccw.count - len;
@@ -292,9 +290,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
                 /* XXX config space endianness */
                 memcpy(dev->vdev->config, config, len);
                 cpu_physical_memory_unmap(config, hw_len, 0, hw_len);
-                if (dev->vdev->set_config) {
-                    dev->vdev->set_config(dev->vdev, dev->vdev->config);
-                }
+                virtio_bus_set_vdev_config(&dev->bus, dev->vdev->config);
                 sch->curr_status.scsw.count = ccw.count - len;
                 ret = 0;
             }
@@ -527,7 +523,9 @@ static int virtio_ccw_device_init(VirtioCcwDevice *dev, VirtIODevice *vdev)
 
     virtio_bind_device(vdev, &virtio_ccw_bindings, DEVICE(dev));
     /* Only the first 32 feature bits are used. */
-    dev->host_features[0] = vdev->get_features(vdev, dev->host_features[0]);
+    dev->host_features[0] = virtio_bus_get_vdev_features(&dev->bus,
+                                                         dev->host_features[0]);
+
     dev->host_features[0] |= 0x1 << VIRTIO_F_NOTIFY_ON_EMPTY;
     dev->host_features[0] |= 0x1 << VIRTIO_F_BAD_FEATURE;
 
diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c
index 3dd1a0f..3c93172 100644
--- a/hw/scsi/vhost-scsi.c
+++ b/hw/scsi/vhost-scsi.c
@@ -217,10 +217,6 @@ static int vhost_scsi_init(VirtIODevice *vdev)
         return ret;
     }
 
-    vdev->get_features = vhost_scsi_get_features;
-    vdev->set_config = vhost_scsi_set_config;
-    vdev->set_status = vhost_scsi_set_status;
-
     s->dev.nvqs = VHOST_SCSI_VQ_NUM_FIXED + vs->conf.num_queues;
     s->dev.vqs = g_new(struct vhost_virtqueue, s->dev.nvqs);
     s->dev.vq_index = 0;
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index 051daea..630e459 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -599,8 +599,6 @@ int virtio_scsi_common_init(VirtIOSCSICommon *s)
     s->sense_size = VIRTIO_SCSI_SENSE_SIZE;
     s->cdb_size = VIRTIO_SCSI_CDB_SIZE;
 
-    vdev->get_config = virtio_scsi_get_config;
-
     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,
@@ -626,10 +624,6 @@ static int virtio_scsi_device_init(VirtIODevice *vdev)
         return ret;
     }
 
-    vdev->get_features = virtio_scsi_get_features;
-    vdev->set_config = virtio_scsi_set_config;
-    vdev->reset = virtio_scsi_reset;
-
     scsi_bus_new(&s->bus, qdev, &virtio_scsi_scsi_info);
     if (!qdev->hotplugged) {
         scsi_bus_legacy_handle_cmdline(&s->bus);
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index 76e32ce..95fb3b0 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -344,10 +344,6 @@ static int virtio_balloon_device_init(VirtIODevice *vdev)
 
     virtio_init(vdev, "virtio-balloon", VIRTIO_ID_BALLOON, 8);
 
-    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/virtio-pci.c b/hw/virtio/virtio-pci.c
index c87ec10..a624b03 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -267,10 +267,10 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
 
     switch (addr) {
     case VIRTIO_PCI_GUEST_FEATURES:
-	/* Guest does not negotiate properly?  We have to assume nothing. */
-	if (val & (1 << VIRTIO_F_BAD_FEATURE)) {
-            val = vdev->bad_features ? vdev->bad_features(vdev) : 0;
-	}
+        /* Guest does not negotiate properly?  We have to assume nothing. */
+        if (val & (1 << VIRTIO_F_BAD_FEATURE)) {
+            val = virtio_bus_get_vdev_bad_features(&proxy->bus);
+        }
         virtio_set_features(vdev, val);
         break;
     case VIRTIO_PCI_QUEUE_PFN:
@@ -535,6 +535,7 @@ static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs)
 {
     PCIDevice *dev = &proxy->pci_dev;
     VirtIODevice *vdev = proxy->vdev;
+    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
     unsigned int vector;
     int ret, queue_no;
     MSIMessage msg;
@@ -555,7 +556,7 @@ static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs)
         /* If guest supports masking, set up irqfd now.
          * Otherwise, delay until unmasked in the frontend.
          */
-        if (proxy->vdev->guest_notifier_mask) {
+        if (k->guest_notifier_mask) {
             ret = kvm_virtio_pci_irqfd_use(proxy, queue_no, vector);
             if (ret < 0) {
                 kvm_virtio_pci_vq_vector_release(proxy, vector);
@@ -571,7 +572,7 @@ undo:
         if (vector >= msix_nr_vectors_allocated(dev)) {
             continue;
         }
-        if (proxy->vdev->guest_notifier_mask) {
+        if (k->guest_notifier_mask) {
             kvm_virtio_pci_irqfd_release(proxy, queue_no, vector);
         }
         kvm_virtio_pci_vq_vector_release(proxy, vector);
@@ -585,6 +586,7 @@ static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs)
     VirtIODevice *vdev = proxy->vdev;
     unsigned int vector;
     int queue_no;
+    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
 
     for (queue_no = 0; queue_no < nvqs; queue_no++) {
         if (!virtio_queue_get_num(vdev, queue_no)) {
@@ -597,7 +599,7 @@ static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs)
         /* If guest supports masking, clean up irqfd now.
          * Otherwise, it was cleaned when masked in the frontend.
          */
-        if (proxy->vdev->guest_notifier_mask) {
+        if (k->guest_notifier_mask) {
             kvm_virtio_pci_irqfd_release(proxy, queue_no, vector);
         }
         kvm_virtio_pci_vq_vector_release(proxy, vector);
@@ -609,6 +611,7 @@ static int virtio_pci_vq_vector_unmask(VirtIOPCIProxy *proxy,
                                        unsigned int vector,
                                        MSIMessage msg)
 {
+    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(proxy->vdev);
     VirtQueue *vq = virtio_get_queue(proxy->vdev, queue_no);
     EventNotifier *n = virtio_queue_get_guest_notifier(vq);
     VirtIOIRQFD *irqfd;
@@ -627,11 +630,11 @@ static int virtio_pci_vq_vector_unmask(VirtIOPCIProxy *proxy,
     /* If guest supports masking, irqfd is already setup, unmask it.
      * Otherwise, set it up now.
      */
-    if (proxy->vdev->guest_notifier_mask) {
-        proxy->vdev->guest_notifier_mask(proxy->vdev, queue_no, false);
+    if (k->guest_notifier_mask) {
+        k->guest_notifier_mask(proxy->vdev, queue_no, false);
         /* Test after unmasking to avoid losing events. */
-        if (proxy->vdev->guest_notifier_pending &&
-            proxy->vdev->guest_notifier_pending(proxy->vdev, queue_no)) {
+        if (k->guest_notifier_pending &&
+            k->guest_notifier_pending(proxy->vdev, queue_no)) {
             event_notifier_set(n);
         }
     } else {
@@ -644,11 +647,13 @@ static void virtio_pci_vq_vector_mask(VirtIOPCIProxy *proxy,
                                              unsigned int queue_no,
                                              unsigned int vector)
 {
+    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(proxy->vdev);
+
     /* If guest supports masking, keep irqfd but mask it.
      * Otherwise, clean it up now.
      */ 
-    if (proxy->vdev->guest_notifier_mask) {
-        proxy->vdev->guest_notifier_mask(proxy->vdev, queue_no, true);
+    if (k->guest_notifier_mask) {
+        k->guest_notifier_mask(proxy->vdev, queue_no, true);
     } else {
         kvm_virtio_pci_irqfd_release(proxy, queue_no, vector);
     }
@@ -708,6 +713,7 @@ static void virtio_pci_vector_poll(PCIDevice *dev,
 {
     VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev);
     VirtIODevice *vdev = proxy->vdev;
+    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
     int queue_no;
     unsigned int vector;
     EventNotifier *notifier;
@@ -724,8 +730,8 @@ static void virtio_pci_vector_poll(PCIDevice *dev,
         }
         vq = virtio_get_queue(vdev, queue_no);
         notifier = virtio_queue_get_guest_notifier(vq);
-        if (vdev->guest_notifier_pending) {
-            if (vdev->guest_notifier_pending(vdev, queue_no)) {
+        if (k->guest_notifier_pending) {
+            if (k->guest_notifier_pending(vdev, queue_no)) {
                 msix_set_pending(dev, vector);
             }
         } else if (event_notifier_test_and_clear(notifier)) {
@@ -765,6 +771,7 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign)
 {
     VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
     VirtIODevice *vdev = proxy->vdev;
+    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
     int r, n;
     bool with_irqfd = msix_enabled(&proxy->pci_dev) &&
         kvm_msi_via_irqfd_enabled();
@@ -779,7 +786,7 @@ 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 || vdev->guest_notifier_mask) && !assign) {
+    if ((proxy->vector_irqfd || k->guest_notifier_mask) && !assign) {
         msix_unset_vector_notifiers(&proxy->pci_dev);
         if (proxy->vector_irqfd) {
             kvm_virtio_pci_vector_release(proxy, nvqs);
@@ -801,7 +808,7 @@ 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 || vdev->guest_notifier_mask) && assign) {
+    if ((with_irqfd || k->guest_notifier_mask) && assign) {
         if (with_irqfd) {
             proxy->vector_irqfd =
                 g_malloc0(sizeof(*proxy->vector_irqfd) *
diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c
index 96e8075..82d7a74 100644
--- a/hw/virtio/virtio-rng.c
+++ b/hw/virtio/virtio-rng.c
@@ -169,8 +169,6 @@ static int virtio_rng_device_init(VirtIODevice *vdev)
 
     vrng->vq = virtio_add_queue(vdev, 8, handle_input);
 
-    vdev->get_features = get_features;
-
     assert(vrng->conf.max_bytes <= INT64_MAX);
     vrng->quota_remaining = vrng->conf.max_bytes;
 
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 1c2282c..de54b41 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -519,10 +519,11 @@ void virtio_update_irq(VirtIODevice *vdev)
 
 void virtio_set_status(VirtIODevice *vdev, uint8_t val)
 {
+    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
     trace_virtio_set_status(vdev, val);
 
-    if (vdev->set_status) {
-        vdev->set_status(vdev, val);
+    if (k->set_status) {
+        k->set_status(vdev, val);
     }
     vdev->status = val;
 }
@@ -530,12 +531,14 @@ void virtio_set_status(VirtIODevice *vdev, uint8_t val)
 void virtio_reset(void *opaque)
 {
     VirtIODevice *vdev = opaque;
+    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
     int i;
 
     virtio_set_status(vdev, 0);
 
-    if (vdev->reset)
-        vdev->reset(vdev);
+    if (k->reset) {
+        k->reset(vdev);
+    }
 
     vdev->guest_features = 0;
     vdev->queue_sel = 0;
@@ -559,9 +562,10 @@ void virtio_reset(void *opaque)
 
 uint32_t virtio_config_readb(VirtIODevice *vdev, uint32_t addr)
 {
+    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
     uint8_t val;
 
-    vdev->get_config(vdev, vdev->config);
+    k->get_config(vdev, vdev->config);
 
     if (addr > (vdev->config_len - sizeof(val)))
         return (uint32_t)-1;
@@ -572,9 +576,10 @@ uint32_t virtio_config_readb(VirtIODevice *vdev, uint32_t addr)
 
 uint32_t virtio_config_readw(VirtIODevice *vdev, uint32_t addr)
 {
+    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
     uint16_t val;
 
-    vdev->get_config(vdev, vdev->config);
+    k->get_config(vdev, vdev->config);
 
     if (addr > (vdev->config_len - sizeof(val)))
         return (uint32_t)-1;
@@ -585,9 +590,10 @@ uint32_t virtio_config_readw(VirtIODevice *vdev, uint32_t addr)
 
 uint32_t virtio_config_readl(VirtIODevice *vdev, uint32_t addr)
 {
+    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
     uint32_t val;
 
-    vdev->get_config(vdev, vdev->config);
+    k->get_config(vdev, vdev->config);
 
     if (addr > (vdev->config_len - sizeof(val)))
         return (uint32_t)-1;
@@ -598,6 +604,7 @@ uint32_t virtio_config_readl(VirtIODevice *vdev, uint32_t addr)
 
 void virtio_config_writeb(VirtIODevice *vdev, uint32_t addr, uint32_t data)
 {
+    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
     uint8_t val = data;
 
     if (addr > (vdev->config_len - sizeof(val)))
@@ -605,12 +612,14 @@ void virtio_config_writeb(VirtIODevice *vdev, uint32_t addr, uint32_t data)
 
     stb_p(vdev->config + addr, val);
 
-    if (vdev->set_config)
-        vdev->set_config(vdev, vdev->config);
+    if (k->set_config) {
+        k->set_config(vdev, vdev->config);
+    }
 }
 
 void virtio_config_writew(VirtIODevice *vdev, uint32_t addr, uint32_t data)
 {
+    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
     uint16_t val = data;
 
     if (addr > (vdev->config_len - sizeof(val)))
@@ -618,12 +627,14 @@ void virtio_config_writew(VirtIODevice *vdev, uint32_t addr, uint32_t data)
 
     stw_p(vdev->config + addr, val);
 
-    if (vdev->set_config)
-        vdev->set_config(vdev, vdev->config);
+    if (k->set_config) {
+        k->set_config(vdev, vdev->config);
+    }
 }
 
 void virtio_config_writel(VirtIODevice *vdev, uint32_t addr, uint32_t data)
 {
+    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
     uint32_t val = data;
 
     if (addr > (vdev->config_len - sizeof(val)))
@@ -631,8 +642,9 @@ void virtio_config_writel(VirtIODevice *vdev, uint32_t addr, uint32_t data)
 
     stl_p(vdev->config + addr, val);
 
-    if (vdev->set_config)
-        vdev->set_config(vdev, vdev->config);
+    if (k->set_config) {
+        k->set_config(vdev, vdev->config);
+    }
 }
 
 void virtio_queue_set_addr(VirtIODevice *vdev, int n, hwaddr addr)
@@ -810,13 +822,14 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f)
 
 int virtio_set_features(VirtIODevice *vdev, uint32_t val)
 {
+    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
     uint32_t supported_features =
         vdev->binding->get_features(vdev->binding_opaque);
     bool bad = (val & ~supported_features) != 0;
 
     val &= supported_features;
-    if (vdev->set_features) {
-        vdev->set_features(vdev, val);
+    if (k->set_features) {
+        k->set_features(vdev, val);
     }
     vdev->guest_features = val;
     return bad ? -1 : 0;
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index efd29b1..25ec4a3 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -128,30 +128,6 @@ struct VirtIODevice
     void *config;
     uint16_t config_vector;
     int nvectors;
-    /*
-     * Function pointers will be removed at the end of the series as they are in
-     * VirtioDeviceClass.
-     */
-    uint32_t (*get_features)(VirtIODevice *vdev, uint32_t requested_features);
-    uint32_t (*bad_features)(VirtIODevice *vdev);
-    void (*set_features)(VirtIODevice *vdev, uint32_t val);
-    void (*get_config)(VirtIODevice *vdev, uint8_t *config);
-    void (*set_config)(VirtIODevice *vdev, const uint8_t *config);
-    void (*reset)(VirtIODevice *vdev);
-    void (*set_status)(VirtIODevice *vdev, uint8_t val);
-    /* Test and clear event pending status.
-     * Should be called after unmask to avoid losing events.
-     * If backend does not support masking,
-     * must check in frontend instead.
-     */
-    bool (*guest_notifier_pending)(VirtIODevice *vdev, int n);
-    /* Mask/unmask events from this vq. Any events reported
-     * while masked will become pending.
-     * If backend does not support masking,
-     * must mask in frontend instead.
-     */
-    void (*guest_notifier_mask)(VirtIODevice *vdev, int n, bool mask);
-
     VirtQueue *vq;
     const VirtIOBindings *binding;
     DeviceState *binding_opaque;
commit a2f1078b70b6cfc98ed795f17f9d975b1dec1f65
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Wed Apr 24 10:21:19 2013 +0200

    virtio-pci: cleanup.
    
    This remove the init, exit functions as they are no longer used.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Message-id: 1366791683-5350-4-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 6278427..c87ec10 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -885,57 +885,6 @@ static const VirtIOBindings virtio_pci_bindings = {
     .vmstate_change = virtio_pci_vmstate_change,
 };
 
-void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev)
-{
-    uint8_t *config;
-    uint32_t size;
-
-    proxy->vdev = vdev;
-
-    config = proxy->pci_dev.config;
-
-    if (proxy->class_code) {
-        pci_config_set_class(config, proxy->class_code);
-    }
-    pci_set_word(config + PCI_SUBSYSTEM_VENDOR_ID,
-                 pci_get_word(config + PCI_VENDOR_ID));
-    pci_set_word(config + PCI_SUBSYSTEM_ID, vdev->device_id);
-    config[PCI_INTERRUPT_PIN] = 1;
-
-    if (vdev->nvectors &&
-        msix_init_exclusive_bar(&proxy->pci_dev, vdev->nvectors, 1)) {
-        vdev->nvectors = 0;
-    }
-
-    proxy->pci_dev.config_write = virtio_write_config;
-
-    size = VIRTIO_PCI_REGION_SIZE(&proxy->pci_dev) + vdev->config_len;
-    if (size & (size-1))
-        size = 1 << qemu_fls(size);
-
-    memory_region_init_io(&proxy->bar, &virtio_pci_config_ops, proxy,
-                          "virtio-pci", size);
-    pci_register_bar(&proxy->pci_dev, 0, PCI_BASE_ADDRESS_SPACE_IO,
-                     &proxy->bar);
-
-    if (!kvm_has_many_ioeventfds()) {
-        proxy->flags &= ~VIRTIO_PCI_FLAG_USE_IOEVENTFD;
-    }
-
-    virtio_bind_device(vdev, &virtio_pci_bindings, DEVICE(proxy));
-    proxy->host_features |= 0x1 << VIRTIO_F_NOTIFY_ON_EMPTY;
-    proxy->host_features |= 0x1 << VIRTIO_F_BAD_FEATURE;
-    proxy->host_features = vdev->get_features(vdev, proxy->host_features);
-}
-
-static void virtio_exit_pci(PCIDevice *pci_dev)
-{
-    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
-
-    memory_region_destroy(&proxy->bar);
-    msix_uninit_exclusive_bar(pci_dev);
-}
-
 #ifdef CONFIG_VIRTFS
 static int virtio_9p_init_pci(VirtIOPCIProxy *vpci_dev)
 {
@@ -1054,7 +1003,8 @@ static void virtio_pci_exit(PCIDevice *pci_dev)
 {
     VirtIOPCIProxy *proxy = VIRTIO_PCI(pci_dev);
     virtio_pci_stop_ioeventfd(proxy);
-    virtio_exit_pci(pci_dev);
+    memory_region_destroy(&proxy->bar);
+    msix_uninit_exclusive_bar(pci_dev);
 }
 
 static void virtio_pci_reset(DeviceState *qdev)
diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h
index 35ae6ac..917bcc5 100644
--- a/hw/virtio/virtio-pci.h
+++ b/hw/virtio/virtio-pci.h
@@ -200,8 +200,6 @@ struct VirtIORngPCI {
     VirtIORNG vdev;
 };
 
-void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev);
-
 /* Virtio ABI version, if we increment this, we break the guest driver. */
 #define VIRTIO_PCI_ABI_VERSION          0
 
commit d51fcfac8aca37f5f10981d2229681474de6304d
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Wed Apr 24 10:21:18 2013 +0200

    virtio-bus: make virtio_x_bus_new static.
    
    virtio_x_bus_new are only used in file scope.
    So this make them static.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Message-id: 1366791683-5350-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 95c9275..0cfbff6 100644
--- a/hw/s390x/s390-virtio-bus.c
+++ b/hw/s390x/s390-virtio-bus.c
@@ -47,6 +47,8 @@
 
 #define VIRTIO_EXT_CODE   0x2603
 
+static void virtio_s390_bus_new(VirtioBusState *bus, VirtIOS390Device *dev);
+
 static const TypeInfo s390_virtio_bus_info = {
     .name = TYPE_S390_VIRTIO_BUS,
     .parent = TYPE_BUS,
@@ -664,7 +666,7 @@ static const TypeInfo s390_virtio_bridge_info = {
 
 /* virtio-s390-bus */
 
-void virtio_s390_bus_new(VirtioBusState *bus, VirtIOS390Device *dev)
+static void virtio_s390_bus_new(VirtioBusState *bus, VirtIOS390Device *dev)
 {
     DeviceState *qdev = DEVICE(dev);
     BusState *qbus;
diff --git a/hw/s390x/s390-virtio-bus.h b/hw/s390x/s390-virtio-bus.h
index 991f9e2..ac81bd8 100644
--- a/hw/s390x/s390-virtio-bus.h
+++ b/hw/s390x/s390-virtio-bus.h
@@ -79,8 +79,6 @@ typedef struct VirtioBusClass VirtioS390BusClass;
 
 typedef struct VirtIOS390Device VirtIOS390Device;
 
-void virtio_s390_bus_new(VirtioBusState *bus, VirtIOS390Device *dev);
-
 typedef struct VirtIOS390DeviceClass {
     DeviceClass qdev;
     int (*init)(VirtIOS390Device *dev);
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 930531b..0591dc2 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -27,6 +27,8 @@
 #include "virtio-ccw.h"
 #include "trace.h"
 
+static void virtio_ccw_bus_new(VirtioBusState *bus, VirtioCcwDevice *dev);
+
 static int virtual_css_bus_reset(BusState *qbus)
 {
     /* This should actually be modelled via the generic css */
@@ -1060,7 +1062,7 @@ static const TypeInfo virtual_css_bridge_info = {
 
 /* virtio-ccw-bus */
 
-void virtio_ccw_bus_new(VirtioBusState *bus, VirtioCcwDevice *dev)
+static void virtio_ccw_bus_new(VirtioBusState *bus, VirtioCcwDevice *dev)
 {
     DeviceState *qdev = DEVICE(dev);
     BusState *qbus;
diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h
index 8599248..04ba1b9 100644
--- a/hw/s390x/virtio-ccw.h
+++ b/hw/s390x/virtio-ccw.h
@@ -60,8 +60,6 @@ typedef struct VirtioBusClass VirtioCcwBusClass;
 
 typedef struct VirtioCcwDevice VirtioCcwDevice;
 
-void virtio_ccw_bus_new(VirtioBusState *bus, VirtioCcwDevice *dev);
-
 typedef struct VirtIOCCWDeviceClass {
     DeviceClass parent_class;
     int (*init)(VirtioCcwDevice *dev);
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 1269a22..6278427 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -98,6 +98,8 @@
 /* HACK for virtio to determine if it's running a big endian guest */
 bool virtio_is_big_endian(void);
 
+static void virtio_pci_bus_new(VirtioBusState *bus, VirtIOPCIProxy *dev);
+
 /* virtio device */
 /* DeviceState to VirtIOPCIProxy. For use off data-path. TODO: use QOM. */
 static inline VirtIOPCIProxy *to_virtio_pci_proxy(DeviceState *d)
@@ -1524,7 +1526,7 @@ static const TypeInfo virtio_rng_pci_info = {
 
 /* virtio-pci-bus */
 
-void virtio_pci_bus_new(VirtioBusState *bus, VirtIOPCIProxy *dev)
+static void virtio_pci_bus_new(VirtioBusState *bus, VirtIOPCIProxy *dev)
 {
     DeviceState *qdev = DEVICE(dev);
     BusState *qbus;
diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h
index ac71824..35ae6ac 100644
--- a/hw/virtio/virtio-pci.h
+++ b/hw/virtio/virtio-pci.h
@@ -201,7 +201,6 @@ struct VirtIORngPCI {
 };
 
 void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev);
-void virtio_pci_bus_new(VirtioBusState *bus, VirtIOPCIProxy *dev);
 
 /* Virtio ABI version, if we increment this, we break the guest driver. */
 #define VIRTIO_PCI_ABI_VERSION          0
commit 5d448f9dac460d0adf7d7549a9c324f50f1dd1e2
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Wed Apr 24 10:21:17 2013 +0200

    virtio-bus: add new functions.
    
    This add two functions:
       * virtio_bus_set_vdev_config.
       * virtio_bus_set_vdev_feature.
    
    Needed by virtio-ccw.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Message-id: 1366791683-5350-2-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c
index 1596a1c..dd10849 100644
--- a/hw/virtio/virtio-bus.c
+++ b/hw/virtio/virtio-bus.c
@@ -124,6 +124,18 @@ uint32_t virtio_bus_get_vdev_features(VirtioBusState *bus,
     return k->get_features(bus->vdev, requested_features);
 }
 
+/* Set the features of the plugged device. */
+void virtio_bus_set_vdev_features(VirtioBusState *bus,
+                                      uint32_t requested_features)
+{
+    VirtioDeviceClass *k;
+    assert(bus->vdev != NULL);
+    k = VIRTIO_DEVICE_GET_CLASS(bus->vdev);
+    if (k->set_features != NULL) {
+        k->set_features(bus->vdev, requested_features);
+    }
+}
+
 /* Get bad features of the plugged device. */
 uint32_t virtio_bus_get_vdev_bad_features(VirtioBusState *bus)
 {
@@ -148,6 +160,17 @@ void virtio_bus_get_vdev_config(VirtioBusState *bus, uint8_t *config)
     }
 }
 
+/* Set config of the plugged device. */
+void virtio_bus_set_vdev_config(VirtioBusState *bus, uint8_t *config)
+{
+    VirtioDeviceClass *k;
+    assert(bus->vdev != NULL);
+    k = VIRTIO_DEVICE_GET_CLASS(bus->vdev);
+    if (k->set_config != NULL) {
+        k->set_config(bus->vdev, config);
+    }
+}
+
 static const TypeInfo virtio_bus_info = {
     .name = TYPE_VIRTIO_BUS,
     .parent = TYPE_BUS,
diff --git a/include/hw/virtio/virtio-bus.h b/include/hw/virtio/virtio-bus.h
index 311e8c7..ec82238 100644
--- a/include/hw/virtio/virtio-bus.h
+++ b/include/hw/virtio/virtio-bus.h
@@ -86,9 +86,14 @@ size_t virtio_bus_get_vdev_config_len(VirtioBusState *bus);
 /* Get the features of the plugged device. */
 uint32_t virtio_bus_get_vdev_features(VirtioBusState *bus,
                                     uint32_t requested_features);
+/* Set the features of the plugged device. */
+void virtio_bus_set_vdev_features(VirtioBusState *bus,
+                                  uint32_t requested_features);
 /* Get bad features of the plugged device. */
 uint32_t virtio_bus_get_vdev_bad_features(VirtioBusState *bus);
 /* Get config of the plugged device. */
 void virtio_bus_get_vdev_config(VirtioBusState *bus, uint8_t *config);
+/* Set config of the plugged device. */
+void virtio_bus_set_vdev_config(VirtioBusState *bus, uint8_t *config);
 
 #endif /* VIRTIO_BUS_H */
commit 611aa333b472c3fee5d4aed3b7e007621797e895
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Wed Apr 24 10:08:01 2013 +0200

    virtio-rng: cleanup: use QOM casts.
    
    As the virtio-rng-pci, virtio-rng-s390 and virtio-rng-ccw are
    switched to the new API, we can use QOM casts.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Acked-by: Amit Shah <amit.shah at redhat.com>
    Message-id: 1366790881-3026-9-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c
index a1dbd1e..96e8075 100644
--- a/hw/virtio/virtio-rng.c
+++ b/hw/virtio/virtio-rng.c
@@ -18,8 +18,9 @@
 
 static bool is_guest_ready(VirtIORNG *vrng)
 {
+    VirtIODevice *vdev = VIRTIO_DEVICE(vrng);
     if (virtio_queue_ready(vrng->vq)
-        && (vrng->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK)) {
+        && (vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
         return true;
     }
     return false;
@@ -39,6 +40,7 @@ static void virtio_rng_process(VirtIORNG *vrng);
 static void chr_read(void *opaque, const void *buf, size_t size)
 {
     VirtIORNG *vrng = opaque;
+    VirtIODevice *vdev = VIRTIO_DEVICE(vrng);
     VirtQueueElement elem;
     size_t len;
     int offset;
@@ -60,7 +62,7 @@ static void chr_read(void *opaque, const void *buf, size_t size)
 
         virtqueue_push(vrng->vq, &elem, len);
     }
-    virtio_notify(&vrng->vdev, vrng->vq);
+    virtio_notify(vdev, vrng->vq);
 }
 
 static void virtio_rng_process(VirtIORNG *vrng)
@@ -86,7 +88,7 @@ static void virtio_rng_process(VirtIORNG *vrng)
 
 static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
 {
-    VirtIORNG *vrng = DO_UPCAST(VirtIORNG, vdev, vdev);
+    VirtIORNG *vrng = VIRTIO_RNG(vdev);
     virtio_rng_process(vrng);
 }
 
@@ -97,19 +99,20 @@ static uint32_t get_features(VirtIODevice *vdev, uint32_t f)
 
 static void virtio_rng_save(QEMUFile *f, void *opaque)
 {
-    VirtIORNG *vrng = opaque;
+    VirtIODevice *vdev = opaque;
 
-    virtio_save(&vrng->vdev, f);
+    virtio_save(vdev, f);
 }
 
 static int virtio_rng_load(QEMUFile *f, void *opaque, int version_id)
 {
     VirtIORNG *vrng = opaque;
+    VirtIODevice *vdev = VIRTIO_DEVICE(vrng);
 
     if (version_id != 1) {
         return -EINVAL;
     }
-    virtio_load(&vrng->vdev, f);
+    virtio_load(vdev, f);
 
     /* We may have an element ready but couldn't process it due to a quota
      * limit.  Make sure to try again after live migration when the quota may
@@ -122,12 +125,12 @@ static int virtio_rng_load(QEMUFile *f, void *opaque, int version_id)
 
 static void check_rate_limit(void *opaque)
 {
-    VirtIORNG *s = opaque;
+    VirtIORNG *vrng = opaque;
 
-    s->quota_remaining = s->conf.max_bytes;
-    virtio_rng_process(s);
-    qemu_mod_timer(s->rate_limit_timer,
-                   qemu_get_clock_ms(vm_clock) + s->conf.period_ms);
+    vrng->quota_remaining = vrng->conf.max_bytes;
+    virtio_rng_process(vrng);
+    qemu_mod_timer(vrng->rate_limit_timer,
+                   qemu_get_clock_ms(vm_clock) + vrng->conf.period_ms);
 }
 
 static int virtio_rng_device_init(VirtIODevice *vdev)
@@ -166,7 +169,7 @@ static int virtio_rng_device_init(VirtIODevice *vdev)
 
     vrng->vq = virtio_add_queue(vdev, 8, handle_input);
 
-    vrng->vdev.get_features = get_features;
+    vdev->get_features = get_features;
 
     assert(vrng->conf.max_bytes <= INT64_MAX);
     vrng->quota_remaining = vrng->conf.max_bytes;
diff --git a/include/hw/virtio/virtio-rng.h b/include/hw/virtio/virtio-rng.h
index 4347818..debaa15 100644
--- a/include/hw/virtio/virtio-rng.h
+++ b/include/hw/virtio/virtio-rng.h
@@ -30,7 +30,7 @@ struct VirtIORNGConf {
 };
 
 typedef struct VirtIORNG {
-    VirtIODevice vdev;
+    VirtIODevice parent_obj;
 
     /* Only one vq - guest puts buffer(s) on it when it needs entropy */
     VirtQueue *vq;
commit 65f3b678f5b825010a1d167e82dca26ca84a199d
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Wed Apr 24 10:08:00 2013 +0200

    virtio-rng: cleanup: remove qdev field.
    
    The qdev field is no longer needed, just drop it.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Acked-by: Amit Shah <amit.shah at redhat.com>
    Message-id: 1366790881-3026-8-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c
index 805dd18..a1dbd1e 100644
--- a/hw/virtio/virtio-rng.c
+++ b/hw/virtio/virtio-rng.c
@@ -168,8 +168,6 @@ static int virtio_rng_device_init(VirtIODevice *vdev)
 
     vrng->vdev.get_features = get_features;
 
-    vrng->qdev = qdev;
-
     assert(vrng->conf.max_bytes <= INT64_MAX);
     vrng->quota_remaining = vrng->conf.max_bytes;
 
diff --git a/include/hw/virtio/virtio-rng.h b/include/hw/virtio/virtio-rng.h
index 973d809..4347818 100644
--- a/include/hw/virtio/virtio-rng.h
+++ b/include/hw/virtio/virtio-rng.h
@@ -32,8 +32,6 @@ struct VirtIORNGConf {
 typedef struct VirtIORNG {
     VirtIODevice vdev;
 
-    DeviceState *qdev;
-
     /* Only one vq - guest puts buffer(s) on it when it needs entropy */
     VirtQueue *vq;
 
commit 46a5a89d654573425b63f8a7a613833973955f35
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Wed Apr 24 10:07:59 2013 +0200

    virtio-rng: 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>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Acked-by: Amit Shah <amit.shah at redhat.com>
    Message-id: 1366790881-3026-7-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c
index b70975b..805dd18 100644
--- a/hw/virtio/virtio-rng.c
+++ b/hw/virtio/virtio-rng.c
@@ -130,47 +130,45 @@ static void check_rate_limit(void *opaque)
                    qemu_get_clock_ms(vm_clock) + s->conf.period_ms);
 }
 
-static VirtIODevice *virtio_rng_common_init(DeviceState *dev,
-                                            VirtIORNGConf *conf,
-                                            VirtIORNG **pvrng)
+static int virtio_rng_device_init(VirtIODevice *vdev)
 {
-    VirtIORNG *vrng = *pvrng;
-    VirtIODevice *vdev;
+    DeviceState *qdev = DEVICE(vdev);
+    VirtIORNG *vrng = VIRTIO_RNG(vdev);
     Error *local_err = NULL;
 
-    /*
-     * We have two cases here: the old virtio-rng-x device, and the
-     * refactored virtio-rng.
-     * This will disappear later in the serie.
-     */
-    if (vrng == NULL) {
-        vdev = virtio_common_init("virtio-rng", VIRTIO_ID_RNG, 0,
-                                  sizeof(VirtIORNG));
-        vrng = DO_UPCAST(VirtIORNG, vdev, vdev);
-    } else {
-        vdev = VIRTIO_DEVICE(vrng);
-        virtio_init(vdev, "virtio-rng", VIRTIO_ID_RNG, 0);
+    if (vrng->conf.rng == NULL) {
+        vrng->conf.default_backend = RNG_RANDOM(object_new(TYPE_RNG_RANDOM));
+
+        object_property_add_child(OBJECT(qdev),
+                                  "default-backend",
+                                  OBJECT(vrng->conf.default_backend),
+                                  NULL);
+
+        object_property_set_link(OBJECT(qdev),
+                                 OBJECT(vrng->conf.default_backend),
+                                 "rng", NULL);
     }
 
-    vrng->rng = conf->rng;
+    virtio_init(vdev, "virtio-rng", VIRTIO_ID_RNG, 0);
+
+    vrng->rng = vrng->conf.rng;
     if (vrng->rng == NULL) {
         qerror_report(QERR_INVALID_PARAMETER_VALUE, "rng", "a valid object");
-        return NULL;
+        return -1;
     }
 
     rng_backend_open(vrng->rng, &local_err);
     if (local_err) {
         qerror_report_err(local_err);
         error_free(local_err);
-        return NULL;
+        return -1;
     }
 
     vrng->vq = virtio_add_queue(vdev, 8, handle_input);
 
     vrng->vdev.get_features = get_features;
 
-    vrng->qdev = dev;
-    memcpy(&(vrng->conf), conf, sizeof(struct VirtIORNGConf));
+    vrng->qdev = qdev;
 
     assert(vrng->conf.max_bytes <= INT64_MAX);
     vrng->quota_remaining = vrng->conf.max_bytes;
@@ -181,52 +179,9 @@ static VirtIODevice *virtio_rng_common_init(DeviceState *dev,
     qemu_mod_timer(vrng->rate_limit_timer,
                    qemu_get_clock_ms(vm_clock) + vrng->conf.period_ms);
 
-    register_savevm(dev, "virtio-rng", -1, 1, virtio_rng_save,
+    register_savevm(qdev, "virtio-rng", -1, 1, virtio_rng_save,
                     virtio_rng_load, vrng);
 
-    return vdev;
-}
-
-/*
- * This two functions will be removed later in the serie.
- */
-VirtIODevice *virtio_rng_init(DeviceState *dev, VirtIORNGConf *conf)
-{
-    VirtIORNG *vdev = NULL;
-    return virtio_rng_common_init(dev, conf, &vdev);
-}
-
-void virtio_rng_exit(VirtIODevice *vdev)
-{
-    VirtIORNG *vrng = DO_UPCAST(VirtIORNG, vdev, vdev);
-
-    qemu_del_timer(vrng->rate_limit_timer);
-    qemu_free_timer(vrng->rate_limit_timer);
-    unregister_savevm(vrng->qdev, "virtio-rng", vrng);
-    virtio_cleanup(vdev);
-}
-
-static int virtio_rng_device_init(VirtIODevice *vdev)
-{
-    DeviceState *qdev = DEVICE(vdev);
-    VirtIORNG *vrng = VIRTIO_RNG(vdev);
-
-    if (vrng->conf.rng == NULL) {
-        vrng->conf.default_backend = RNG_RANDOM(object_new(TYPE_RNG_RANDOM));
-
-        object_property_add_child(OBJECT(qdev),
-                                  "default-backend",
-                                  OBJECT(vrng->conf.default_backend),
-                                  NULL);
-
-        object_property_set_link(OBJECT(qdev),
-                                 OBJECT(vrng->conf.default_backend),
-                                 "rng", NULL);
-    }
-
-    if (virtio_rng_common_init(qdev, &(vrng->conf), &vrng) == NULL) {
-        return -1;
-    }
     return 0;
 }
 
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index d3f1436..efd29b1 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -261,7 +261,6 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *serial);
 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_VIRTFS
 VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf);
 #endif
@@ -270,7 +269,6 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf);
 void virtio_net_exit(VirtIODevice *vdev);
 void virtio_serial_exit(VirtIODevice *vdev);
 void virtio_scsi_exit(VirtIODevice *vdev);
-void virtio_rng_exit(VirtIODevice *vdev);
 
 #define DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) \
 	DEFINE_PROP_BIT("indirect_desc", _state, _field, \
commit 2db26d4ca240bc0f04898253b9469a2435665084
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Wed Apr 24 10:07:58 2013 +0200

    virtio-rng-ccw: switch to the new API.
    
    Here the virtio-rng-ccw is modified for the new API. The device
    virtio-rng-pci extends virtio-pci. It creates and connects a virtio-rng-device
    during the init. The properties are not changed.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Acked-by: Amit Shah <amit.shah at redhat.com>
    Message-id: 1366790881-3026-6-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 7fdc8c3..930531b 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -709,28 +709,21 @@ static void vhost_ccw_scsi_instance_init(Object *obj)
 }
 #endif
 
-static int virtio_ccw_rng_init(VirtioCcwDevice *dev)
+static int virtio_ccw_rng_init(VirtioCcwDevice *ccw_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) {
+    VirtIORNGCcw *dev = VIRTIO_RNG_CCW(ccw_dev);
+    DeviceState *vdev = DEVICE(&dev->vdev);
+
+    qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
+    if (qdev_init(vdev) < 0) {
         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);
+    object_property_set_link(OBJECT(dev),
+                             OBJECT(dev->vdev.conf.default_backend), "rng",
+                             NULL);
+
+    return virtio_ccw_device_init(ccw_dev, VIRTIO_DEVICE(vdev));
 }
 
 /* DeviceState to VirtioCcwDevice. Note: used on datapath,
@@ -947,18 +940,19 @@ static const TypeInfo vhost_ccw_scsi = {
 };
 #endif
 
-static void virtio_ccw_rng_initfn(Object *obj)
+static void virtio_ccw_rng_instance_init(Object *obj)
 {
-    VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(obj);
-
+    VirtIORNGCcw *dev = VIRTIO_RNG_CCW(obj);
+    object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_RNG);
+    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
     object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
-                             (Object **)&dev->rng.rng, NULL);
+                             (Object **)&dev->vdev.conf.rng, NULL);
 }
 
 static Property virtio_ccw_rng_properties[] = {
     DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
     DEFINE_VIRTIO_COMMON_FEATURES(VirtioCcwDevice, host_features[0]),
-    DEFINE_VIRTIO_RNG_PROPERTIES(VirtioCcwDevice, rng),
+    DEFINE_VIRTIO_RNG_PROPERTIES(VirtIORNGCcw, vdev.conf),
     DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -968,16 +962,16 @@ static void virtio_ccw_rng_class_init(ObjectClass *klass, void *data)
     VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass);
 
     k->init = virtio_ccw_rng_init;
-    k->exit = virtio_ccw_rng_exit;
+    k->exit = virtio_ccw_exit;
     dc->reset = virtio_ccw_reset;
     dc->props = virtio_ccw_rng_properties;
 }
 
 static const TypeInfo virtio_ccw_rng = {
-    .name          = "virtio-rng-ccw",
+    .name          = TYPE_VIRTIO_RNG_CCW,
     .parent        = TYPE_VIRTIO_CCW_DEVICE,
-    .instance_size = sizeof(VirtioCcwDevice),
-    .instance_init = virtio_ccw_rng_initfn,
+    .instance_size = sizeof(VirtIORNGCcw),
+    .instance_init = virtio_ccw_rng_instance_init,
     .class_init    = virtio_ccw_rng_class_init,
 };
 
diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h
index 84055e7..8599248 100644
--- a/hw/s390x/virtio-ccw.h
+++ b/hw/s390x/virtio-ccw.h
@@ -77,7 +77,6 @@ struct VirtioCcwDevice {
     VirtIODevice *vdev;
     char *bus_id;
     uint32_t host_features[VIRTIO_CCW_FEATURE_SIZE];
-    VirtIORNGConf rng;
     VirtioBusState bus;
     /* Guest provided values: */
     hwaddr indicators;
@@ -160,6 +159,17 @@ typedef struct VirtIONetCcw {
     VirtIONet vdev;
 } VirtIONetCcw;
 
+/* virtio-rng-ccw */
+
+#define TYPE_VIRTIO_RNG_CCW "virtio-rng-ccw"
+#define VIRTIO_RNG_CCW(obj) \
+        OBJECT_CHECK(VirtIORNGCcw, (obj), TYPE_VIRTIO_RNG_CCW)
+
+typedef struct VirtIORNGCcw {
+    VirtioCcwDevice parent_obj;
+    VirtIORNG vdev;
+} VirtIORNGCcw;
+
 VirtualCssBus *virtual_css_bus_init(void);
 void virtio_ccw_device_update_status(SubchDev *sch);
 VirtIODevice *virtio_ccw_get_vdev(SubchDev *sch);
commit 0bca1f531312037ab988b883ea3df85ddd2cc5b1
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Wed Apr 24 10:07:57 2013 +0200

    virtio-rng-s390: switch to the new API.
    
    Here the virtio-rng-s390 is modified for the new API. The device
    virtio-rng-s390 extends virtio-s390-device as before. It creates and
    connects a virtio-rng during the init. The properties are not modified.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Acked-by: Amit Shah <amit.shah at redhat.com>
    Message-id: 1366790881-3026-5-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 dabbc2e..95c9275 100644
--- a/hw/s390x/s390-virtio-bus.c
+++ b/hw/s390x/s390-virtio-bus.c
@@ -262,16 +262,31 @@ static void s390_vhost_scsi_instance_init(Object *obj)
 }
 #endif
 
-static int s390_virtio_rng_init(VirtIOS390Device *dev)
+
+static int s390_virtio_rng_init(VirtIOS390Device *s390_dev)
 {
-    VirtIODevice *vdev;
+    VirtIORNGS390 *dev = VIRTIO_RNG_S390(s390_dev);
+    DeviceState *vdev = DEVICE(&dev->vdev);
 
-    vdev = virtio_rng_init((DeviceState *)dev, &dev->rng);
-    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);
+    object_property_set_link(OBJECT(dev),
+                             OBJECT(dev->vdev.conf.default_backend), "rng",
+                             NULL);
+
+    return s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev));
+}
+
+static void s390_virtio_rng_instance_init(Object *obj)
+{
+    VirtIORNGS390 *dev = VIRTIO_RNG_S390(obj);
+    object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_RNG);
+    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
+    object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
+                             (Object **)&dev->vdev.conf.rng, NULL);
 }
 
 static uint64_t s390_virtio_device_vq_token(VirtIOS390Device *dev, int vq)
@@ -523,14 +538,6 @@ static const TypeInfo s390_virtio_serial = {
     .class_init    = s390_virtio_serial_class_init,
 };
 
-static void s390_virtio_rng_initfn(Object *obj)
-{
-    VirtIOS390Device *dev = VIRTIO_S390_DEVICE(obj);
-
-    object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
-                             (Object **)&dev->rng.rng, NULL);
-}
-
 static void s390_virtio_rng_class_init(ObjectClass *klass, void *data)
 {
     VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
@@ -539,10 +546,10 @@ static void s390_virtio_rng_class_init(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo s390_virtio_rng = {
-    .name          = "virtio-rng-s390",
+    .name          = TYPE_VIRTIO_RNG_S390,
     .parent        = TYPE_VIRTIO_S390_DEVICE,
-    .instance_size = sizeof(VirtIOS390Device),
-    .instance_init = s390_virtio_rng_initfn,
+    .instance_size = sizeof(VirtIORNGS390),
+    .instance_init = s390_virtio_rng_instance_init,
     .class_init    = s390_virtio_rng_class_init,
 };
 
diff --git a/hw/s390x/s390-virtio-bus.h b/hw/s390x/s390-virtio-bus.h
index d7c47db..991f9e2 100644
--- a/hw/s390x/s390-virtio-bus.h
+++ b/hw/s390x/s390-virtio-bus.h
@@ -93,7 +93,6 @@ struct VirtIOS390Device {
     uint8_t feat_len;
     VirtIODevice *vdev;
     uint32_t host_features;
-    VirtIORNGConf rng;
     VirtioBusState bus;
 };
 
@@ -176,4 +175,15 @@ typedef struct VHostSCSIS390 {
 } VHostSCSIS390;
 #endif
 
+/* virtio-rng-s390 */
+
+#define TYPE_VIRTIO_RNG_S390 "virtio-rng-s390"
+#define VIRTIO_RNG_S390(obj) \
+        OBJECT_CHECK(VirtIORNGS390, (obj), TYPE_VIRTIO_RNG_S390)
+
+typedef struct VirtIORNGS390 {
+    VirtIOS390Device parent_obj;
+    VirtIORNG vdev;
+} VirtIORNGS390;
+
 #endif
commit 59ccd20a9ac719cff82180429458728f03ec612f
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Wed Apr 24 10:07:56 2013 +0200

    virtio-rng-pci: switch to the new API.
    
    Here the virtio-rng-pci is modified for the new API. The device
    virtio-rng-pci extends virtio-pci. It creates and connects a virtio-rng-device
    during the init. The properties are not changed.
    
    The virtio_pci_reset function, is removed as no longer used.
    The virtio_pci_rst function, is renamed virtio_pci_reset.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Acked-by: Amit Shah <amit.shah at redhat.com>
    Message-id: 1366790881-3026-4-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 4860db1..1269a22 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -257,15 +257,6 @@ static void virtio_pci_stop_ioeventfd(VirtIOPCIProxy *proxy)
     proxy->ioeventfd_started = false;
 }
 
-static void virtio_pci_reset(DeviceState *d)
-{
-    VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
-    virtio_pci_stop_ioeventfd(proxy);
-    virtio_reset(proxy->vdev);
-    msix_unuse_all_vectors(&proxy->pci_dev);
-    proxy->flags &= ~VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
-}
-
 static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
 {
     VirtIOPCIProxy *proxy = opaque;
@@ -943,79 +934,6 @@ static void virtio_exit_pci(PCIDevice *pci_dev)
     msix_uninit_exclusive_bar(pci_dev);
 }
 
-static int virtio_rng_init_pci(PCIDevice *pci_dev)
-{
-    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
-    VirtIODevice *vdev;
-
-    if (proxy->rng.rng == NULL) {
-        proxy->rng.default_backend = RNG_RANDOM(object_new(TYPE_RNG_RANDOM));
-
-        object_property_add_child(OBJECT(pci_dev),
-                                  "default-backend",
-                                  OBJECT(proxy->rng.default_backend),
-                                  NULL);
-
-        object_property_set_link(OBJECT(pci_dev),
-                                 OBJECT(proxy->rng.default_backend),
-                                 "rng", NULL);
-    }
-
-    vdev = virtio_rng_init(&pci_dev->qdev, &proxy->rng);
-    if (!vdev) {
-        return -1;
-    }
-    virtio_init_pci(proxy, vdev);
-    return 0;
-}
-
-static void virtio_rng_exit_pci(PCIDevice *pci_dev)
-{
-    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
-
-    virtio_pci_stop_ioeventfd(proxy);
-    virtio_rng_exit(proxy->vdev);
-    virtio_exit_pci(pci_dev);
-}
-
-static void virtio_rng_initfn(Object *obj)
-{
-    PCIDevice *pci_dev = PCI_DEVICE(obj);
-    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
-
-    object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
-                             (Object **)&proxy->rng.rng, NULL);
-}
-
-static Property virtio_rng_properties[] = {
-    DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
-    DEFINE_VIRTIO_RNG_PROPERTIES(VirtIOPCIProxy, rng),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void virtio_rng_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init = virtio_rng_init_pci;
-    k->exit = virtio_rng_exit_pci;
-    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
-    k->device_id = PCI_DEVICE_ID_VIRTIO_RNG;
-    k->revision = VIRTIO_PCI_ABI_VERSION;
-    k->class_id = PCI_CLASS_OTHERS;
-    dc->reset = virtio_pci_reset;
-    dc->props = virtio_rng_properties;
-}
-
-static const TypeInfo virtio_rng_info = {
-    .name          = "virtio-rng-pci",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(VirtIOPCIProxy),
-    .instance_init = virtio_rng_initfn,
-    .class_init    = virtio_rng_class_init,
-};
-
 #ifdef CONFIG_VIRTFS
 static int virtio_9p_init_pci(VirtIOPCIProxy *vpci_dev)
 {
@@ -1137,11 +1055,7 @@ static void virtio_pci_exit(PCIDevice *pci_dev)
     virtio_exit_pci(pci_dev);
 }
 
-/*
- * This will be renamed virtio_pci_reset at the end of the series.
- * virtio_pci_reset is still in use at this moment.
- */
-static void virtio_pci_rst(DeviceState *qdev)
+static void virtio_pci_reset(DeviceState *qdev)
 {
     VirtIOPCIProxy *proxy = VIRTIO_PCI(qdev);
     VirtioBusState *bus = VIRTIO_BUS(&proxy->bus);
@@ -1161,7 +1075,7 @@ static void virtio_pci_class_init(ObjectClass *klass, void *data)
     k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
     k->revision = VIRTIO_PCI_ABI_VERSION;
     k->class_id = PCI_CLASS_OTHERS;
-    dc->reset = virtio_pci_rst;
+    dc->reset = virtio_pci_reset;
 }
 
 static const TypeInfo virtio_pci_info = {
@@ -1550,6 +1464,64 @@ static const TypeInfo virtio_net_pci_info = {
     .class_init    = virtio_net_pci_class_init,
 };
 
+/* virtio-rng-pci */
+
+static Property virtio_rng_pci_properties[] = {
+    DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
+    DEFINE_VIRTIO_RNG_PROPERTIES(VirtIORngPCI, vdev.conf),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static int virtio_rng_pci_init(VirtIOPCIProxy *vpci_dev)
+{
+    VirtIORngPCI *vrng = VIRTIO_RNG_PCI(vpci_dev);
+    DeviceState *vdev = DEVICE(&vrng->vdev);
+
+    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+    if (qdev_init(vdev) < 0) {
+        return -1;
+    }
+
+    object_property_set_link(OBJECT(vrng),
+                             OBJECT(vrng->vdev.conf.default_backend), "rng",
+                             NULL);
+
+    return 0;
+}
+
+static void virtio_rng_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_rng_pci_init;
+    dc->props = virtio_rng_pci_properties;
+
+    pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+    pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_RNG;
+    pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
+    pcidev_k->class_id = PCI_CLASS_OTHERS;
+}
+
+static void virtio_rng_initfn(Object *obj)
+{
+    VirtIORngPCI *dev = VIRTIO_RNG_PCI(obj);
+    object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_RNG);
+    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
+    object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
+                             (Object **)&dev->vdev.conf.rng, NULL);
+
+}
+
+static const TypeInfo virtio_rng_pci_info = {
+    .name          = TYPE_VIRTIO_RNG_PCI,
+    .parent        = TYPE_VIRTIO_PCI,
+    .instance_size = sizeof(VirtIORngPCI),
+    .instance_init = virtio_rng_initfn,
+    .class_init    = virtio_rng_pci_class_init,
+};
+
 /* virtio-pci-bus */
 
 void virtio_pci_bus_new(VirtioBusState *bus, VirtIOPCIProxy *dev)
@@ -1588,7 +1560,7 @@ static const TypeInfo virtio_pci_bus_info = {
 
 static void virtio_pci_register_types(void)
 {
-    type_register_static(&virtio_rng_info);
+    type_register_static(&virtio_rng_pci_info);
     type_register_static(&virtio_pci_bus_info);
     type_register_static(&virtio_pci_info);
 #ifdef CONFIG_VIRTFS
diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h
index db0185c..ac71824 100644
--- a/hw/virtio/virtio-pci.h
+++ b/hw/virtio/virtio-pci.h
@@ -38,6 +38,7 @@ typedef struct VirtIOBalloonPCI VirtIOBalloonPCI;
 typedef struct VirtIOSerialPCI VirtIOSerialPCI;
 typedef struct VirtIONetPCI VirtIONetPCI;
 typedef struct VHostSCSIPCI VHostSCSIPCI;
+typedef struct VirtIORngPCI VirtIORngPCI;
 
 /* virtio-pci-bus */
 
@@ -87,7 +88,6 @@ struct VirtIOPCIProxy {
     uint32_t class_code;
     uint32_t nvectors;
     uint32_t host_features;
-    VirtIORNGConf rng;
     bool ioeventfd_disabled;
     bool ioeventfd_started;
     VirtIOIRQFD *vector_irqfd;
@@ -188,6 +188,18 @@ typedef struct V9fsPCIState {
 
 #endif
 
+/*
+ * virtio-rng-pci: This extends VirtioPCIProxy.
+ */
+#define TYPE_VIRTIO_RNG_PCI "virtio-rng-pci"
+#define VIRTIO_RNG_PCI(obj) \
+        OBJECT_CHECK(VirtIORngPCI, (obj), TYPE_VIRTIO_RNG_PCI)
+
+struct VirtIORngPCI {
+    VirtIOPCIProxy parent_obj;
+    VirtIORNG vdev;
+};
+
 void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev);
 void virtio_pci_bus_new(VirtioBusState *bus, VirtIOPCIProxy *dev);
 
commit 6eac8aec02b1e9c5a626820bcca7654cb7d006a7
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Wed Apr 24 10:07:55 2013 +0200

    virtio-rng: add virtio-rng device.
    
    Create virtio-rng-device which extends virtio-device, so it can be connected on
    virtio-bus.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Acked-by: Amit Shah <amit.shah at redhat.com>
    Message-id: 1366790881-3026-3-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 56539d3..7fdc8c3 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -958,8 +958,7 @@ static void virtio_ccw_rng_initfn(Object *obj)
 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_VIRTIO_RNG_PROPERTIES(VirtioCcwDevice, rng),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index a1f15a8..4860db1 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -989,13 +989,7 @@ static void virtio_rng_initfn(Object *obj)
 
 static Property virtio_rng_properties[] = {
     DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
-    /* Set a default rate limit of 2^47 bytes per minute or roughly 2TB/s.  If
-       you have an entropy source capable of generating more entropy than this
-       and you can pass it through via virtio-rng, then hats off to you.  Until
-       then, this is unlimited for all practical purposes.
-    */
-    DEFINE_PROP_UINT64("max-bytes", VirtIOPCIProxy, rng.max_bytes, INT64_MAX),
-    DEFINE_PROP_UINT32("period", VirtIOPCIProxy, rng.period_ms, 1 << 16),
+    DEFINE_VIRTIO_RNG_PROPERTIES(VirtIOPCIProxy, rng),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c
index 05b4d57..b70975b 100644
--- a/hw/virtio/virtio-rng.c
+++ b/hw/virtio/virtio-rng.c
@@ -130,17 +130,27 @@ static void check_rate_limit(void *opaque)
                    qemu_get_clock_ms(vm_clock) + s->conf.period_ms);
 }
 
-
-VirtIODevice *virtio_rng_init(DeviceState *dev, VirtIORNGConf *conf)
+static VirtIODevice *virtio_rng_common_init(DeviceState *dev,
+                                            VirtIORNGConf *conf,
+                                            VirtIORNG **pvrng)
 {
-    VirtIORNG *vrng;
+    VirtIORNG *vrng = *pvrng;
     VirtIODevice *vdev;
     Error *local_err = NULL;
 
-    vdev = virtio_common_init("virtio-rng", VIRTIO_ID_RNG, 0,
-                              sizeof(VirtIORNG));
-
-    vrng = DO_UPCAST(VirtIORNG, vdev, vdev);
+    /*
+     * We have two cases here: the old virtio-rng-x device, and the
+     * refactored virtio-rng.
+     * This will disappear later in the serie.
+     */
+    if (vrng == NULL) {
+        vdev = virtio_common_init("virtio-rng", VIRTIO_ID_RNG, 0,
+                                  sizeof(VirtIORNG));
+        vrng = DO_UPCAST(VirtIORNG, vdev, vdev);
+    } else {
+        vdev = VIRTIO_DEVICE(vrng);
+        virtio_init(vdev, "virtio-rng", VIRTIO_ID_RNG, 0);
+    }
 
     vrng->rng = conf->rng;
     if (vrng->rng == NULL) {
@@ -156,6 +166,7 @@ VirtIODevice *virtio_rng_init(DeviceState *dev, VirtIORNGConf *conf)
     }
 
     vrng->vq = virtio_add_queue(vdev, 8, handle_input);
+
     vrng->vdev.get_features = get_features;
 
     vrng->qdev = dev;
@@ -176,6 +187,15 @@ VirtIODevice *virtio_rng_init(DeviceState *dev, VirtIORNGConf *conf)
     return vdev;
 }
 
+/*
+ * This two functions will be removed later in the serie.
+ */
+VirtIODevice *virtio_rng_init(DeviceState *dev, VirtIORNGConf *conf)
+{
+    VirtIORNG *vdev = NULL;
+    return virtio_rng_common_init(dev, conf, &vdev);
+}
+
 void virtio_rng_exit(VirtIODevice *vdev)
 {
     VirtIORNG *vrng = DO_UPCAST(VirtIORNG, vdev, vdev);
@@ -185,3 +205,77 @@ void virtio_rng_exit(VirtIODevice *vdev)
     unregister_savevm(vrng->qdev, "virtio-rng", vrng);
     virtio_cleanup(vdev);
 }
+
+static int virtio_rng_device_init(VirtIODevice *vdev)
+{
+    DeviceState *qdev = DEVICE(vdev);
+    VirtIORNG *vrng = VIRTIO_RNG(vdev);
+
+    if (vrng->conf.rng == NULL) {
+        vrng->conf.default_backend = RNG_RANDOM(object_new(TYPE_RNG_RANDOM));
+
+        object_property_add_child(OBJECT(qdev),
+                                  "default-backend",
+                                  OBJECT(vrng->conf.default_backend),
+                                  NULL);
+
+        object_property_set_link(OBJECT(qdev),
+                                 OBJECT(vrng->conf.default_backend),
+                                 "rng", NULL);
+    }
+
+    if (virtio_rng_common_init(qdev, &(vrng->conf), &vrng) == NULL) {
+        return -1;
+    }
+    return 0;
+}
+
+static int virtio_rng_device_exit(DeviceState *qdev)
+{
+    VirtIORNG *vrng = VIRTIO_RNG(qdev);
+    VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
+
+    qemu_del_timer(vrng->rate_limit_timer);
+    qemu_free_timer(vrng->rate_limit_timer);
+    unregister_savevm(qdev, "virtio-rng", vrng);
+    virtio_common_cleanup(vdev);
+    return 0;
+}
+
+static Property virtio_rng_properties[] = {
+    DEFINE_VIRTIO_RNG_PROPERTIES(VirtIORNG, conf),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_rng_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
+    dc->exit = virtio_rng_device_exit;
+    dc->props = virtio_rng_properties;
+    vdc->init = virtio_rng_device_init;
+    vdc->get_features = get_features;
+}
+
+static void virtio_rng_initfn(Object *obj)
+{
+    VirtIORNG *vrng = VIRTIO_RNG(obj);
+
+    object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
+                             (Object **)&vrng->conf.rng, NULL);
+}
+
+static const TypeInfo virtio_rng_info = {
+    .name = TYPE_VIRTIO_RNG,
+    .parent = TYPE_VIRTIO_DEVICE,
+    .instance_size = sizeof(VirtIORNG),
+    .instance_init = virtio_rng_initfn,
+    .class_init = virtio_rng_class_init,
+};
+
+static void virtio_register_types(void)
+{
+    type_register_static(&virtio_rng_info);
+}
+
+type_init(virtio_register_types)
diff --git a/include/hw/virtio/virtio-rng.h b/include/hw/virtio/virtio-rng.h
index c578c00..973d809 100644
--- a/include/hw/virtio/virtio-rng.h
+++ b/include/hw/virtio/virtio-rng.h
@@ -15,6 +15,10 @@
 #include "sysemu/rng.h"
 #include "sysemu/rng-random.h"
 
+#define TYPE_VIRTIO_RNG "virtio-rng-device"
+#define VIRTIO_RNG(obj) \
+        OBJECT_CHECK(VirtIORNG, (obj), TYPE_VIRTIO_RNG)
+
 /* The Virtio ID for the virtio rng device */
 #define VIRTIO_ID_RNG    4
 
@@ -44,4 +48,14 @@ typedef struct VirtIORNG {
     int64_t quota_remaining;
 } VirtIORNG;
 
+/* Set a default rate limit of 2^47 bytes per minute or roughly 2TB/s.  If
+   you have an entropy source capable of generating more entropy than this
+   and you can pass it through via virtio-rng, then hats off to you.  Until
+   then, this is unlimited for all practical purposes.
+*/
+#define DEFINE_VIRTIO_RNG_PROPERTIES(_state, _conf_field)                    \
+        DEFINE_PROP_UINT64("max-bytes", _state, _conf_field.max_bytes,       \
+                           INT64_MAX),                                       \
+        DEFINE_PROP_UINT32("period", _state, _conf_field.period_ms, 1 << 16)
+
 #endif
commit af1a8ad6467eb7056573bc3580d3d1824a05224a
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Wed Apr 24 10:07:54 2013 +0200

    virtio-rng: don't use pointer for configuration.
    
    The configuration field must not be a pointer as it will be used for
    virtio-rng properties. So *conf is replaced by conf.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Acked-by: Amit Shah <amit.shah at redhat.com>
    Message-id: 1366790881-3026-2-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c
index fcc223a..05b4d57 100644
--- a/hw/virtio/virtio-rng.c
+++ b/hw/virtio/virtio-rng.c
@@ -124,10 +124,10 @@ static void check_rate_limit(void *opaque)
 {
     VirtIORNG *s = opaque;
 
-    s->quota_remaining = s->conf->max_bytes;
+    s->quota_remaining = s->conf.max_bytes;
     virtio_rng_process(s);
     qemu_mod_timer(s->rate_limit_timer,
-                   qemu_get_clock_ms(vm_clock) + s->conf->period_ms);
+                   qemu_get_clock_ms(vm_clock) + s->conf.period_ms);
 }
 
 
@@ -159,16 +159,16 @@ VirtIODevice *virtio_rng_init(DeviceState *dev, VirtIORNGConf *conf)
     vrng->vdev.get_features = get_features;
 
     vrng->qdev = dev;
-    vrng->conf = conf;
+    memcpy(&(vrng->conf), conf, sizeof(struct VirtIORNGConf));
 
-    assert(vrng->conf->max_bytes <= INT64_MAX);
-    vrng->quota_remaining = vrng->conf->max_bytes;
+    assert(vrng->conf.max_bytes <= INT64_MAX);
+    vrng->quota_remaining = vrng->conf.max_bytes;
 
     vrng->rate_limit_timer = qemu_new_timer_ms(vm_clock,
                                                check_rate_limit, vrng);
 
     qemu_mod_timer(vrng->rate_limit_timer,
-                   qemu_get_clock_ms(vm_clock) + vrng->conf->period_ms);
+                   qemu_get_clock_ms(vm_clock) + vrng->conf.period_ms);
 
     register_savevm(dev, "virtio-rng", -1, 1, virtio_rng_save,
                     virtio_rng_load, vrng);
diff --git a/include/hw/virtio/virtio-rng.h b/include/hw/virtio/virtio-rng.h
index c9cadc2..c578c00 100644
--- a/include/hw/virtio/virtio-rng.h
+++ b/include/hw/virtio/virtio-rng.h
@@ -33,7 +33,7 @@ typedef struct VirtIORNG {
     /* Only one vq - guest puts buffer(s) on it when it needs entropy */
     VirtQueue *vq;
 
-    VirtIORNGConf *conf;
+    VirtIORNGConf conf;
 
     RngBackend *rng;
 
commit 5a37532d0897de488c35ab2db6d86647bd2a1b6f
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Apr 24 12:08:38 2013 +0200

    input: introduce keyboard handler list
    
    Add a linked list of keyboard handlers.  Added handlers will go
    to the head of the list.  Removed handlers will be zapped from
    the list.  The head of the list will be used for events.
    
    This fixes the keyboard-dead-after-usb-kbd-unplug issue, key events
    will be re-routed to the ps/2 kbd instead of being discarded.
    
    [ v2: fix cut+paste bug found my Markus ]
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
    Message-id: 1366798118-3248-3-git-send-email-kraxel at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/input/hid.c b/hw/input/hid.c
index 5fbde98..14b3125 100644
--- a/hw/input/hid.c
+++ b/hw/input/hid.c
@@ -415,7 +415,7 @@ void hid_free(HIDState *hs)
 {
     switch (hs->kind) {
     case HID_KEYBOARD:
-        qemu_remove_kbd_event_handler();
+        qemu_remove_kbd_event_handler(hs->kbd.eh_entry);
         break;
     case HID_MOUSE:
     case HID_TABLET:
@@ -431,7 +431,7 @@ void hid_init(HIDState *hs, int kind, HIDEventFunc event)
     hs->event = event;
 
     if (hs->kind == HID_KEYBOARD) {
-        qemu_add_kbd_event_handler(hid_keyboard_event, hs);
+        hs->kbd.eh_entry = qemu_add_kbd_event_handler(hid_keyboard_event, hs);
     } else if (hs->kind == HID_MOUSE) {
         hs->ptr.eh_entry = qemu_add_mouse_event_handler(hid_pointer_event, hs,
                                                         0, "QEMU HID Mouse");
diff --git a/include/hw/input/hid.h b/include/hw/input/hid.h
index 56c71ed..2567879 100644
--- a/include/hw/input/hid.h
+++ b/include/hw/input/hid.h
@@ -31,6 +31,7 @@ typedef struct HIDKeyboardState {
     uint8_t leds;
     uint8_t key[16];
     int32_t keys;
+    QEMUPutKbdEntry *eh_entry;
 } HIDKeyboardState;
 
 struct HIDState {
diff --git a/include/ui/console.h b/include/ui/console.h
index 5cc5d0c..1c82f51 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -29,10 +29,12 @@ typedef void QEMUPutLEDEvent(void *opaque, int ledstate);
 typedef void QEMUPutMouseEvent(void *opaque, int dx, int dy, int dz, int buttons_state);
 
 typedef struct QEMUPutMouseEntry QEMUPutMouseEntry;
+typedef struct QEMUPutKbdEntry QEMUPutKbdEntry;
 typedef struct QEMUPutLEDEntry QEMUPutLEDEntry;
 
-void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque);
-void qemu_remove_kbd_event_handler(void);
+QEMUPutKbdEntry *qemu_add_kbd_event_handler(QEMUPutKBDEvent *func,
+                                            void *opaque);
+void qemu_remove_kbd_event_handler(QEMUPutKbdEntry *entry);
 QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
                                                 void *opaque, int absolute,
                                                 const char *name);
diff --git a/ui/input.c b/ui/input.c
index d8793e7..8ca1a03 100644
--- a/ui/input.c
+++ b/ui/input.c
@@ -41,18 +41,25 @@ struct QEMUPutMouseEntry {
     QTAILQ_ENTRY(QEMUPutMouseEntry) node;
 };
 
+struct QEMUPutKbdEntry {
+    QEMUPutKBDEvent *put_kbd;
+    void *opaque;
+    QTAILQ_ENTRY(QEMUPutKbdEntry) next;
+};
+
 struct QEMUPutLEDEntry {
     QEMUPutLEDEvent *put_led;
     void *opaque;
     QTAILQ_ENTRY(QEMUPutLEDEntry) next;
 };
 
-static QEMUPutKBDEvent *qemu_put_kbd_event;
-static void *qemu_put_kbd_event_opaque;
-static QTAILQ_HEAD(, QEMUPutLEDEntry) led_handlers = QTAILQ_HEAD_INITIALIZER(led_handlers);
+static QTAILQ_HEAD(, QEMUPutLEDEntry) led_handlers =
+    QTAILQ_HEAD_INITIALIZER(led_handlers);
+static QTAILQ_HEAD(, QEMUPutKbdEntry) kbd_handlers =
+    QTAILQ_HEAD_INITIALIZER(kbd_handlers);
 static QTAILQ_HEAD(, QEMUPutMouseEntry) mouse_handlers =
     QTAILQ_HEAD_INITIALIZER(mouse_handlers);
-static NotifierList mouse_mode_notifiers = 
+static NotifierList mouse_mode_notifiers =
     NOTIFIER_LIST_INITIALIZER(mouse_mode_notifiers);
 
 static const int key_defs[] = {
@@ -304,16 +311,20 @@ void qmp_send_key(KeyValueList *keys, bool has_hold_time, int64_t hold_time,
                    muldiv64(get_ticks_per_sec(), hold_time, 1000));
 }
 
-void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
+QEMUPutKbdEntry *qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
 {
-    qemu_put_kbd_event_opaque = opaque;
-    qemu_put_kbd_event = func;
+    QEMUPutKbdEntry *entry;
+
+    entry = g_malloc0(sizeof(QEMUPutKbdEntry));
+    entry->put_kbd = func;
+    entry->opaque = opaque;
+    QTAILQ_INSERT_HEAD(&kbd_handlers, entry, next);
+    return entry;
 }
 
-void qemu_remove_kbd_event_handler(void)
+void qemu_remove_kbd_event_handler(QEMUPutKbdEntry *entry)
 {
-    qemu_put_kbd_event_opaque = NULL;
-    qemu_put_kbd_event = NULL;
+    QTAILQ_REMOVE(&kbd_handlers, entry, next);
 }
 
 static void check_mode_change(void)
@@ -397,11 +408,13 @@ void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry)
 
 void kbd_put_keycode(int keycode)
 {
+    QEMUPutKbdEntry *entry = QTAILQ_FIRST(&kbd_handlers);
+
     if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) {
         return;
     }
-    if (qemu_put_kbd_event) {
-        qemu_put_kbd_event(qemu_put_kbd_event_opaque, keycode);
+    if (entry) {
+        entry->put_kbd(entry->opaque, keycode);
     }
 }
 
commit 72711efb58c13e28c89813490120b32947a2d719
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Apr 24 12:08:37 2013 +0200

    input: make QEMUPutLEDEntry + QEMUPutMouseEntry private
    
    There is no need for anybody outside ui/input.c to access the
    struct elements.  Move the definitions, leaving only the typedefs
    in the header files.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
    Message-id: 1366798118-3248-2-git-send-email-kraxel at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/include/ui/console.h b/include/ui/console.h
index e591d74..5cc5d0c 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -28,23 +28,8 @@ typedef void QEMUPutKBDEvent(void *opaque, int keycode);
 typedef void QEMUPutLEDEvent(void *opaque, int ledstate);
 typedef void QEMUPutMouseEvent(void *opaque, int dx, int dy, int dz, int buttons_state);
 
-typedef struct QEMUPutMouseEntry {
-    QEMUPutMouseEvent *qemu_put_mouse_event;
-    void *qemu_put_mouse_event_opaque;
-    int qemu_put_mouse_event_absolute;
-    char *qemu_put_mouse_event_name;
-
-    int index;
-
-    /* used internally by qemu for handling mice */
-    QTAILQ_ENTRY(QEMUPutMouseEntry) node;
-} QEMUPutMouseEntry;
-
-typedef struct QEMUPutLEDEntry {
-    QEMUPutLEDEvent *put_led;
-    void *opaque;
-    QTAILQ_ENTRY(QEMUPutLEDEntry) next;
-} QEMUPutLEDEntry;
+typedef struct QEMUPutMouseEntry QEMUPutMouseEntry;
+typedef struct QEMUPutLEDEntry QEMUPutLEDEntry;
 
 void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque);
 void qemu_remove_kbd_event_handler(void);
diff --git a/ui/input.c b/ui/input.c
index ecfeb43..d8793e7 100644
--- a/ui/input.c
+++ b/ui/input.c
@@ -29,6 +29,24 @@
 #include "qmp-commands.h"
 #include "qapi-types.h"
 
+struct QEMUPutMouseEntry {
+    QEMUPutMouseEvent *qemu_put_mouse_event;
+    void *qemu_put_mouse_event_opaque;
+    int qemu_put_mouse_event_absolute;
+    char *qemu_put_mouse_event_name;
+
+    int index;
+
+    /* used internally by qemu for handling mice */
+    QTAILQ_ENTRY(QEMUPutMouseEntry) node;
+};
+
+struct QEMUPutLEDEntry {
+    QEMUPutLEDEvent *put_led;
+    void *opaque;
+    QTAILQ_ENTRY(QEMUPutLEDEntry) next;
+};
+
 static QEMUPutKBDEvent *qemu_put_kbd_event;
 static void *qemu_put_kbd_event_opaque;
 static QTAILQ_HEAD(, QEMUPutLEDEntry) led_handlers = QTAILQ_HEAD_INITIALIZER(led_handlers);
commit a3ac6b53d4e8ed6fa2ca1af87c68a8b7d5535220
Author: Hu Tao <hutao at cn.fujitsu.com>
Date:   Wed Apr 24 18:37:22 2013 +0800

    ich9: kill cmos_s3
    
    Signed-off-by: Hu Tao <hutao at cn.fujitsu.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Message-id: 1366799842-18550-1-git-send-email-hutao at cn.fujitsu.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c
index e663d29..4a17f32 100644
--- a/hw/acpi/ich9.c
+++ b/hw/acpi/ich9.c
@@ -203,7 +203,7 @@ static void pm_powerdown_req(Notifier *n, void *opaque)
 }
 
 void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
-                  qemu_irq sci_irq, qemu_irq cmos_s3)
+                  qemu_irq sci_irq)
 {
     memory_region_init(&pm->io, "ich9-pm", ICH9_PMIO_SIZE);
     memory_region_set_enabled(&pm->io, false);
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 6ac1a89..e5f417e 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -45,17 +45,6 @@
 /* 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)
 {
@@ -84,7 +73,6 @@ static void pc_q35_init(QEMUMachineInitArgs *args)
     int i;
     ICH9LPCState *ich9_lpc;
     PCIDevice *ahci;
-    qemu_irq *cmos_s3;
 
     pc_cpus_init(cpu_model);
     pc_acpi_init("q35-acpi-dsdt.aml");
@@ -175,8 +163,7 @@ static void pc_q35_init(QEMUMachineInitArgs *args)
     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);
+    ich9_lpc_pm_init(lpc);
 
     /* ahci and SATA device, for q35 1 ahci controller is built-in */
     ahci = pci_create_simple_multifunction(host_bus,
diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c
index d116075..667e882 100644
--- a/hw/isa/lpc_ich9.c
+++ b/hw/isa/lpc_ich9.c
@@ -356,13 +356,13 @@ static void ich9_set_sci(void *opaque, int irq_num, int level)
     }
 }
 
-void ich9_lpc_pm_init(PCIDevice *lpc_pci, qemu_irq cmos_s3)
+void ich9_lpc_pm_init(PCIDevice *lpc_pci)
 {
     ICH9LPCState *lpc = ICH9_LPC_DEVICE(lpc_pci);
     qemu_irq *sci_irq;
 
     sci_irq = qemu_allocate_irqs(ich9_set_sci, lpc, 1);
-    ich9_pm_init(lpc_pci, &lpc->pm, sci_irq[0], cmos_s3);
+    ich9_pm_init(lpc_pci, &lpc->pm, sci_irq[0]);
 
     ich9_lpc_reset(&lpc->d.qdev);
 }
diff --git a/include/hw/acpi/ich9.h b/include/hw/acpi/ich9.h
index 85b82ee..b1fe71f 100644
--- a/include/hw/acpi/ich9.h
+++ b/include/hw/acpi/ich9.h
@@ -45,7 +45,7 @@ typedef struct ICH9LPCPMRegs {
 } ICH9LPCPMRegs;
 
 void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
-                  qemu_irq sci_irq, qemu_irq cmos_s3_resume);
+                  qemu_irq sci_irq);
 void ich9_pm_iospace_update(ICH9LPCPMRegs *pm, uint32_t pm_io_base);
 extern const VMStateDescription vmstate_ich9_pm;
 
diff --git a/include/hw/i386/ich9.h b/include/hw/i386/ich9.h
index 51d5981..c5f637b 100644
--- a/include/hw/i386/ich9.h
+++ b/include/hw/i386/ich9.h
@@ -18,7 +18,7 @@
 void ich9_lpc_set_irq(void *opaque, int irq_num, int level);
 int ich9_lpc_map_irq(PCIDevice *pci_dev, int intx);
 PCIINTxRoute ich9_route_intx_pin_to_irq(void *opaque, int pirq_pin);
-void ich9_lpc_pm_init(PCIDevice *pci_lpc, qemu_irq cmos_s3);
+void ich9_lpc_pm_init(PCIDevice *pci_lpc);
 PCIBus *ich9_d2pbr_init(PCIBus *bus, int devfn, int sec_bus);
 i2c_bus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t smb_io_base);
 
commit 57f97834efe0c208ffadc9d2959f3d3d55580e52
Author: Alon Levy <alevy at redhat.com>
Date:   Mon Mar 4 21:43:36 2013 +0200

    libcacard/cac: change big switch functions to single return point
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Reviewed-by: Marc-André Lureau <mlureau at redhat.com>

diff --git a/libcacard/cac.c b/libcacard/cac.c
index 5864539..7a06b5a 100644
--- a/libcacard/cac.c
+++ b/libcacard/cac.c
@@ -40,41 +40,51 @@ static VCardStatus
 cac_common_process_apdu(VCard *card, VCardAPDU *apdu, VCardResponse **response)
 {
     int ef;
+    VCardStatus ret = VCARD_FAIL;
 
     switch (apdu->a_ins) {
     case VCARD7816_INS_SELECT_FILE:
         if (apdu->a_p1 != 0x02) {
             /* let the 7816 code handle applet switches */
-            return VCARD_NEXT;
+            ret = VCARD_NEXT;
+            break;
         }
         /* handle file id setting */
         if (apdu->a_Lc != 2) {
             *response = vcard_make_response(
                 VCARD7816_STATUS_ERROR_DATA_INVALID);
-            return VCARD_DONE;
+            ret = VCARD_DONE;
+            break;
         }
         /* CAC 1.0 only supports ef = 0 */
         ef = apdu->a_body[0] | (apdu->a_body[1] << 8);
         if (ef != 0) {
             *response = vcard_make_response(
                 VCARD7816_STATUS_ERROR_FILE_NOT_FOUND);
-            return VCARD_DONE;
+            ret = VCARD_DONE;
+            break;
         }
         *response = vcard_make_response(VCARD7816_STATUS_SUCCESS);
-        return VCARD_DONE;
+        ret = VCARD_DONE;
+        break;
     case VCARD7816_INS_GET_RESPONSE:
     case VCARD7816_INS_VERIFY:
         /* let the 7816 code handle these */
-        return VCARD_NEXT;
+        ret = VCARD_NEXT;
+        break;
     case CAC_GET_PROPERTIES:
     case CAC_GET_ACR:
         /* skip these for now, this will probably be needed */
         *response = vcard_make_response(VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
-        return VCARD_DONE;
+        ret = VCARD_DONE;
+        break;
+    default:
+        *response = vcard_make_response(
+            VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
+        ret = VCARD_DONE;
+        break;
     }
-    *response = vcard_make_response(
-        VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
-    return VCARD_DONE;
+    return ret;
 }
 
 /*
@@ -108,6 +118,7 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu,
     int size, next;
     unsigned char *sign_buffer;
     vcard_7816_status_t status;
+    VCardStatus ret = VCARD_FAIL;
 
     applet_private = vcard_get_current_applet_private(card, apdu->a_channel);
     assert(applet_private);
@@ -117,7 +128,8 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu,
     case CAC_UPDATE_BUFFER:
         *response = vcard_make_response(
             VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED);
-        return VCARD_DONE;
+        ret = VCARD_DONE;
+        break;
     case CAC_GET_CERTIFICATE:
         if ((apdu->a_p2 != 0) || (apdu->a_p1 != 0)) {
             *response = vcard_make_response(
@@ -147,7 +159,8 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu,
             *response = vcard_make_response(
                             VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
         }
-        return VCARD_DONE;
+        ret = VCARD_DONE;
+        break;
     case CAC_SIGN_DECRYPT:
         if (apdu->a_p2 != 0) {
             *response = vcard_make_response(
@@ -164,7 +177,8 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu,
             pki_applet->sign_buffer_len = 0;
             *response = vcard_make_response(
                             VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
-            return VCARD_DONE;
+            ret = VCARD_DONE;
+            break;
         }
         memcpy(sign_buffer+pki_applet->sign_buffer_len, apdu->a_body, size);
         size += pki_applet->sign_buffer_len;
@@ -175,7 +189,8 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu,
             pki_applet->sign_buffer = sign_buffer;
             pki_applet->sign_buffer_len = size;
             *response = vcard_make_response(VCARD7816_STATUS_SUCCESS);
-            return VCARD_DONE;
+            ret = VCARD_DONE;
+            break;
         case 0x00:
             /* we now have the whole buffer, do the operation, result will be
              * in the sign_buffer */
@@ -200,15 +215,20 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu,
         g_free(sign_buffer);
         pki_applet->sign_buffer = NULL;
         pki_applet->sign_buffer_len = 0;
-        return VCARD_DONE;
+        ret = VCARD_DONE;
+        break;
     case CAC_READ_BUFFER:
         /* new CAC call, go ahead and use the old version for now */
         /* TODO: implement */
         *response = vcard_make_response(
                                 VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
-        return VCARD_DONE;
+        ret = VCARD_DONE;
+        break;
+    default:
+        ret = cac_common_process_apdu(card, apdu, response);
+        break;
     }
-    return cac_common_process_apdu(card, apdu, response);
+    return ret;
 }
 
 
@@ -216,19 +236,26 @@ static VCardStatus
 cac_applet_id_process_apdu(VCard *card, VCardAPDU *apdu,
                            VCardResponse **response)
 {
+    VCardStatus ret = VCARD_FAIL;
+
     switch (apdu->a_ins) {
     case CAC_UPDATE_BUFFER:
         *response = vcard_make_response(
                         VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED);
-        return VCARD_DONE;
+        ret = VCARD_DONE;
+        break;
     case CAC_READ_BUFFER:
         /* new CAC call, go ahead and use the old version for now */
         /* TODO: implement */
         *response = vcard_make_response(
                         VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
-        return VCARD_DONE;
+        ret = VCARD_DONE;
+        break;
+    default:
+        ret = cac_common_process_apdu(card, apdu, response);
+        break;
     }
-    return cac_common_process_apdu(card, apdu, response);
+    return ret;
 }
 
 
@@ -240,16 +267,20 @@ static VCardStatus
 cac_applet_container_process_apdu(VCard *card, VCardAPDU *apdu,
                                   VCardResponse **response)
 {
+    VCardStatus ret = VCARD_FAIL;
+
     switch (apdu->a_ins) {
     case CAC_READ_BUFFER:
     case CAC_UPDATE_BUFFER:
         *response = vcard_make_response(
                         VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
-        return VCARD_DONE;
+        ret = VCARD_DONE;
+        break;
     default:
+        ret = cac_common_process_apdu(card, apdu, response);
         break;
     }
-    return cac_common_process_apdu(card, apdu, response);
+    return ret;
 }
 
 /*
commit 58aeda15abb963196faaa4a0f23c5af45840f1b0
Author: Alon Levy <alevy at redhat.com>
Date:   Tue Mar 5 17:31:10 2013 +0200

    dev-smartcard-reader: empty implementation for Mechanical (fail correctly)
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Reviewed-by: Marc-André Lureau <mlureau at redhat.com>

diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index 78ef504..125cc2c 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -1051,6 +1051,10 @@ static void ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
             ccid_reset_error_status(s);
             ccid_write_parameters(s, ccid_header);
             break;
+        case CCID_MESSAGE_TYPE_PC_to_RDR_Mechanical:
+            ccid_report_error_failed(s, 0);
+            ccid_write_slot_status(s, ccid_header);
+            break;
         default:
             DPRINTF(s, 1,
                 "handle_data: ERROR: unhandled message type %Xh\n",
commit 0b6a16c1a47b622b1a692ab179013d9e30e9cf3b
Author: Alon Levy <alevy at redhat.com>
Date:   Tue Mar 5 16:27:43 2013 +0200

    libcacard: move atr setting from macro to function
    
    Only because qemu's checkpatch complains about it.
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Reviewed-by: Marc-André Lureau <mlureau at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index a473348..fcb303a 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -32,6 +32,7 @@ libcacard-y += libcacard/vcard.o libcacard/vreader.o
 libcacard-y += libcacard/vcard_emul_nss.o
 libcacard-y += libcacard/vcard_emul_type.o
 libcacard-y += libcacard/card_7816.o
+libcacard-y += libcacard/vcardt.o
 
 ######################################################################
 # Target independent part of system emulation. The long term path is to
diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c
index 9ba80fb..1a3e568 100644
--- a/libcacard/vcard_emul_nss.c
+++ b/libcacard/vcard_emul_nss.c
@@ -33,6 +33,9 @@
 #include "vreader.h"
 #include "vevent.h"
 
+#include "libcacard/vcardt_internal.h"
+
+
 typedef enum {
     VCardEmulUnknown = -1,
     VCardEmulFalse = 0,
@@ -519,18 +522,23 @@ vcard_emul_reader_get_slot(VReader *vreader)
 }
 
 /*
- *  Card ATR's map to physical cards. VCARD_ATR_PREFIX will set appropriate
+ *  Card ATR's map to physical cards. vcard_alloc_atr will set appropriate
  *  historical bytes for any software emulated card. The remaining bytes can be
  *  used to indicate the actual emulator
  */
-static const unsigned char nss_atr[] = { VCARD_ATR_PREFIX(3), 'N', 'S', 'S' };
+static unsigned char *nss_atr;
+static int nss_atr_len;
 
 void
 vcard_emul_get_atr(VCard *card, unsigned char *atr, int *atr_len)
 {
-    int len = MIN(sizeof(nss_atr), *atr_len);
+    int len;
     assert(atr != NULL);
 
+    if (nss_atr == NULL) {
+        nss_atr = vcard_alloc_atr("NSS", &nss_atr_len);
+    }
+    len = MIN(nss_atr_len, *atr_len);
     memcpy(atr, nss_atr, len);
     *atr_len = len;
 }
diff --git a/libcacard/vcardt.c b/libcacard/vcardt.c
new file mode 100644
index 0000000..9ce4648
--- /dev/null
+++ b/libcacard/vcardt.c
@@ -0,0 +1,40 @@
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+
+#include "libcacard/vcardt.h"
+
+#include "libcacard/vcardt_internal.h"
+
+/* create an ATR with appropriate historical bytes */
+#define ATR_TS_DIRECT_CONVENTION 0x3b
+#define ATR_TA_PRESENT 0x10
+#define ATR_TB_PRESENT 0x20
+#define ATR_TC_PRESENT 0x40
+#define ATR_TD_PRESENT 0x80
+
+unsigned char *vcard_alloc_atr(const char *postfix, int *atr_len)
+{
+    int postfix_len;
+    const char prefix[] = "VCARD_";
+    const char default_postfix[] = "DEFAULT";
+    const int prefix_len = sizeof(prefix) - 1;
+    int total_len;
+    unsigned char *atr;
+
+    if (postfix == NULL) {
+        postfix = default_postfix;
+    }
+    postfix_len = strlen(postfix);
+    total_len = 3 + prefix_len + postfix_len;
+    atr = g_malloc(total_len);
+    atr[0] = ATR_TS_DIRECT_CONVENTION;
+    atr[1] = ATR_TD_PRESENT + prefix_len + postfix_len;
+    atr[2] = 0x00;
+    memcpy(&atr[3], prefix, prefix_len);
+    memcpy(&atr[3 + prefix_len], postfix, postfix_len);
+    if (atr_len) {
+        *atr_len = total_len;
+    }
+    return atr;
+}
diff --git a/libcacard/vcardt.h b/libcacard/vcardt.h
index 3b9a619..795e265 100644
--- a/libcacard/vcardt.h
+++ b/libcacard/vcardt.h
@@ -25,19 +25,6 @@ typedef struct VCardEmulStruct VCardEmul;
 
 #define MAX_CHANNEL 4
 
-/* create an ATR with appropriate historical bytes */
-#define TS_DIRECT_CONVENTION 0x3b
-#define TA_PRESENT 0x10
-#define TB_PRESENT 0x20
-#define TC_PRESENT 0x40
-#define TD_PRESENT 0x80
-
-#define VCARD_ATR_PREFIX(size) \
-    TS_DIRECT_CONVENTION, \
-    TD_PRESENT + (6 + size), \
-    0x00, \
-    'V', 'C', 'A', 'R', 'D', '_'
-
 typedef enum {
     VCARD_DONE,
     VCARD_NEXT,
diff --git a/libcacard/vcardt_internal.h b/libcacard/vcardt_internal.h
new file mode 100644
index 0000000..e5c8d2d
--- /dev/null
+++ b/libcacard/vcardt_internal.h
@@ -0,0 +1,6 @@
+#ifndef VCARDT_INTERNAL_H
+#define VCARDT_INTERNAL_H
+
+unsigned char *vcard_alloc_atr(const char *postfix, int *atr_len);
+
+#endif
commit 7a6858962457c54be44715d6562504c765d9ea76
Author: Alon Levy <alevy at redhat.com>
Date:   Tue Mar 5 15:32:19 2013 +0200

    libcacard/vreader: add debugging messages for apdu
    
    Using g_debug with log domain libcacard
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Reviewed-by: Marc-André Lureau <mlureau at redhat.com>

diff --git a/libcacard/cac.c b/libcacard/cac.c
index 927a4ca..5864539 100644
--- a/libcacard/cac.c
+++ b/libcacard/cac.c
@@ -12,13 +12,6 @@
 #include "vcard_emul.h"
 #include "card_7816.h"
 
-#define CAC_GET_PROPERTIES  0x56
-#define CAC_GET_ACR         0x4c
-#define CAC_READ_BUFFER     0x52
-#define CAC_UPDATE_BUFFER   0x58
-#define CAC_SIGN_DECRYPT    0x42
-#define CAC_GET_CERTIFICATE 0x36
-
 /* private data for PKI applets */
 typedef struct CACPKIAppletDataStruct {
     unsigned char *cert;
diff --git a/libcacard/cac.h b/libcacard/cac.h
index 15a61be..d24a2a8 100644
--- a/libcacard/cac.h
+++ b/libcacard/cac.h
@@ -9,6 +9,14 @@
 #define CAC_H 1
 #include "vcard.h"
 #include "vreader.h"
+
+#define CAC_GET_PROPERTIES  0x56
+#define CAC_GET_ACR         0x4c
+#define CAC_READ_BUFFER     0x52
+#define CAC_UPDATE_BUFFER   0x58
+#define CAC_SIGN_DECRYPT    0x42
+#define CAC_GET_CERTIFICATE 0x36
+
 /*
  * Initialize the cac card. This is the only public function in this file. All
  * the rest are connected through function pointers.
diff --git a/libcacard/vreader.c b/libcacard/vreader.c
index f3efc27..5793d73 100644
--- a/libcacard/vreader.c
+++ b/libcacard/vreader.c
@@ -5,6 +5,12 @@
  * See the COPYING.LIB file in the top-level directory.
  */
 
+#ifdef G_LOG_DOMAIN
+#undef G_LOG_DOMAIN
+#endif
+#define G_LOG_DOMAIN "libcacard"
+#include <glib.h>
+
 #include "qemu-common.h"
 #include "qemu/thread.h"
 
@@ -13,6 +19,9 @@
 #include "card_7816.h"
 #include "vreader.h"
 #include "vevent.h"
+#include "cac.h" /* just for debugging defines */
+
+#define LIBCACARD_LOG_DOMAIN "libcacard"
 
 struct VReaderStruct {
     int    reference_count;
@@ -24,6 +33,66 @@ struct VReaderStruct {
     VReaderEmulFree reader_private_free;
 };
 
+/*
+ * Debug helpers
+ */
+
+static const char *
+apdu_ins_to_string(int ins)
+{
+    switch (ins) {
+    case VCARD7816_INS_MANAGE_CHANNEL:
+        return "manage channel";
+    case VCARD7816_INS_EXTERNAL_AUTHENTICATE:
+        return "external authenticate";
+    case VCARD7816_INS_GET_CHALLENGE:
+        return "get challenge";
+    case VCARD7816_INS_INTERNAL_AUTHENTICATE:
+        return "internal authenticate";
+    case VCARD7816_INS_ERASE_BINARY:
+        return "erase binary";
+    case VCARD7816_INS_READ_BINARY:
+        return "read binary";
+    case VCARD7816_INS_WRITE_BINARY:
+        return "write binary";
+    case VCARD7816_INS_UPDATE_BINARY:
+        return "update binary";
+    case VCARD7816_INS_READ_RECORD:
+        return "read record";
+    case VCARD7816_INS_WRITE_RECORD:
+        return "write record";
+    case VCARD7816_INS_UPDATE_RECORD:
+        return "update record";
+    case VCARD7816_INS_APPEND_RECORD:
+        return "append record";
+    case VCARD7816_INS_ENVELOPE:
+        return "envelope";
+    case VCARD7816_INS_PUT_DATA:
+        return "put data";
+    case VCARD7816_INS_GET_DATA:
+        return "get data";
+    case VCARD7816_INS_SELECT_FILE:
+        return "select file";
+    case VCARD7816_INS_VERIFY:
+        return "verify";
+    case VCARD7816_INS_GET_RESPONSE:
+        return "get response";
+    case CAC_GET_PROPERTIES:
+        return "get properties";
+    case CAC_GET_ACR:
+        return "get acr";
+    case CAC_READ_BUFFER:
+        return "read buffer";
+    case CAC_UPDATE_BUFFER:
+        return "update buffer";
+    case CAC_SIGN_DECRYPT:
+        return "sign decrypt";
+    case CAC_GET_CERTIFICATE:
+        return "get certificate";
+    }
+    return "unknown";
+}
+
 /* manage locking */
 static inline void
 vreader_lock(VReader *reader)
@@ -204,7 +273,15 @@ vreader_xfr_bytes(VReader *reader,
         response = vcard_make_response(status);
         card_status = VCARD_DONE;
     } else {
+        g_debug("%s: CLS=0x%x,INS=0x%x,P1=0x%x,P2=0x%x,Lc=%d,Le=%d %s\n",
+              __func__, apdu->a_cla, apdu->a_ins, apdu->a_p1, apdu->a_p2,
+              apdu->a_Lc, apdu->a_Le, apdu_ins_to_string(apdu->a_ins));
         card_status = vcard_process_apdu(card, apdu, &response);
+        if (response) {
+            g_debug("%s: status=%d sw1=0x%x sw2=0x%x len=%d (total=%d)\n",
+                  __func__, response->b_status, response->b_sw1,
+                  response->b_sw2, response->b_len, response->b_total_len);
+        }
     }
     assert(card_status == VCARD_DONE);
     if (card_status == VCARD_DONE) {
commit 2f8f916b6d4482976bb5cf179f65aa2cfcd1aec9
Author: Alon Levy <alevy at redhat.com>
Date:   Mon Mar 4 18:58:29 2013 +0200

    dev-smartcard-reader: copy atr protocol to ccid parameters
    
    Adds todos.
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Reviewed-by: Marc-André Lureau <mlureau at redhat.com>

diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index 8022f9f..78ef504 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -833,14 +833,59 @@ static void ccid_write_data_block_answer(USBCCIDState *s,
     ccid_write_data_block(s, slot, seq, data, len);
 }
 
+static uint8_t atr_get_protocol_num(const uint8_t *atr, uint32_t len)
+{
+    int i;
+
+    if (len < 2 || !(atr[1] & 0x80)) {
+        /* too short or TD1 not included */
+        return 0; /* T=0, default */
+    }
+    i = 1 + !!(atr[1] & 0x10) + !!(atr[1] & 0x20) + !!(atr[1] & 0x40);
+    i += !!(atr[1] & 0x80);
+    return atr[i] & 0x0f;
+}
+
 static void ccid_write_data_block_atr(USBCCIDState *s, CCID_Header *recv)
 {
     const uint8_t *atr = NULL;
     uint32_t len = 0;
+    uint8_t atr_protocol_num;
+    CCID_T0ProtocolDataStructure *t0 = &s->abProtocolDataStructure.t0;
+    CCID_T1ProtocolDataStructure *t1 = &s->abProtocolDataStructure.t1;
 
     if (s->card) {
         atr = ccid_card_get_atr(s->card, &len);
     }
+    atr_protocol_num = atr_get_protocol_num(atr, len);
+    DPRINTF(s, D_VERBOSE, "%s: atr contains protocol=%d\n", __func__,
+            atr_protocol_num);
+    /* set parameters from ATR - see spec page 109 */
+    s->bProtocolNum = (atr_protocol_num <= 1 ? atr_protocol_num
+                                             : s->bProtocolNum);
+    switch (atr_protocol_num) {
+    case 0:
+        /* TODO: unimplemented ATR T0 parameters */
+        t0->bmFindexDindex = 0;
+        t0->bmTCCKST0 = 0;
+        t0->bGuardTimeT0 = 0;
+        t0->bWaitingIntegerT0 = 0;
+        t0->bClockStop = 0;
+        break;
+    case 1:
+        /* TODO: unimplemented ATR T1 parameters */
+        t1->bmFindexDindex = 0;
+        t1->bmTCCKST1 = 0;
+        t1->bGuardTimeT1 = 0;
+        t1->bWaitingIntegerT1 = 0;
+        t1->bClockStop = 0;
+        t1->bIFSC = 0;
+        t1->bNadValue = 0;
+        break;
+    default:
+        DPRINTF(s, D_WARN, "%s: error: unsupported ATR protocol %d\n",
+                __func__, atr_protocol_num);
+    }
     ccid_write_data_block(s, recv->bSlot, recv->bSeq, atr, len);
 }
 
commit d7d218ef02d87c637d20d64da8f575d434ff6f78
Author: Alon Levy <alevy at redhat.com>
Date:   Wed Mar 27 10:14:15 2013 +0200

    dev-smartcard-reader: change default protocol to T=0
    
    We don't support T=1 so we shouldn't advertise it by default.
    
    Two independent changes:
    * Default ATR
     sets T=0. This gets overwritten by the client provided ATR later.
    * Class descriptor
     changes dwAdvertise dwProtocols.PPPP to 0x1 and dwProtocols.RRRR=0 per spec.
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Reviewed-by: Marc-André Lureau <mlureau at redhat.com>

diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index 0d482a9..8022f9f 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -335,8 +335,8 @@ static const uint8_t qemu_ccid_descriptor[] = {
                      */
         0x07,       /* u8  bVoltageSupport; 01h - 5.0v, 02h - 3.0, 03 - 1.8 */
 
-        0x03, 0x00, /* u32 dwProtocols; RRRR PPPP. RRRR = 0000h.*/
-        0x00, 0x00, /* PPPP: 0001h = Protocol T=0, 0002h = Protocol T=1 */
+        0x00, 0x00, /* u32 dwProtocols; RRRR PPPP. RRRR = 0000h.*/
+        0x01, 0x00, /* PPPP: 0001h = Protocol T=0, 0002h = Protocol T=1 */
                     /* u32 dwDefaultClock; in kHZ (0x0fa0 is 4 MHz) */
         0xa0, 0x0f, 0x00, 0x00,
                     /* u32 dwMaximumClock; */
@@ -875,7 +875,7 @@ static const CCID_ProtocolDataStructure defaultProtocolDataStructure = {
 
 static void ccid_reset_parameters(USBCCIDState *s)
 {
-   s->bProtocolNum = 1; /* T=1 */
+   s->bProtocolNum = 0; /* T=0 */
    s->abProtocolDataStructure = defaultProtocolDataStructure;
 }
 
commit 4942d6c39477f441a106430ab11f85806b4532f5
Author: Alon Levy <alevy at redhat.com>
Date:   Mon Mar 4 18:57:45 2013 +0200

    dev-smartcard-reader: define structs for CCID_Parameter internals
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Reviewed-by: Marc-André Lureau <mlureau at redhat.com>

diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index 35f234e..0d482a9 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -189,10 +189,34 @@ typedef struct QEMU_PACKED CCID_SlotStatus {
     uint8_t     bClockStatus;
 } CCID_SlotStatus;
 
+typedef struct QEMU_PACKED CCID_T0ProtocolDataStructure {
+    uint8_t     bmFindexDindex;
+    uint8_t     bmTCCKST0;
+    uint8_t     bGuardTimeT0;
+    uint8_t     bWaitingIntegerT0;
+    uint8_t     bClockStop;
+} CCID_T0ProtocolDataStructure;
+
+typedef struct QEMU_PACKED CCID_T1ProtocolDataStructure {
+    uint8_t     bmFindexDindex;
+    uint8_t     bmTCCKST1;
+    uint8_t     bGuardTimeT1;
+    uint8_t     bWaitingIntegerT1;
+    uint8_t     bClockStop;
+    uint8_t     bIFSC;
+    uint8_t     bNadValue;
+} CCID_T1ProtocolDataStructure;
+
+typedef union CCID_ProtocolDataStructure {
+    CCID_T0ProtocolDataStructure t0;
+    CCID_T1ProtocolDataStructure t1;
+    uint8_t data[7]; /* must be = max(sizeof(t0), sizeof(t1)) */
+} CCID_ProtocolDataStructure;
+
 typedef struct QEMU_PACKED CCID_Parameter {
     CCID_BULK_IN b;
     uint8_t     bProtocolNum;
-    uint8_t     abProtocolDataStructure[0];
+    CCID_ProtocolDataStructure abProtocolDataStructure;
 } CCID_Parameter;
 
 typedef struct QEMU_PACKED CCID_DataBlock {
@@ -224,7 +248,7 @@ typedef struct QEMU_PACKED CCID_SetParameters {
     CCID_Header hdr;
     uint8_t     bProtocolNum;
     uint16_t   abRFU;
-    uint8_t    abProtocolDataStructure[0];
+    CCID_ProtocolDataStructure abProtocolDataStructure;
 } CCID_SetParameters;
 
 typedef struct CCID_Notify_Slot_Change {
@@ -254,8 +278,6 @@ typedef struct CCIDBus {
     BusState qbus;
 } CCIDBus;
 
-#define MAX_PROTOCOL_SIZE   7
-
 /*
  * powered - defaults to true, changed by PowerOn/PowerOff messages
  */
@@ -279,7 +301,7 @@ typedef struct USBCCIDState {
     uint8_t  bError;
     uint8_t  bmCommandStatus;
     uint8_t  bProtocolNum;
-    uint8_t  abProtocolDataStructure[MAX_PROTOCOL_SIZE];
+    CCID_ProtocolDataStructure abProtocolDataStructure;
     uint32_t ulProtocolDataStructureSize;
     uint32_t state_vmstate;
     uint32_t migration_target_ip;
@@ -765,7 +787,7 @@ static void ccid_write_parameters(USBCCIDState *s, CCID_Header *recv)
     h->b.bStatus = ccid_calc_status(s);
     h->b.bError = s->bError;
     h->bProtocolNum = s->bProtocolNum;
-    memcpy(h->abProtocolDataStructure, s->abProtocolDataStructure, len);
+    h->abProtocolDataStructure = s->abProtocolDataStructure;
     ccid_reset_error_status(s);
 }
 
@@ -825,38 +847,36 @@ static void ccid_write_data_block_atr(USBCCIDState *s, CCID_Header *recv)
 static void ccid_set_parameters(USBCCIDState *s, CCID_Header *recv)
 {
     CCID_SetParameters *ph = (CCID_SetParameters *) recv;
-    uint32_t len = 0;
-    if ((ph->bProtocolNum & 3) == 0) {
-        len = 5;
-    }
-    if ((ph->bProtocolNum & 3) == 1) {
-        len = 7;
-    }
-    if (len == 0) {
-        s->bmCommandStatus = COMMAND_STATUS_FAILED;
-        s->bError = 7; /* Protocol invalid or not supported */
+    uint32_t protocol_num = ph->bProtocolNum & 3;
+
+    if (protocol_num != 0 && protocol_num != 1) {
+        ccid_report_error_failed(s, ERROR_CMD_NOT_SUPPORTED);
         return;
     }
-    s->bProtocolNum = ph->bProtocolNum;
-    memcpy(s->abProtocolDataStructure, ph->abProtocolDataStructure, len);
-    s->ulProtocolDataStructureSize = len;
-    DPRINTF(s, 1, "%s: using len %d\n", __func__, len);
+    s->bProtocolNum = protocol_num;
+    s->abProtocolDataStructure = ph->abProtocolDataStructure;
 }
 
 /*
  * must be 5 bytes for T=0, 7 bytes for T=1
  * See page 52
  */
-static const uint8_t abDefaultProtocolDataStructure[7] = {
-    0x77, 0x00, 0x00, 0x00, 0x00, 0xfe /*IFSC*/, 0x00 /*NAD*/ };
+static const CCID_ProtocolDataStructure defaultProtocolDataStructure = {
+    .t1 = {
+        .bmFindexDindex = 0x77,
+        .bmTCCKST1 = 0x00,
+        .bGuardTimeT1 = 0x00,
+        .bWaitingIntegerT1 = 0x00,
+        .bClockStop = 0x00,
+        .bIFSC = 0xfe,
+        .bNadValue = 0x00,
+    }
+};
 
 static void ccid_reset_parameters(USBCCIDState *s)
 {
-   uint32_t len = sizeof(abDefaultProtocolDataStructure);
-
    s->bProtocolNum = 1; /* T=1 */
-   s->ulProtocolDataStructureSize = len;
-   memcpy(s->abProtocolDataStructure, abDefaultProtocolDataStructure, len);
+   s->abProtocolDataStructure = defaultProtocolDataStructure;
 }
 
 /* NOTE: only a single slot is supported (SLOT_0) */
@@ -1345,7 +1365,7 @@ static VMStateDescription ccid_vmstate = {
         VMSTATE_UINT8(bError, USBCCIDState),
         VMSTATE_UINT8(bmCommandStatus, USBCCIDState),
         VMSTATE_UINT8(bProtocolNum, USBCCIDState),
-        VMSTATE_BUFFER(abProtocolDataStructure, USBCCIDState),
+        VMSTATE_BUFFER(abProtocolDataStructure.data, USBCCIDState),
         VMSTATE_UINT32(ulProtocolDataStructureSize, USBCCIDState),
         VMSTATE_STRUCT_ARRAY(bulk_in_pending, USBCCIDState,
                        BULK_IN_PENDING_NUM, 1, bulk_in_vmstate, BulkIn),
commit b16352acf3105000e14f194b556e159d5d06cff9
Author: Alon Levy <alevy at redhat.com>
Date:   Mon Mar 4 18:41:28 2013 +0200

    ccid-card-passthru, dev-smartcard-reader: add debug environment variables
    
    Introduces a new utility function: parse_debug_env to avoid code
    duplication.
    
    This overrides whatever debug value is set on the corresponding devices
    from the command line, and is meant to ease the usage with any
    management stack. For libvirt you can set environment variables by
    extending the dom namespace, i.e:
    
    <domain type='kvm' id='3' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
      <qemu:commandline>
        <qemu:env name='QEMU_CCID_PASSTHRU_DEBUG' value='4'/>
        <qemu:env name='QEMU_CCID_DEBUG' value='4'/>
      </qemu:commandline>
    </domain>
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Reviewed-by: Marc-André Lureau <mlureau at redhat.com>

diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
index 16d51c9..01c7e6f 100644
--- a/hw/usb/ccid-card-passthru.c
+++ b/hw/usb/ccid-card-passthru.c
@@ -350,6 +350,8 @@ static int passthru_initfn(CCIDCardState *base)
         error_report("missing chardev");
         return -1;
     }
+    card->debug = parse_debug_env("QEMU_CCID_PASSTHRU_DEBUG", D_VERBOSE,
+                                  card->debug);
     assert(sizeof(DEFAULT_ATR) <= MAX_ATR_SIZE);
     memcpy(card->atr, DEFAULT_ATR, sizeof(DEFAULT_ATR));
     card->atr_length = sizeof(DEFAULT_ATR);
diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index 98f3be1..35f234e 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -1260,6 +1260,7 @@ static int ccid_initfn(USBDevice *dev)
     s->bulk_out_pos = 0;
     ccid_reset_parameters(s);
     ccid_reset(s);
+    s->debug = parse_debug_env("QEMU_CCID_DEBUG", D_VERBOSE, s->debug);
     return 0;
 }
 
diff --git a/include/qemu-common.h b/include/qemu-common.h
index 3b1873e..a39cdba 100644
--- a/include/qemu-common.h
+++ b/include/qemu-common.h
@@ -482,4 +482,9 @@ can_use_buffer_find_nonzero_offset(const void *buf, size_t len)
 }
 size_t buffer_find_nonzero_offset(const void *buf, size_t len);
 
+/*
+ * helper to parse debug environment variables
+ */
+int parse_debug_env(const char *name, int max, int initial);
+
 #endif
diff --git a/util/cutils.c b/util/cutils.c
index 5024253..a165819 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -482,3 +482,26 @@ int uleb128_decode_small(const uint8_t *in, uint32_t *n)
         return 2;
     }
 }
+
+/*
+ * helper to parse debug environment variables
+ */
+int parse_debug_env(const char *name, int max, int initial)
+{
+    char *debug_env = getenv(name);
+    char *inv = NULL;
+    int debug;
+
+    if (!debug_env) {
+        return initial;
+    }
+    debug = strtol(debug_env, &inv, 10);
+    if (inv == debug_env) {
+        return initial;
+    }
+    if (debug < 0 || debug > max) {
+        fprintf(stderr, "warning: %s not in [0, %d]", name, max);
+        return initial;
+    }
+    return debug;
+}
commit 0e61400c1941aabc9f45d5ff961b57337c7caac6
Author: Alon Levy <alevy at redhat.com>
Date:   Mon Mar 4 18:39:09 2013 +0200

    ccid-card-passthru: add atr check
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Reviewed-by: Marc-André Lureau <mlureau at redhat.com>

diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
index 275b887..16d51c9 100644
--- a/hw/usb/ccid-card-passthru.c
+++ b/hw/usb/ccid-card-passthru.c
@@ -138,6 +138,59 @@ static void ccid_card_vscard_handle_init(
     ccid_card_vscard_send_init(card);
 }
 
+static int check_atr(PassthruState *card, uint8_t *data, int len)
+{
+    int historical_length, opt_bytes;
+    int td_count = 0;
+    int td;
+
+    if (len < 2) {
+        return 0;
+    }
+    historical_length = data[1] & 0xf;
+    opt_bytes = 0;
+    if (data[0] != 0x3b && data[0] != 0x3f) {
+        DPRINTF(card, D_WARN, "atr's T0 is 0x%X, not in {0x3b, 0x3f}\n",
+                data[0]);
+        return 0;
+    }
+    td_count = 0;
+    td = data[1] >> 4;
+    while (td && td_count < 2 && opt_bytes + historical_length + 2 < len) {
+        td_count++;
+        if (td & 0x1) {
+            opt_bytes++;
+        }
+        if (td & 0x2) {
+            opt_bytes++;
+        }
+        if (td & 0x4) {
+            opt_bytes++;
+        }
+        if (td & 0x8) {
+            opt_bytes++;
+            td = data[opt_bytes + 2] >> 4;
+        }
+    }
+    if (len < 2 + historical_length + opt_bytes) {
+        DPRINTF(card, D_WARN,
+            "atr too short: len %d, but historical_len %d, T1 0x%X\n",
+            len, historical_length, data[1]);
+        return 0;
+    }
+    if (len > 2 + historical_length + opt_bytes) {
+        DPRINTF(card, D_WARN,
+            "atr too long: len %d, but hist/opt %d/%d, T1 0x%X\n",
+            len, historical_length, opt_bytes, data[1]);
+        /* let it through */
+    }
+    DPRINTF(card, D_VERBOSE,
+            "atr passes check: %d total length, %d historical, %d optional\n",
+            len, historical_length, opt_bytes);
+
+    return 1;
+}
+
 static void ccid_card_vscard_handle_message(PassthruState *card,
     VSCMsgHeader *scr_msg_header)
 {
@@ -152,6 +205,12 @@ static void ccid_card_vscard_handle_message(PassthruState *card,
                                         VSC_GENERAL_ERROR);
             break;
         }
+        if (!check_atr(card, data, scr_msg_header->length)) {
+            error_report("ATR is inconsistent, ignoring");
+            ccid_card_vscard_send_error(card, scr_msg_header->reader_id,
+                                        VSC_GENERAL_ERROR);
+            break;
+        }
         memcpy(card->atr, data, scr_msg_header->length);
         card->atr_length = scr_msg_header->length;
         ccid_card_card_inserted(&card->base);
commit a26dfd95d33d650f9f9f93b6ee6f03be925db1a8
Author: Alon Levy <alevy at redhat.com>
Date:   Tue Mar 5 15:35:24 2013 +0200

    libcacard: change default ATR
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Reviewed-by: Marc-André Lureau <mlureau at redhat.com>

diff --git a/libcacard/vcardt.h b/libcacard/vcardt.h
index 538bdde..3b9a619 100644
--- a/libcacard/vcardt.h
+++ b/libcacard/vcardt.h
@@ -26,9 +26,17 @@ typedef struct VCardEmulStruct VCardEmul;
 #define MAX_CHANNEL 4
 
 /* create an ATR with appropriate historical bytes */
-#define VCARD_ATR_PREFIX(size) 0x3b, 0x66+(size), 0x00, 0xff, \
-                               'V', 'C', 'A', 'R', 'D', '_'
+#define TS_DIRECT_CONVENTION 0x3b
+#define TA_PRESENT 0x10
+#define TB_PRESENT 0x20
+#define TC_PRESENT 0x40
+#define TD_PRESENT 0x80
 
+#define VCARD_ATR_PREFIX(size) \
+    TS_DIRECT_CONVENTION, \
+    TD_PRESENT + (6 + size), \
+    0x00, \
+    'V', 'C', 'A', 'R', 'D', '_'
 
 typedef enum {
     VCARD_DONE,
commit 693e47738d05463b2743b0a652412d33cf254977
Author: Alon Levy <alevy at redhat.com>
Date:   Tue Mar 5 15:31:26 2013 +0200

    dev-smartcard-reader: reuse usb.h definitions
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Reviewed-by: Marc-André Lureau <mlureau at redhat.com>

diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index 38c3c0e..98f3be1 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -68,12 +68,6 @@ do { \
 #define BULK_IN_BUF_SIZE 384
 #define BULK_IN_PENDING_NUM 8
 
-#define InterfaceOutClass \
-    ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE)<<8)
-
-#define InterfaceInClass  \
-    ((USB_DIR_IN  | USB_TYPE_CLASS | USB_RECIP_INTERFACE)<<8)
-
 #define CCID_MAX_PACKET_SIZE                64
 
 #define CCID_CONTROL_ABORT                  0x1
@@ -410,8 +404,8 @@ static const USBDescStrings desc_strings = {
 static const USBDescIface desc_iface0 = {
     .bInterfaceNumber              = 0,
     .bNumEndpoints                 = 3,
-    .bInterfaceClass               = 0x0b,
-    .bInterfaceSubClass            = 0x00,
+    .bInterfaceClass               = USB_CLASS_CSCID,
+    .bInterfaceSubClass            = USB_SUBCLASS_UNDEFINED,
     .bInterfaceProtocol            = 0x00,
     .iInterface                    = STR_INTERFACE,
     .ndesc                         = 1,
@@ -687,15 +681,15 @@ static void ccid_handle_control(USBDevice *dev, USBPacket *p, int request,
 
     switch (request) {
         /* Class specific requests.  */
-    case InterfaceOutClass | CCID_CONTROL_ABORT:
+    case ClassInterfaceOutRequest | CCID_CONTROL_ABORT:
         DPRINTF(s, 1, "ccid_control abort UNIMPLEMENTED\n");
         p->status = USB_RET_STALL;
         break;
-    case InterfaceInClass | CCID_CONTROL_GET_CLOCK_FREQUENCIES:
+    case ClassInterfaceRequest | CCID_CONTROL_GET_CLOCK_FREQUENCIES:
         DPRINTF(s, 1, "ccid_control get clock frequencies UNIMPLEMENTED\n");
         p->status = USB_RET_STALL;
         break;
-    case InterfaceInClass | CCID_CONTROL_GET_DATA_RATES:
+    case ClassInterfaceRequest | CCID_CONTROL_GET_DATA_RATES:
         DPRINTF(s, 1, "ccid_control get data rates UNIMPLEMENTED\n");
         p->status = USB_RET_STALL;
         break;
commit c5cd7c875608911ec74817d24cd12b825014ba19
Author: Alon Levy <alevy at redhat.com>
Date:   Mon Mar 4 21:40:53 2013 +0200

    dev-smartcard-reader: support windows guest
    
    By not advertising USB wakeup support (which we don't).
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Reviewed-by: Marc-André Lureau <mlureau at redhat.com>

diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index 6133edf..38c3c0e 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -359,11 +359,11 @@ static const uint8_t qemu_ccid_descriptor[] = {
                      * 20000 Short APDU level exchange with CCID
                      * 40000 Short and Extended APDU level exchange with CCID
                      *
-                     * + 100000 USB Wake up signaling supported on card
+                     * 100000 USB Wake up signaling supported on card
                      * insertion and removal. Must set bit 5 in bmAttributes
                      * in Configuration descriptor if 100000 is set.
                      */
-        0xfe, 0x04, 0x11, 0x00,
+        0xfe, 0x04, 0x01, 0x00,
                     /*
                      * u32 dwMaxCCIDMessageLength; For extended APDU in
                      * [261 + 10 , 65544 + 10]. Otherwise the minimum is
commit 47bf53af7507986fc473cb308324340448fd85e7
Author: Alon Levy <alevy at redhat.com>
Date:   Mon Mar 4 18:55:07 2013 +0200

    dev-smartcard-reader: remove aborts (never triggered, but just in case)
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Reviewed-by: Marc-André Lureau <mlureau at redhat.com>

diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index 6653619..6133edf 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -796,6 +796,12 @@ static void ccid_write_data_block(USBCCIDState *s, uint8_t slot, uint8_t seq,
     ccid_reset_error_status(s);
 }
 
+static void ccid_report_error_failed(USBCCIDState *s, uint8_t error)
+{
+    s->bmCommandStatus = COMMAND_STATUS_FAILED;
+    s->bError = error;
+}
+
 static void ccid_write_data_block_answer(USBCCIDState *s,
     const uint8_t *data, uint32_t len)
 {
@@ -803,7 +809,9 @@ static void ccid_write_data_block_answer(USBCCIDState *s,
     uint8_t slot;
 
     if (!ccid_has_pending_answers(s)) {
-        abort();
+        DPRINTF(s, D_WARN, "error: no pending answer to return to guest\n");
+        ccid_report_error_failed(s, ERROR_ICC_MUTE);
+        return;
     }
     ccid_remove_pending_answer(s, &slot, &seq);
     ccid_write_data_block(s, slot, seq, data, len);
@@ -857,12 +865,6 @@ static void ccid_reset_parameters(USBCCIDState *s)
    memcpy(s->abProtocolDataStructure, abDefaultProtocolDataStructure, len);
 }
 
-static void ccid_report_error_failed(USBCCIDState *s, uint8_t error)
-{
-    s->bmCommandStatus = COMMAND_STATUS_FAILED;
-    s->bError = error;
-}
-
 /* NOTE: only a single slot is supported (SLOT_0) */
 static void ccid_on_slot_change(USBCCIDState *s, bool full)
 {
@@ -1129,7 +1131,9 @@ void ccid_card_send_apdu_to_guest(CCIDCardState *card,
     s->bmCommandStatus = COMMAND_STATUS_NO_ERROR;
     answer = ccid_peek_next_answer(s);
     if (answer == NULL) {
-        abort();
+        DPRINTF(s, D_WARN, "%s: error: unexpected lack of answer\n", __func__);
+        ccid_report_error_failed(s, ERROR_HW_ERROR);
+        return;
     }
     DPRINTF(s, 1, "APDU returned to guest %d (answer seq %d, slot %d)\n",
         len, answer->seq, answer->slot);
commit 7e1ac5abe3fbbfee4ddfc2d9971a644bd787e055
Author: Alon Levy <alevy at redhat.com>
Date:   Mon Mar 4 18:50:33 2013 +0200

    dev-smartcard-reader: nicer debug messages
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Reviewed-by: Marc-André Lureau <mlureau at redhat.com>

diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index 57eb803..6653619 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -639,13 +639,47 @@ static void ccid_handle_reset(USBDevice *dev)
     ccid_reset(s);
 }
 
+static const char *ccid_control_to_str(USBCCIDState *s, int request)
+{
+    switch (request) {
+        /* generic - should be factored out if there are other debugees */
+    case DeviceOutRequest | USB_REQ_SET_ADDRESS:
+        return "(generic) set address";
+    case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
+        return "(generic) get descriptor";
+    case DeviceRequest | USB_REQ_GET_CONFIGURATION:
+        return "(generic) get configuration";
+    case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
+        return "(generic) set configuration";
+    case DeviceRequest | USB_REQ_GET_STATUS:
+        return "(generic) get status";
+    case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
+        return "(generic) clear feature";
+    case DeviceOutRequest | USB_REQ_SET_FEATURE:
+        return "(generic) set_feature";
+    case InterfaceRequest | USB_REQ_GET_INTERFACE:
+        return "(generic) get interface";
+    case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
+        return "(generic) set interface";
+        /* class requests */
+    case ClassInterfaceOutRequest | CCID_CONTROL_ABORT:
+        return "ABORT";
+    case ClassInterfaceRequest | CCID_CONTROL_GET_CLOCK_FREQUENCIES:
+        return "GET_CLOCK_FREQUENCIES";
+    case ClassInterfaceRequest | CCID_CONTROL_GET_DATA_RATES:
+        return "GET_DATA_RATES";
+    }
+    return "unknown";
+}
+
 static void ccid_handle_control(USBDevice *dev, USBPacket *p, int request,
                                int value, int index, int length, uint8_t *data)
 {
     USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
     int ret;
 
-    DPRINTF(s, 1, "got control %x, value %x\n", request, value);
+    DPRINTF(s, 1, "%s: got control %s (%x), value %x\n", __func__,
+            ccid_control_to_str(s, request), request, value);
     ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
     if (ret >= 0) {
         return;
@@ -695,7 +729,7 @@ static uint8_t ccid_calc_status(USBCCIDState *s)
      * bmCommandStatus
      */
     uint8_t ret = ccid_card_status(s) | (s->bmCommandStatus << 6);
-    DPRINTF(s, D_VERBOSE, "status = %d\n", ret);
+    DPRINTF(s, D_VERBOSE, "%s: status = %d\n", __func__, ret);
     return ret;
 }
 
@@ -756,7 +790,7 @@ static void ccid_write_data_block(USBCCIDState *s, uint8_t slot, uint8_t seq,
     p->b.bStatus = ccid_calc_status(s);
     p->b.bError = s->bError;
     if (p->b.bError) {
-        DPRINTF(s, D_VERBOSE, "error %d", p->b.bError);
+        DPRINTF(s, D_VERBOSE, "error %d\n", p->b.bError);
     }
     memcpy(p->abData, data, len);
     ccid_reset_error_status(s);
@@ -873,6 +907,28 @@ static void ccid_on_apdu_from_guest(USBCCIDState *s, CCID_XferBlock *recv)
     }
 }
 
+static const char *ccid_message_type_to_str(uint8_t type)
+{
+    switch (type) {
+    case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOn: return "IccPowerOn";
+    case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOff: return "IccPowerOff";
+    case CCID_MESSAGE_TYPE_PC_to_RDR_GetSlotStatus: return "GetSlotStatus";
+    case CCID_MESSAGE_TYPE_PC_to_RDR_XfrBlock: return "XfrBlock";
+    case CCID_MESSAGE_TYPE_PC_to_RDR_GetParameters: return "GetParameters";
+    case CCID_MESSAGE_TYPE_PC_to_RDR_ResetParameters: return "ResetParameters";
+    case CCID_MESSAGE_TYPE_PC_to_RDR_SetParameters: return "SetParameters";
+    case CCID_MESSAGE_TYPE_PC_to_RDR_Escape: return "Escape";
+    case CCID_MESSAGE_TYPE_PC_to_RDR_IccClock: return "IccClock";
+    case CCID_MESSAGE_TYPE_PC_to_RDR_T0APDU: return "T0APDU";
+    case CCID_MESSAGE_TYPE_PC_to_RDR_Secure: return "Secure";
+    case CCID_MESSAGE_TYPE_PC_to_RDR_Mechanical: return "Mechanical";
+    case CCID_MESSAGE_TYPE_PC_to_RDR_Abort: return "Abort";
+    case CCID_MESSAGE_TYPE_PC_to_RDR_SetDataRateAndClockFrequency:
+        return "SetDataRateAndClockFrequency";
+    }
+    return "unknown";
+}
+
 static void ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
 {
     CCID_Header *ccid_header;
@@ -895,13 +951,15 @@ static void ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
                 "%s: bad USB_TOKEN_OUT length, should be at least 10 bytes\n",
                 __func__);
     } else {
-        DPRINTF(s, D_MORE_INFO, "%s %x\n", __func__, ccid_header->bMessageType);
+        DPRINTF(s, D_MORE_INFO, "%s %x %s\n", __func__,
+                ccid_header->bMessageType,
+                ccid_message_type_to_str(ccid_header->bMessageType));
         switch (ccid_header->bMessageType) {
         case CCID_MESSAGE_TYPE_PC_to_RDR_GetSlotStatus:
             ccid_write_slot_status(s, ccid_header);
             break;
         case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOn:
-            DPRINTF(s, 1, "PowerOn: %d\n",
+            DPRINTF(s, 1, "%s: PowerOn: %d\n", __func__,
                 ((CCID_IccPowerOn *)(ccid_header))->bPowerSelect);
             s->powered = true;
             if (!ccid_card_inserted(s)) {
@@ -911,7 +969,6 @@ static void ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
             ccid_write_data_block_atr(s, ccid_header);
             break;
         case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOff:
-            DPRINTF(s, 1, "PowerOff\n");
             ccid_reset_error_status(s);
             s->powered = false;
             ccid_write_slot_status(s, ccid_header);
commit 4543d43c6181d90f86fb528430f250810dde03d5
Author: Alon Levy <alevy at redhat.com>
Date:   Mon Mar 4 18:45:49 2013 +0200

    dev-smartcard-reader: white space fixes
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Reviewed-by: Marc-André Lureau <mlureau at redhat.com>

diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index db8ce02..57eb803 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -471,6 +471,7 @@ static const USBDesc desc_ccid = {
 static const uint8_t *ccid_card_get_atr(CCIDCardState *card, uint32_t *len)
 {
     CCIDCardClass *cc = CCID_CARD_GET_CLASS(card);
+
     if (cc->get_atr) {
         return cc->get_atr(card, len);
     }
@@ -482,6 +483,7 @@ static void ccid_card_apdu_from_guest(CCIDCardState *card,
                                       uint32_t len)
 {
     CCIDCardClass *cc = CCID_CARD_GET_CLASS(card);
+
     if (cc->apdu_from_guest) {
         cc->apdu_from_guest(card, apdu, len);
     }
@@ -490,6 +492,7 @@ static void ccid_card_apdu_from_guest(CCIDCardState *card,
 static int ccid_card_exitfn(CCIDCardState *card)
 {
     CCIDCardClass *cc = CCID_CARD_GET_CLASS(card);
+
     if (cc->exitfn) {
         return cc->exitfn(card);
     }
@@ -499,6 +502,7 @@ static int ccid_card_exitfn(CCIDCardState *card)
 static int ccid_card_initfn(CCIDCardState *card)
 {
     CCIDCardClass *cc = CCID_CARD_GET_CLASS(card);
+
     if (cc->initfn) {
         return cc->initfn(card);
     }
commit ad2181f2b612cd8bf0a790faa2a1b51559f7234b
Author: Marc-André Lureau <mlureau at redhat.com>
Date:   Wed Mar 20 14:07:49 2013 +0100

    libcacard: remove default libcoolkey loading
    
    Use only the modules defined in the NSS database.
    
    Signed-off-by: Marc-André Lureau <mlureau at redhat.com>
    Reviewed-by: Alon Levy <alevy at redhat.com>

diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c
index 6b1ca8a..9ba80fb 100644
--- a/libcacard/vcard_emul_nss.c
+++ b/libcacard/vcard_emul_nss.c
@@ -870,7 +870,7 @@ VCardEmulError
 vcard_emul_init(const VCardEmulOptions *options)
 {
     SECStatus rv;
-    PRBool ret, has_readers = PR_FALSE, need_coolkey_module;
+    PRBool ret, has_readers = PR_FALSE;
     VReader *vreader;
     VReaderEmul *vreader_emul;
     SECMODListLock *module_lock;
@@ -983,30 +983,15 @@ vcard_emul_init(const VCardEmulOptions *options)
     /* make sure we have some PKCS #11 module loaded */
     module_lock = SECMOD_GetDefaultModuleListLock();
     module_list = SECMOD_GetDefaultModuleList();
-    need_coolkey_module = !has_readers;
     SECMOD_GetReadLock(module_lock);
     for (mlp = module_list; mlp; mlp = mlp->next) {
         SECMODModule *module = mlp->module;
         if (module_has_removable_hw_slots(module)) {
-            need_coolkey_module = PR_FALSE;
             break;
         }
     }
     SECMOD_ReleaseReadLock(module_lock);
 
-    if (need_coolkey_module) {
-        SECMODModule *module;
-        module = SECMOD_LoadUserModule(
-                    (char *)"library=libcoolkeypk11.so name=Coolkey",
-                    NULL, PR_FALSE);
-        if (module == NULL) {
-            return VCARD_EMUL_FAIL;
-        }
-        SECMOD_DestroyModule(module); /* free our reference, Module will still
-                                       * be on the list.
-                                       * until we destroy it */
-    }
-
     /* now examine all the slots, finding which should be readers */
     /* We should control this with options. For now we mirror out any
      * removable hardware slot */
commit 667e0b4b6806d53e0b46e29a15d24427ef958c78
Author: Marc-André Lureau <mlureau at redhat.com>
Date:   Wed Mar 20 14:07:48 2013 +0100

    libcacard: remove sql: prefix
    
    For some reason, with sql:/ prefix, the PKCS11 modules are not loaded.
    
    This patch goes on top of Alon smartcard series.
    
    Signed-off-by: Marc-André Lureau <mlureau at redhat.com>
    Reviewed-by: Alon Levy <alevy at redhat.com>

diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c
index 21d4689..6b1ca8a 100644
--- a/libcacard/vcard_emul_nss.c
+++ b/libcacard/vcard_emul_nss.c
@@ -893,7 +893,7 @@ vcard_emul_init(const VCardEmulOptions *options)
     if (options->nss_db) {
         rv = NSS_Init(options->nss_db);
     } else {
-        gchar *path, *db;
+        gchar *path;
 #ifndef _WIN32
         path = g_strdup("/etc/pki/nssdb");
 #else
@@ -905,10 +905,8 @@ vcard_emul_init(const VCardEmulOptions *options)
         path = g_build_filename(
             g_get_system_config_dirs()[0], "pki", "nssdb", NULL);
 #endif
-        db = g_strdup_printf("sql:%s", path);
 
-        rv = NSS_Init(db);
-        g_free(db);
+        rv = NSS_Init(path);
         g_free(path);
     }
     if (rv != SECSuccess) {
commit c9495ee9eb57786f5a60d4591bb186b23f6b6bef
Author: Marc-André Lureau <mlureau at redhat.com>
Date:   Mon Feb 25 23:31:16 2013 +0100

    libcacard: teach vscclient to use GMainLoop for portability
    
    This version handles non-blocking sending and receiving from the
    socket.
    
    Signed-off-by: Marc-André Lureau <mlureau at redhat.com>
    Reviewed-by: Alon Levy <alevy at redhat.com>

diff --git a/libcacard/vscclient.c b/libcacard/vscclient.c
index 5f47634..ac23647 100644
--- a/libcacard/vscclient.c
+++ b/libcacard/vscclient.c
@@ -10,7 +10,10 @@
  * See the COPYING.LIB file in the top-level directory.
  */
 
+#ifndef _WIN32
 #include <netdb.h>
+#endif
+#include <glib.h>
 
 #include "qemu-common.h"
 #include "qemu/thread.h"
@@ -22,9 +25,7 @@
 #include "vcard_emul.h"
 #include "vevent.h"
 
-int verbose;
-
-int sock;
+static int verbose;
 
 static void
 print_byte_array(
@@ -51,7 +52,47 @@ print_usage(void) {
     vcard_emul_usage();
 }
 
-static QemuMutex write_lock;
+static GIOChannel *channel_socket;
+static GByteArray *socket_to_send;
+static QemuMutex socket_to_send_lock;
+static guint socket_tag;
+
+static void
+update_socket_watch(gboolean out);
+
+static gboolean
+do_socket_send(GIOChannel *source,
+               GIOCondition condition,
+               gpointer data)
+{
+    gsize bw;
+    GError *err = NULL;
+
+    g_return_val_if_fail(socket_to_send->len != 0, FALSE);
+    g_return_val_if_fail(condition & G_IO_OUT, FALSE);
+
+    g_io_channel_write_chars(channel_socket,
+        (gchar *)socket_to_send->data, socket_to_send->len, &bw, &err);
+    if (err != NULL) {
+        g_error("Error while sending socket %s", err->message);
+        return FALSE;
+    }
+    g_byte_array_remove_range(socket_to_send, 0, bw);
+
+    if (socket_to_send->len == 0) {
+        update_socket_watch(FALSE);
+        return FALSE;
+    }
+    return TRUE;
+}
+
+static gboolean
+socket_prepare_sending(gpointer user_data)
+{
+    update_socket_watch(TRUE);
+
+    return FALSE;
+}
 
 static int
 send_msg(
@@ -60,10 +101,9 @@ send_msg(
     const void *msg,
     unsigned int length
 ) {
-    int rv;
     VSCMsgHeader mhHeader;
 
-    qemu_mutex_lock(&write_lock);
+    qemu_mutex_lock(&socket_to_send_lock);
 
     if (verbose > 10) {
         printf("sending type=%d id=%u, len =%u (0x%x)\n",
@@ -73,23 +113,11 @@ send_msg(
     mhHeader.type = htonl(type);
     mhHeader.reader_id = 0;
     mhHeader.length = htonl(length);
-    rv = write(sock, &mhHeader, sizeof(mhHeader));
-    if (rv < 0) {
-        /* Error */
-        fprintf(stderr, "write header error\n");
-        close(sock);
-        qemu_mutex_unlock(&write_lock);
-        return 16;
-    }
-    rv = write(sock, msg, length);
-    if (rv < 0) {
-        /* Error */
-        fprintf(stderr, "write error\n");
-        close(sock);
-        qemu_mutex_unlock(&write_lock);
-        return 16;
-    }
-    qemu_mutex_unlock(&write_lock);
+    g_byte_array_append(socket_to_send, (guint8 *)&mhHeader, sizeof(mhHeader));
+    g_byte_array_append(socket_to_send, (guint8 *)msg, length);
+    g_idle_add(socket_prepare_sending, NULL);
+
+    qemu_mutex_unlock(&socket_to_send_lock);
 
     return 0;
 }
@@ -245,139 +273,203 @@ on_host_init(VSCMsgHeader *mhHeader, VSCMsgInit *incoming)
     return 0;
 }
 
+
+enum {
+    STATE_HEADER,
+    STATE_MESSAGE,
+};
+
 #define APDUBufSize 270
 
-static int
-do_socket_read(void)
+static gboolean
+do_socket_read(GIOChannel *source,
+               GIOCondition condition,
+               gpointer data)
 {
     int rv;
     int dwSendLength;
     int dwRecvLength;
     uint8_t pbRecvBuffer[APDUBufSize];
-    uint8_t pbSendBuffer[APDUBufSize];
+    static uint8_t pbSendBuffer[APDUBufSize];
     VReaderStatus reader_status;
     VReader *reader = NULL;
-    VSCMsgHeader mhHeader;
+    static VSCMsgHeader mhHeader;
     VSCMsgError *error_msg;
+    GError *err = NULL;
 
-    rv = read(sock, &mhHeader, sizeof(mhHeader));
-    if (rv < sizeof(mhHeader)) {
-        /* Error */
-        if (rv < 0) {
-            perror("header read error\n");
-        } else {
-            fprintf(stderr, "header short read %d\n", rv);
-        }
-        return -1;
-    }
-    mhHeader.type = ntohl(mhHeader.type);
-    mhHeader.reader_id = ntohl(mhHeader.reader_id);
-    mhHeader.length = ntohl(mhHeader.length);
-    if (verbose) {
-        printf("Header: type=%d, reader_id=%u length=%d (0x%x)\n",
-               mhHeader.type, mhHeader.reader_id, mhHeader.length,
-               mhHeader.length);
-    }
-    switch (mhHeader.type) {
-    case VSC_APDU:
-    case VSC_Flush:
-    case VSC_Error:
-    case VSC_Init:
-        rv = read(sock, pbSendBuffer, mhHeader.length);
-        break;
-    default:
-        fprintf(stderr, "Unexpected message of type 0x%X\n", mhHeader.type);
-        return -1;
+    static gchar *buf;
+    static gsize br, to_read;
+    static int state = STATE_HEADER;
+
+    if (state == STATE_HEADER && to_read == 0) {
+        buf = (gchar *)&mhHeader;
+        to_read = sizeof(mhHeader);
     }
-    switch (mhHeader.type) {
-    case VSC_APDU:
-        if (rv < 0) {
-            /* Error */
-            fprintf(stderr, "read error\n");
-            close(sock);
-            return -1;
+
+    if (to_read > 0) {
+        g_io_channel_read_chars(source, (gchar *)buf, to_read, &br, &err);
+        if (err != NULL) {
+            g_error("error while reading: %s", err->message);
         }
+        buf += br;
+        to_read -= br;
+        if (to_read != 0) {
+            return TRUE;
+        }
+    }
+
+    if (state == STATE_HEADER) {
+        mhHeader.type = ntohl(mhHeader.type);
+        mhHeader.reader_id = ntohl(mhHeader.reader_id);
+        mhHeader.length = ntohl(mhHeader.length);
         if (verbose) {
-            printf(" recv APDU: ");
-            print_byte_array(pbSendBuffer, mhHeader.length);
+            printf("Header: type=%d, reader_id=%u length=%d (0x%x)\n",
+                   mhHeader.type, mhHeader.reader_id, mhHeader.length,
+                   mhHeader.length);
         }
-        /* Transmit received APDU */
-        dwSendLength = mhHeader.length;
-        dwRecvLength = sizeof(pbRecvBuffer);
-        reader = vreader_get_reader_by_id(mhHeader.reader_id);
-        reader_status = vreader_xfr_bytes(reader,
-                                          pbSendBuffer, dwSendLength,
-                                          pbRecvBuffer, &dwRecvLength);
-        if (reader_status == VREADER_OK) {
-            mhHeader.length = dwRecvLength;
+        switch (mhHeader.type) {
+        case VSC_APDU:
+        case VSC_Flush:
+        case VSC_Error:
+        case VSC_Init:
+            buf = (gchar *)pbSendBuffer;
+            to_read = mhHeader.length;
+            state = STATE_MESSAGE;
+            return TRUE;
+        default:
+            fprintf(stderr, "Unexpected message of type 0x%X\n", mhHeader.type);
+            return FALSE;
+        }
+    }
+
+    if (state == STATE_MESSAGE) {
+        switch (mhHeader.type) {
+        case VSC_APDU:
             if (verbose) {
-                printf(" send response: ");
-                print_byte_array(pbRecvBuffer, mhHeader.length);
+                printf(" recv APDU: ");
+                print_byte_array(pbSendBuffer, mhHeader.length);
             }
-            send_msg(VSC_APDU, mhHeader.reader_id,
-                     pbRecvBuffer, dwRecvLength);
-        } else {
-            rv = reader_status; /* warning: not meaningful */
-            send_msg(VSC_Error, mhHeader.reader_id, &rv, sizeof(uint32_t));
-        }
-        vreader_free(reader);
-        reader = NULL; /* we've freed it, don't use it by accident
-                          again */
-        break;
-    case VSC_Flush:
-        /* TODO: actually flush */
-        send_msg(VSC_FlushComplete, mhHeader.reader_id, NULL, 0);
-        break;
-    case VSC_Error:
-        error_msg = (VSCMsgError *) pbSendBuffer;
-        if (error_msg->code == VSC_SUCCESS) {
-            qemu_mutex_lock(&pending_reader_lock);
-            if (pending_reader) {
-                vreader_set_id(pending_reader, mhHeader.reader_id);
-                vreader_free(pending_reader);
-                pending_reader = NULL;
-                qemu_cond_signal(&pending_reader_condition);
+            /* Transmit received APDU */
+            dwSendLength = mhHeader.length;
+            dwRecvLength = sizeof(pbRecvBuffer);
+            reader = vreader_get_reader_by_id(mhHeader.reader_id);
+            reader_status = vreader_xfr_bytes(reader,
+                                              pbSendBuffer, dwSendLength,
+                                              pbRecvBuffer, &dwRecvLength);
+            if (reader_status == VREADER_OK) {
+                mhHeader.length = dwRecvLength;
+                if (verbose) {
+                    printf(" send response: ");
+                    print_byte_array(pbRecvBuffer, mhHeader.length);
+                }
+                send_msg(VSC_APDU, mhHeader.reader_id,
+                         pbRecvBuffer, dwRecvLength);
+            } else {
+                rv = reader_status; /* warning: not meaningful */
+                send_msg(VSC_Error, mhHeader.reader_id, &rv, sizeof(uint32_t));
             }
-            qemu_mutex_unlock(&pending_reader_lock);
+            vreader_free(reader);
+            reader = NULL; /* we've freed it, don't use it by accident
+                              again */
             break;
-        }
-        printf("warning: qemu refused to add reader\n");
-        if (error_msg->code == VSC_CANNOT_ADD_MORE_READERS) {
-            /* clear pending reader, qemu can't handle any more */
-            qemu_mutex_lock(&pending_reader_lock);
-            if (pending_reader) {
-                pending_reader = NULL;
-                /* make sure the event loop doesn't hang */
-                qemu_cond_signal(&pending_reader_condition);
+        case VSC_Flush:
+            /* TODO: actually flush */
+            send_msg(VSC_FlushComplete, mhHeader.reader_id, NULL, 0);
+            break;
+        case VSC_Error:
+            error_msg = (VSCMsgError *) pbSendBuffer;
+            if (error_msg->code == VSC_SUCCESS) {
+                qemu_mutex_lock(&pending_reader_lock);
+                if (pending_reader) {
+                    vreader_set_id(pending_reader, mhHeader.reader_id);
+                    vreader_free(pending_reader);
+                    pending_reader = NULL;
+                    qemu_cond_signal(&pending_reader_condition);
+                }
+                qemu_mutex_unlock(&pending_reader_lock);
+                break;
             }
-            qemu_mutex_unlock(&pending_reader_lock);
+            printf("warning: qemu refused to add reader\n");
+            if (error_msg->code == VSC_CANNOT_ADD_MORE_READERS) {
+                /* clear pending reader, qemu can't handle any more */
+                qemu_mutex_lock(&pending_reader_lock);
+                if (pending_reader) {
+                    pending_reader = NULL;
+                    /* make sure the event loop doesn't hang */
+                    qemu_cond_signal(&pending_reader_condition);
+                }
+                qemu_mutex_unlock(&pending_reader_lock);
+            }
+            break;
+        case VSC_Init:
+            if (on_host_init(&mhHeader, (VSCMsgInit *)pbSendBuffer) < 0) {
+                return FALSE;
+            }
+            break;
+        default:
+            g_warn_if_reached();
+            return FALSE;
         }
-        break;
-    case VSC_Init:
-        if (on_host_init(&mhHeader, (VSCMsgInit *)pbSendBuffer) < 0) {
-            return -1;
+
+        state = STATE_HEADER;
+    }
+
+
+    return TRUE;
+}
+
+static gboolean
+do_socket(GIOChannel *source,
+          GIOCondition condition,
+          gpointer data)
+{
+    /* not sure if two watches work well with a single win32 sources */
+    if (condition & G_IO_OUT) {
+        if (!do_socket_send(source, condition, data)) {
+            return FALSE;
         }
-        break;
-    default:
-        printf("Default\n");
-        return -1;
     }
 
-    return 0;
+    if (condition & G_IO_IN) {
+        if (!do_socket_read(source, condition, data)) {
+            return FALSE;
+        }
+    }
+
+    return TRUE;
 }
 
 static void
-do_command(void)
+update_socket_watch(gboolean out)
+{
+    if (socket_tag != 0) {
+        g_source_remove(socket_tag);
+    }
+
+    socket_tag = g_io_add_watch(channel_socket,
+        G_IO_IN | (out ? G_IO_OUT : 0), do_socket, NULL);
+}
+
+static gboolean
+do_command(GIOChannel *source,
+           GIOCondition condition,
+           gpointer data)
 {
-    char inbuf[255];
     char *string;
     VCardEmulError error;
     static unsigned int default_reader_id;
     unsigned int reader_id;
     VReader *reader = NULL;
+    GError *err = NULL;
+
+    g_assert(condition & G_IO_IN);
 
     reader_id = default_reader_id;
-    string = fgets(inbuf, sizeof(inbuf), stdin);
+    g_io_channel_read_line(source, &string, NULL, NULL, &err);
+    if (err != NULL) {
+        g_error("Error while reading command: %s", err->message);
+    }
+
     if (string != NULL) {
         if (strncmp(string, "exit", 4) == 0) {
             /* remove all the readers */
@@ -491,6 +583,8 @@ do_command(void)
     vreader_free(reader);
     printf("> ");
     fflush(stdout);
+
+    return TRUE;
 }
 
 
@@ -504,7 +598,7 @@ connect_to_qemu(
 ) {
     struct addrinfo hints;
     struct addrinfo *server;
-    int ret;
+    int ret, sock;
 
     sock = qemu_socket(AF_INET, SOCK_STREAM, 0);
     if (sock < 0) {
@@ -543,6 +637,8 @@ main(
     int argc,
     char *argv[]
 ) {
+    GMainLoop *loop;
+    GIOChannel *channel_stdin;
     char *qemu_host;
     char *qemu_port;
     VSCMsgHeader mhHeader;
@@ -552,7 +648,10 @@ main(
     char *cert_names[MAX_CERTS];
     char *emul_args = NULL;
     int cert_count = 0;
-    int c, rv;
+    int c, sock;
+
+    if (socket_init() != 0)
+        return 1;
 
     while ((c = getopt(argc, argv, "c:e:pd:")) != -1) {
         switch (c) {
@@ -618,15 +717,33 @@ main(
         exit(5);
     }
 
-    qemu_mutex_init(&write_lock);
+    socket_to_send = g_byte_array_new();
+    qemu_mutex_init(&socket_to_send_lock);
     qemu_mutex_init(&pending_reader_lock);
     qemu_cond_init(&pending_reader_condition);
 
     vcard_emul_init(command_line_options);
 
+    loop = g_main_loop_new(NULL, true);
+
     printf("> ");
     fflush(stdout);
 
+#ifdef _WIN32
+    channel_stdin = g_io_channel_win32_new_fd(STDIN_FILENO);
+#else
+    channel_stdin = g_io_channel_unix_new(STDIN_FILENO);
+#endif
+    g_io_add_watch(channel_stdin, G_IO_IN, do_command, NULL);
+#ifdef _WIN32
+    channel_socket = g_io_channel_win32_new_socket(sock);
+#else
+    channel_socket = g_io_channel_unix_new(sock);
+#endif
+    g_io_channel_set_encoding(channel_socket, NULL, NULL);
+    /* we buffer ourself for thread safety reasons */
+    g_io_channel_set_buffered(channel_socket, FALSE);
+
     /* Send init message, Host responds (and then we send reader attachments) */
     VSCMsgInit init = {
         .version = htonl(VSCARD_VERSION),
@@ -635,28 +752,12 @@ main(
     };
     send_msg(VSC_Init, mhHeader.reader_id, &init, sizeof(init));
 
-    do {
-        fd_set fds;
-
-        FD_ZERO(&fds);
-        FD_SET(1, &fds);
-        FD_SET(sock, &fds);
+    g_main_loop_run(loop);
+    g_main_loop_unref(loop);
 
-        /* waiting on input from the socket */
-        rv = select(sock+1, &fds, NULL, NULL, NULL);
-        if (rv < 0) {
-            /* handle error */
-            perror("select");
-            return 7;
-        }
-        if (FD_ISSET(1, &fds)) {
-            do_command();
-        }
-        if (!FD_ISSET(sock, &fds)) {
-            continue;
-        }
-        rv = do_socket_read();
-    } while (rv >= 0);
+    g_io_channel_unref(channel_stdin);
+    g_io_channel_unref(channel_socket);
+    g_byte_array_unref(socket_to_send);
 
     return 0;
 }
commit 930c8ad472ec00d40cfbf1e9b1395946bf0dd392
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Mon Feb 25 23:31:15 2013 +0100

    libcacard: vscclient to use QemuThread for portability
    
    Signed-off-by: Marc-André Lureau <marcandre.lureau at redhat.com>
    Reviewed-by: Alon Levy <alevy at redhat.com>

diff --git a/libcacard/vscclient.c b/libcacard/vscclient.c
index 5e00db3..5f47634 100644
--- a/libcacard/vscclient.c
+++ b/libcacard/vscclient.c
@@ -218,8 +218,7 @@ on_host_init(VSCMsgHeader *mhHeader, VSCMsgInit *incoming)
     int num_capabilities =
         1 + ((mhHeader->length - sizeof(VSCMsgInit)) / sizeof(uint32_t));
     int i;
-    int rv;
-    pthread_t thread_id;
+    QemuThread thread_id;
 
     incoming->version = ntohl(incoming->version);
     if (incoming->version != VSCARD_VERSION) {
@@ -242,11 +241,7 @@ on_host_init(VSCMsgHeader *mhHeader, VSCMsgInit *incoming)
     send_msg(VSC_ReaderRemove, VSCARD_MINIMAL_READER_ID, NULL, 0);
     /* launch the event_thread. This will trigger reader adds for all the
      * existing readers */
-    rv = pthread_create(&thread_id, NULL, event_thread, NULL);
-    if (rv < 0) {
-        perror("pthread_create");
-        return rv;
-    }
+    qemu_thread_create(&thread_id, event_thread, NULL, 0);
     return 0;
 }
 
commit a50b831ae1fe039b7c22793f307e0b8afdf50589
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Mon Feb 25 23:31:14 2013 +0100

    libcacard: split vscclient main() from socket reading
    
    Signed-off-by: Marc-André Lureau <marcandre.lureau at redhat.com>
    Reviewed-by: Alon Levy <alevy at redhat.com>

diff --git a/libcacard/vscclient.c b/libcacard/vscclient.c
index 9b744f2..5e00db3 100644
--- a/libcacard/vscclient.c
+++ b/libcacard/vscclient.c
@@ -211,6 +211,166 @@ get_id_from_string(char *string, unsigned int default_id)
     return id;
 }
 
+static int
+on_host_init(VSCMsgHeader *mhHeader, VSCMsgInit *incoming)
+{
+    uint32_t *capabilities = (incoming->capabilities);
+    int num_capabilities =
+        1 + ((mhHeader->length - sizeof(VSCMsgInit)) / sizeof(uint32_t));
+    int i;
+    int rv;
+    pthread_t thread_id;
+
+    incoming->version = ntohl(incoming->version);
+    if (incoming->version != VSCARD_VERSION) {
+        if (verbose > 0) {
+            printf("warning: host has version %d, we have %d\n",
+                verbose, VSCARD_VERSION);
+        }
+    }
+    if (incoming->magic != VSCARD_MAGIC) {
+        printf("unexpected magic: got %d, expected %d\n",
+            incoming->magic, VSCARD_MAGIC);
+        return -1;
+    }
+    for (i = 0 ; i < num_capabilities; ++i) {
+        capabilities[i] = ntohl(capabilities[i]);
+    }
+    /* Future: check capabilities */
+    /* remove whatever reader might be left in qemu,
+     * in case of an unclean previous exit. */
+    send_msg(VSC_ReaderRemove, VSCARD_MINIMAL_READER_ID, NULL, 0);
+    /* launch the event_thread. This will trigger reader adds for all the
+     * existing readers */
+    rv = pthread_create(&thread_id, NULL, event_thread, NULL);
+    if (rv < 0) {
+        perror("pthread_create");
+        return rv;
+    }
+    return 0;
+}
+
+#define APDUBufSize 270
+
+static int
+do_socket_read(void)
+{
+    int rv;
+    int dwSendLength;
+    int dwRecvLength;
+    uint8_t pbRecvBuffer[APDUBufSize];
+    uint8_t pbSendBuffer[APDUBufSize];
+    VReaderStatus reader_status;
+    VReader *reader = NULL;
+    VSCMsgHeader mhHeader;
+    VSCMsgError *error_msg;
+
+    rv = read(sock, &mhHeader, sizeof(mhHeader));
+    if (rv < sizeof(mhHeader)) {
+        /* Error */
+        if (rv < 0) {
+            perror("header read error\n");
+        } else {
+            fprintf(stderr, "header short read %d\n", rv);
+        }
+        return -1;
+    }
+    mhHeader.type = ntohl(mhHeader.type);
+    mhHeader.reader_id = ntohl(mhHeader.reader_id);
+    mhHeader.length = ntohl(mhHeader.length);
+    if (verbose) {
+        printf("Header: type=%d, reader_id=%u length=%d (0x%x)\n",
+               mhHeader.type, mhHeader.reader_id, mhHeader.length,
+               mhHeader.length);
+    }
+    switch (mhHeader.type) {
+    case VSC_APDU:
+    case VSC_Flush:
+    case VSC_Error:
+    case VSC_Init:
+        rv = read(sock, pbSendBuffer, mhHeader.length);
+        break;
+    default:
+        fprintf(stderr, "Unexpected message of type 0x%X\n", mhHeader.type);
+        return -1;
+    }
+    switch (mhHeader.type) {
+    case VSC_APDU:
+        if (rv < 0) {
+            /* Error */
+            fprintf(stderr, "read error\n");
+            close(sock);
+            return -1;
+        }
+        if (verbose) {
+            printf(" recv APDU: ");
+            print_byte_array(pbSendBuffer, mhHeader.length);
+        }
+        /* Transmit received APDU */
+        dwSendLength = mhHeader.length;
+        dwRecvLength = sizeof(pbRecvBuffer);
+        reader = vreader_get_reader_by_id(mhHeader.reader_id);
+        reader_status = vreader_xfr_bytes(reader,
+                                          pbSendBuffer, dwSendLength,
+                                          pbRecvBuffer, &dwRecvLength);
+        if (reader_status == VREADER_OK) {
+            mhHeader.length = dwRecvLength;
+            if (verbose) {
+                printf(" send response: ");
+                print_byte_array(pbRecvBuffer, mhHeader.length);
+            }
+            send_msg(VSC_APDU, mhHeader.reader_id,
+                     pbRecvBuffer, dwRecvLength);
+        } else {
+            rv = reader_status; /* warning: not meaningful */
+            send_msg(VSC_Error, mhHeader.reader_id, &rv, sizeof(uint32_t));
+        }
+        vreader_free(reader);
+        reader = NULL; /* we've freed it, don't use it by accident
+                          again */
+        break;
+    case VSC_Flush:
+        /* TODO: actually flush */
+        send_msg(VSC_FlushComplete, mhHeader.reader_id, NULL, 0);
+        break;
+    case VSC_Error:
+        error_msg = (VSCMsgError *) pbSendBuffer;
+        if (error_msg->code == VSC_SUCCESS) {
+            qemu_mutex_lock(&pending_reader_lock);
+            if (pending_reader) {
+                vreader_set_id(pending_reader, mhHeader.reader_id);
+                vreader_free(pending_reader);
+                pending_reader = NULL;
+                qemu_cond_signal(&pending_reader_condition);
+            }
+            qemu_mutex_unlock(&pending_reader_lock);
+            break;
+        }
+        printf("warning: qemu refused to add reader\n");
+        if (error_msg->code == VSC_CANNOT_ADD_MORE_READERS) {
+            /* clear pending reader, qemu can't handle any more */
+            qemu_mutex_lock(&pending_reader_lock);
+            if (pending_reader) {
+                pending_reader = NULL;
+                /* make sure the event loop doesn't hang */
+                qemu_cond_signal(&pending_reader_condition);
+            }
+            qemu_mutex_unlock(&pending_reader_lock);
+        }
+        break;
+    case VSC_Init:
+        if (on_host_init(&mhHeader, (VSCMsgInit *)pbSendBuffer) < 0) {
+            return -1;
+        }
+        break;
+    default:
+        printf("Default\n");
+        return -1;
+    }
+
+    return 0;
+}
+
 static void
 do_command(void)
 {
@@ -339,8 +499,6 @@ do_command(void)
 }
 
 
-#define APDUBufSize 270
-
 /* just for ease of parsing command line arguments. */
 #define MAX_CERTS 100
 
@@ -385,44 +543,6 @@ connect_to_qemu(
     return sock;
 }
 
-static int on_host_init(VSCMsgHeader *mhHeader, VSCMsgInit *incoming)
-{
-    uint32_t *capabilities = (incoming->capabilities);
-    int num_capabilities =
-        1 + ((mhHeader->length - sizeof(VSCMsgInit)) / sizeof(uint32_t));
-    int i;
-    int rv;
-    pthread_t thread_id;
-
-    incoming->version = ntohl(incoming->version);
-    if (incoming->version != VSCARD_VERSION) {
-        if (verbose > 0) {
-            printf("warning: host has version %d, we have %d\n",
-                verbose, VSCARD_VERSION);
-        }
-    }
-    if (incoming->magic != VSCARD_MAGIC) {
-        printf("unexpected magic: got %d, expected %d\n",
-            incoming->magic, VSCARD_MAGIC);
-        return -1;
-    }
-    for (i = 0 ; i < num_capabilities; ++i) {
-        capabilities[i] = ntohl(capabilities[i]);
-    }
-    /* Future: check capabilities */
-    /* remove whatever reader might be left in qemu,
-     * in case of an unclean previous exit. */
-    send_msg(VSC_ReaderRemove, VSCARD_MINIMAL_READER_ID, NULL, 0);
-    /* launch the event_thread. This will trigger reader adds for all the
-     * existing readers */
-    rv = pthread_create(&thread_id, NULL, event_thread, NULL);
-    if (rv < 0) {
-        perror("pthread_create");
-        return rv;
-    }
-    return 0;
-}
-
 int
 main(
     int argc,
@@ -431,21 +551,13 @@ main(
     char *qemu_host;
     char *qemu_port;
     VSCMsgHeader mhHeader;
-    VSCMsgError *error_msg;
 
-    int rv;
-    int dwSendLength;
-    int dwRecvLength;
-    uint8_t pbRecvBuffer[APDUBufSize];
-    uint8_t pbSendBuffer[APDUBufSize];
-     VReaderStatus reader_status;
-    VReader *reader = NULL;
     VCardEmulOptions *command_line_options = NULL;
 
     char *cert_names[MAX_CERTS];
     char *emul_args = NULL;
     int cert_count = 0;
-    int c;
+    int c, rv;
 
     while ((c = getopt(argc, argv, "c:e:pd:")) != -1) {
         switch (c) {
@@ -548,109 +660,7 @@ main(
         if (!FD_ISSET(sock, &fds)) {
             continue;
         }
-
-        rv = read(sock, &mhHeader, sizeof(mhHeader));
-        if (rv < sizeof(mhHeader)) {
-            /* Error */
-            if (rv < 0) {
-                perror("header read error\n");
-            } else {
-                fprintf(stderr, "header short read %d\n", rv);
-            }
-            return 8;
-        }
-        mhHeader.type = ntohl(mhHeader.type);
-        mhHeader.reader_id = ntohl(mhHeader.reader_id);
-        mhHeader.length = ntohl(mhHeader.length);
-        if (verbose) {
-            printf("Header: type=%d, reader_id=%u length=%d (0x%x)\n",
-                    mhHeader.type, mhHeader.reader_id, mhHeader.length,
-                                               mhHeader.length);
-        }
-        switch (mhHeader.type) {
-        case VSC_APDU:
-        case VSC_Flush:
-        case VSC_Error:
-        case VSC_Init:
-            rv = read(sock, pbSendBuffer, mhHeader.length);
-            break;
-        default:
-            fprintf(stderr, "Unexpected message of type 0x%X\n", mhHeader.type);
-            return 0;
-        }
-        switch (mhHeader.type) {
-        case VSC_APDU:
-            if (rv < 0) {
-                /* Error */
-                fprintf(stderr, "read error\n");
-                close(sock);
-                return 8;
-            }
-            if (verbose) {
-                printf(" recv APDU: ");
-                print_byte_array(pbSendBuffer, mhHeader.length);
-            }
-            /* Transmit received APDU */
-            dwSendLength = mhHeader.length;
-            dwRecvLength = sizeof(pbRecvBuffer);
-            reader = vreader_get_reader_by_id(mhHeader.reader_id);
-            reader_status = vreader_xfr_bytes(reader,
-                pbSendBuffer, dwSendLength,
-                pbRecvBuffer, &dwRecvLength);
-            if (reader_status == VREADER_OK) {
-                mhHeader.length = dwRecvLength;
-                if (verbose) {
-                    printf(" send response: ");
-                    print_byte_array(pbRecvBuffer, mhHeader.length);
-                }
-                send_msg(VSC_APDU, mhHeader.reader_id,
-                         pbRecvBuffer, dwRecvLength);
-            } else {
-                rv = reader_status; /* warning: not meaningful */
-                send_msg(VSC_Error, mhHeader.reader_id, &rv, sizeof(uint32_t));
-            }
-            vreader_free(reader);
-            reader = NULL; /* we've freed it, don't use it by accident
-                              again */
-            break;
-        case VSC_Flush:
-            /* TODO: actually flush */
-            send_msg(VSC_FlushComplete, mhHeader.reader_id, NULL, 0);
-            break;
-        case VSC_Error:
-            error_msg = (VSCMsgError *) pbSendBuffer;
-            if (error_msg->code == VSC_SUCCESS) {
-                qemu_mutex_lock(&pending_reader_lock);
-                if (pending_reader) {
-                    vreader_set_id(pending_reader, mhHeader.reader_id);
-                    vreader_free(pending_reader);
-                    pending_reader = NULL;
-                    qemu_cond_signal(&pending_reader_condition);
-                }
-                qemu_mutex_unlock(&pending_reader_lock);
-                break;
-            }
-            printf("warning: qemu refused to add reader\n");
-            if (error_msg->code == VSC_CANNOT_ADD_MORE_READERS) {
-                /* clear pending reader, qemu can't handle any more */
-                qemu_mutex_lock(&pending_reader_lock);
-                if (pending_reader) {
-                    pending_reader = NULL;
-                    /* make sure the event loop doesn't hang */
-                    qemu_cond_signal(&pending_reader_condition);
-                }
-                qemu_mutex_unlock(&pending_reader_lock);
-            }
-            break;
-        case VSC_Init:
-            if (on_host_init(&mhHeader, (VSCMsgInit *)pbSendBuffer) < 0) {
-                return -1;
-            }
-            break;
-        default:
-            printf("Default\n");
-            return 0;
-        }
+        rv = do_socket_read();
     } while (rv >= 0);
 
     return 0;
commit 5354e4d242175e067bb70732f694ae9322a81351
Author: Marc-André Lureau <mlureau at redhat.com>
Date:   Mon Feb 25 23:31:13 2013 +0100

    libcacard: fix mingw64 cross-compilation
    
    Compile and link with version.lo
    
    Signed-off-by: Marc-André Lureau <mlureau at redhat.com>
    Reviewed-by: Alon Levy <alevy at redhat.com>

diff --git a/Makefile b/Makefile
index 88375dc..b6ad03a 100644
--- a/Makefile
+++ b/Makefile
@@ -166,11 +166,15 @@ recurse-all: $(SUBDIR_RULES) $(ROMSUBDIR_RULES)
 
 bt-host.o: QEMU_CFLAGS += $(BLUEZ_CFLAGS)
 
-version.o: $(SRC_PATH)/version.rc config-host.h
+version.o: $(SRC_PATH)/version.rc config-host.h | version.lo
 	$(call quiet-command,$(WINDRES) -I. -o $@ $<,"  RC    $(TARGET_DIR)$@")
+version.lo: $(SRC_PATH)/version.rc config-host.h
+	$(call quiet-command,$(LIBTOOL) --mode=compile --tag=RC $(WINDRES) -I. -o $@ $<,"lt RC   $(TARGET_DIR)$@")
 
 version-obj-$(CONFIG_WIN32) += version.o
-Makefile: $(version-obj-y)
+version-lobj-$(CONFIG_WIN32) += $(if $(LIBTOOL),version.lo)
+Makefile: $(version-obj-y) $(version-lobj-y)
+
 
 ######################################################################
 # Build libraries
diff --git a/rules.mak b/rules.mak
index 36aba2d..292a422 100644
--- a/rules.mak
+++ b/rules.mak
@@ -35,7 +35,8 @@ LIBTOOL += $(if $(V),,--quiet)
 LINK = $(call quiet-command,\
        $(if $(filter %.lo %.la,$^),$(LIBTOOL) --mode=link --tag=CC \
        )$(CC) $(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ \
-       $(sort $(filter %.o, $1)) $(filter-out %.o, $1) $(version-obj-y) \
+       $(sort $(filter %.o, $1)) $(filter-out %.o, $1) \
+       $(if $(filter %.lo %.la,$^),$(version-lobj-y),$(version-obj-y)) \
        $(if $(filter %.lo %.la,$^),$(LIBTOOLFLAGS)) \
        $(LIBS),$(if $(filter %.lo %.la,$^),"lt LINK ", "  LINK  ")"$(TARGET_DIR)$@")
 endif
commit 37746c5eacf309fa019ea0fa45f776c36c561457
Author: Marc-André Lureau <mlureau at redhat.com>
Date:   Mon Feb 25 23:31:12 2013 +0100

    build-sys: must link with -fstack-protector
    
    It is needed to give that flag to the linker as well, but latest
    libtool 2.4.2 still swallows that argument, so let's pass it with
    libtool -Wc argument.
    
    qemu-1.4.0/stubs/arch-query-cpu-def.c:6: undefined reference to `__stack_chk_guard'
    
    Signed-off-by: Marc-André Lureau <mlureau at redhat.com>
    Reviewed-by: Alon Levy <alevy at redhat.com>

diff --git a/configure b/configure
index 33d3354..ee2e7e8 100755
--- a/configure
+++ b/configure
@@ -1244,7 +1244,7 @@ fi
 gcc_flags="-Wold-style-declaration -Wold-style-definition -Wtype-limits"
 gcc_flags="-Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers $gcc_flags"
 gcc_flags="-Wmissing-include-dirs -Wempty-body -Wnested-externs $gcc_flags"
-gcc_flags="-fstack-protector-all -Wendif-labels $gcc_flags"
+gcc_flags="-Wendif-labels $gcc_flags"
 gcc_flags="-Wno-initializer-overrides $gcc_flags"
 # Note that we do not add -Werror to gcc_flags here, because that would
 # enable it for all configure tests. If a configure test failed due
@@ -1263,6 +1263,11 @@ for flag in $gcc_flags; do
     fi
 done
 
+if compile_prog "-Werror -fstack-protector-all" "" ; then
+    QEMU_CFLAGS="$QEMU_CFLAGS -fstack-protector-all"
+    LIBTOOLFLAGS="$LIBTOOLFLAGS -Wc,-fstack-protector-all"
+fi
+
 # Workaround for http://gcc.gnu.org/PR55489.  Happens with -fPIE/-fPIC and
 # large functions that use global variables.  The bug is in all releases of
 # GCC, but it became particularly acute in 4.6.x and 4.7.x.  It is fixed in
@@ -4078,6 +4083,7 @@ else
   echo "AUTOCONF_HOST := "                             >> $config_host_mak
 fi
 echo "LDFLAGS=$LDFLAGS" >> $config_host_mak
+echo "LIBTOOLFLAGS=$LIBTOOLFLAGS" >> $config_host_mak
 echo "LIBS+=$LIBS" >> $config_host_mak
 echo "LIBS_TOOLS+=$libs_tools" >> $config_host_mak
 echo "EXESUF=$EXESUF" >> $config_host_mak
diff --git a/rules.mak b/rules.mak
index edc2552..36aba2d 100644
--- a/rules.mak
+++ b/rules.mak
@@ -36,6 +36,7 @@ LINK = $(call quiet-command,\
        $(if $(filter %.lo %.la,$^),$(LIBTOOL) --mode=link --tag=CC \
        )$(CC) $(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ \
        $(sort $(filter %.o, $1)) $(filter-out %.o, $1) $(version-obj-y) \
+       $(if $(filter %.lo %.la,$^),$(LIBTOOLFLAGS)) \
        $(LIBS),$(if $(filter %.lo %.la,$^),"lt LINK ", "  LINK  ")"$(TARGET_DIR)$@")
 endif
 
commit d3bf825e59125bc6a0accec0dca119ea0155cb82
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Mon Feb 25 23:31:11 2013 +0100

    util: move socket_init() to osdep.c
    
    vscclient needs to call socket_init() for portability.
    Moving to osdep.c since it has no internal dependency.
    
    Signed-off-by: Marc-André Lureau <marcandre.lureau at redhat.com>
    Reviewed-by: Alon Levy <alevy at redhat.com>

diff --git a/util/osdep.c b/util/osdep.c
index bd59ac9..6ae5aaf 100644
--- a/util/osdep.c
+++ b/util/osdep.c
@@ -406,3 +406,26 @@ bool fips_get_state(void)
     return fips_enabled;
 }
 
+#ifdef _WIN32
+static void socket_cleanup(void)
+{
+    WSACleanup();
+}
+#endif
+
+int socket_init(void)
+{
+#ifdef _WIN32
+    WSADATA Data;
+    int ret, err;
+
+    ret = WSAStartup(MAKEWORD(2, 2), &Data);
+    if (ret != 0) {
+        err = WSAGetLastError();
+        fprintf(stderr, "WSAStartup: %d\n", err);
+        return -1;
+    }
+    atexit(socket_cleanup);
+#endif
+    return 0;
+}
diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index 94581aa..fdd8dc4 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -974,27 +974,3 @@ int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp)
     qemu_opts_del(opts);
     return fd;
 }
-
-#ifdef _WIN32
-static void socket_cleanup(void)
-{
-    WSACleanup();
-}
-#endif
-
-int socket_init(void)
-{
-#ifdef _WIN32
-    WSADATA Data;
-    int ret, err;
-
-    ret = WSAStartup(MAKEWORD(2,2), &Data);
-    if (ret != 0) {
-        err = WSAGetLastError();
-        fprintf(stderr, "WSAStartup: %d\n", err);
-        return -1;
-    }
-    atexit(socket_cleanup);
-#endif
-    return 0;
-}
commit e2d9c5e769d59f2bca649b8286892d49bdcfc2b1
Author: Marc-André Lureau <mlureau at redhat.com>
Date:   Wed Feb 27 21:08:06 2013 +0100

    libcacard: use system config directory for nss db on win32
    
    It's a bit nicer to look for default database under
    CSIDL_COMMON_APPDATA\pki\nss rather that /etc/pki/nss.
    
    Signed-off-by: Marc-André Lureau <mlureau at redhat.com>
    Reviewed-by: Alon Levy <alevy at redhat.com>

diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c
index df79476..21d4689 100644
--- a/libcacard/vcard_emul_nss.c
+++ b/libcacard/vcard_emul_nss.c
@@ -893,7 +893,23 @@ vcard_emul_init(const VCardEmulOptions *options)
     if (options->nss_db) {
         rv = NSS_Init(options->nss_db);
     } else {
-        rv = NSS_Init("sql:/etc/pki/nssdb");
+        gchar *path, *db;
+#ifndef _WIN32
+        path = g_strdup("/etc/pki/nssdb");
+#else
+        if (g_get_system_config_dirs() == NULL ||
+            g_get_system_config_dirs()[0] == NULL) {
+            return VCARD_EMUL_FAIL;
+        }
+
+        path = g_build_filename(
+            g_get_system_config_dirs()[0], "pki", "nssdb", NULL);
+#endif
+        db = g_strdup_printf("sql:%s", path);
+
+        rv = NSS_Init(db);
+        g_free(db);
+        g_free(path);
     }
     if (rv != SECSuccess) {
         return VCARD_EMUL_FAIL;
commit da000a4867749434e03896a5072321771736352a
Author: Jim Meyering <meyering at redhat.com>
Date:   Mon May 21 21:51:33 2012 +0200

    ccid: declare DEFAULT_ATR table to be "static const"
    
    Signed-off-by: Jim Meyering <meyering at redhat.com>
    Reviewed-by: Alon Levy <alevy at redhat.com>
    Reviewed-by: Marc-André Lureau <mlureau at redhat.com>

diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
index 71a45f6..275b887 100644
--- a/hw/usb/ccid-card-passthru.c
+++ b/hw/usb/ccid-card-passthru.c
@@ -27,7 +27,7 @@ do {                                                    \
 #define D_VERBOSE 4
 
 /* TODO: do we still need this? */
-uint8_t DEFAULT_ATR[] = {
+static const uint8_t DEFAULT_ATR[] = {
 /*
  * From some example somewhere
  * 0x3B, 0xB0, 0x18, 0x00, 0xD1, 0x81, 0x05, 0xB1, 0x40, 0x38, 0x1F, 0x03, 0x28
commit d18c7117467aa5fae95a7c6eaffcf50618197e79
Author: Jim Meyering <meyering at redhat.com>
Date:   Mon May 21 21:56:20 2012 +0200

    ccid: make backend_enum_table "static const" and adjust users
    
    Signed-off-by: Jim Meyering <meyering at redhat.com>
    Reviewed-by: Alon Levy <alevy at redhat.com>
    Reviewed-by: Marc-André Lureau <mlureau at redhat.com>

diff --git a/hw/usb/ccid-card-emulated.c b/hw/usb/ccid-card-emulated.c
index 6cbb176..094284d 100644
--- a/hw/usb/ccid-card-emulated.c
+++ b/hw/usb/ccid-card-emulated.c
@@ -462,14 +462,14 @@ typedef struct EnumTable {
     uint32_t value;
 } EnumTable;
 
-EnumTable backend_enum_table[] = {
+static const EnumTable backend_enum_table[] = {
     {BACKEND_NSS_EMULATED_NAME, BACKEND_NSS_EMULATED},
     {BACKEND_CERTIFICATES_NAME, BACKEND_CERTIFICATES},
     {NULL, 0},
 };
 
 static uint32_t parse_enumeration(char *str,
-    EnumTable *table, uint32_t not_found_value)
+    const EnumTable *table, uint32_t not_found_value)
 {
     uint32_t ret = not_found_value;
 
@@ -490,7 +490,7 @@ static int emulated_initfn(CCIDCardState *base)
 {
     EmulatedState *card = DO_UPCAST(EmulatedState, base, base);
     VCardEmulError ret;
-    EnumTable *ptable;
+    const EnumTable *ptable;
 
     QSIMPLEQ_INIT(&card->event_list);
     QSIMPLEQ_INIT(&card->guest_apdu_list);
commit d0ebd78890fba2ab458ec34763dae8566ccb1b72
Author: Marc-André Lureau <mlureau at redhat.com>
Date:   Wed Nov 21 14:16:08 2012 +0100

    ccid-card-emul: do not crash if backend is not provided
    
    Program received signal SIGSEGV, Segmentation fault.
    __strcmp_sse42 () at ../sysdeps/x86_64/multiarch/strcmp-sse42.S:164
    164               movdqu        (%rsi), %xmm2
    (gdb) bt
        at /home/elmarco/320g/src/qemu/hw/ccid-card-emulated.c:477
        at /home/elmarco/320g/src/qemu/hw/ccid-card-emulated.c:503
    
    Signed-off-by: Marc-André Lureau <mlureau at redhat.com>
    Reviewed-by: Alon Levy <alevy at redhat.com>

diff --git a/hw/usb/ccid-card-emulated.c b/hw/usb/ccid-card-emulated.c
index d534c94..6cbb176 100644
--- a/hw/usb/ccid-card-emulated.c
+++ b/hw/usb/ccid-card-emulated.c
@@ -473,6 +473,9 @@ static uint32_t parse_enumeration(char *str,
 {
     uint32_t ret = not_found_value;
 
+    if (str == NULL)
+        return 0;
+
     while (table->name != NULL) {
         if (strcmp(table->name, str) == 0) {
             ret = table->value;
commit e2fd2115ce26049335d66ae0ae5e5c0ad06fb498
Author: Marc-André Lureau <mlureau at redhat.com>
Date:   Sun Dec 2 22:00:55 2012 +0100

    libcacard: correct T0 historical bytes size
    
    The VCARD_ATR_PREFIX macro adds a prefix of 6 characters only.
    
    pcsc_scan was complaining before the patch:
    
    + Historical bytes: 56 43 41 52 44 5F 4E 53 53
     ERROR! ATR is truncated: 2 byte(s) is/are missing
    
    Signed-off-by: Marc-André Lureau <mlureau at redhat.com>
    Reviewed-by: Alon Levy <alevy at redhat.com>

diff --git a/libcacard/vcardt.h b/libcacard/vcardt.h
index d3e9522..538bdde 100644
--- a/libcacard/vcardt.h
+++ b/libcacard/vcardt.h
@@ -26,7 +26,7 @@ typedef struct VCardEmulStruct VCardEmul;
 #define MAX_CHANNEL 4
 
 /* create an ATR with appropriate historical bytes */
-#define VCARD_ATR_PREFIX(size) 0x3b, 0x68+(size), 0x00, 0xff, \
+#define VCARD_ATR_PREFIX(size) 0x3b, 0x66+(size), 0x00, 0xff, \
                                'V', 'C', 'A', 'R', 'D', '_'
 
 


More information about the Spice-commits mailing list