[Spice-commits] 133 commits - Makefile Makefile.objs Makefile.target block.c block.h block/blkdebug.c block/bochs.c block/cloop.c block/dmg.c block/parallels.c block/qcow.c block/qcow2.c block/vdi.c block/vpc.c configure cpu-all.h cpu-defs.h cpu-exec.c cpus.c darwin-user/main.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/x86_64-softmmu.mak exec-all.h exec.c gdbstub.c hw/acpi.c hw/acpi.h hw/acpi_piix4.c hw/apb_pci.c hw/apm.c hw/apm.h hw/e1000.c hw/fdc.c hw/fdc.h hw/hw.h hw/ide hw/iov.c hw/iov.h hw/lsi53c895a.c hw/mc146818rtc.c hw/mc146818rtc.h hw/mips_jazz.c hw/mips_malta.c hw/mips_r4k.c hw/pc.c hw/pc.h hw/pc_piix.c hw/pci.c hw/pci.h hw/pckbd.c hw/piix_pci.c hw/pm_smbus.c hw/pm_smbus.h hw/ppc.c hw/ppc_prep.c hw/qdev.c hw/qdev.h hw/s390-virtio.c hw/scsi-disk.c hw/serial.c hw/sm501.c hw/tmp105.c hw/vga.c hw/virtio-net.c hw/virtio.c ia64-dis.c iov.c iov.h kvm-all.c kvm.h linux-user/elfload.c linux-user/main.c linux-user/mmap.c linux-user/signal.c linux-user/syscall.c linux-user/syscall_defs.h mips-dis.c monitor.c pc-bios/README pc-bios/bios.bin pc-bios/openbios-ppc pc-bios/openbios-sparc32 pc-bios/openbios-sparc64 pc-bios/s390-zipl.rom qemu-common.h qemu-monitor.hx qemu-nbd.c qemu-sockets.c roms/seabios savevm.c softmmu_exec.h sparc-dis.c target-i386/kvm.c target-i386/translate.c target-mips/translate.c target-ppc/kvm.c target-ppc/translate.c target-s390x/kvm.c target-sh4/translate.c target-sparc/cpu.h target-sparc/exec.h target-sparc/helper.c target-sparc/machine.c target-sparc/op_helper.c target-sparc/translate.c tcg/i386 tcg/tcg.c tcg/tcg.h tests/qruncom.c tests/runcom.c vl.c vnc.c

Gerd Hoffmann kraxel at kemper.freedesktop.org
Wed May 19 04:45:27 PDT 2010


 Makefile                             |    3 
 Makefile.objs                        |    5 
 Makefile.target                      |    3 
 block.c                              |   49 +-
 block.h                              |    2 
 block/blkdebug.c                     |    4 
 block/bochs.c                        |   81 +--
 block/cloop.c                        |   48 +-
 block/dmg.c                          |  109 ++---
 block/parallels.c                    |   51 --
 block/qcow.c                         |    2 
 block/qcow2.c                        |  493 +++++++++++------------
 block/vdi.c                          |   34 +
 block/vpc.c                          |   21 
 configure                            |   15 
 cpu-all.h                            |    5 
 cpu-defs.h                           |    6 
 cpu-exec.c                           |   29 -
 cpus.c                               |   90 +++-
 darwin-user/main.c                   |    2 
 default-configs/i386-softmmu.mak     |    1 
 default-configs/mips-softmmu.mak     |    1 
 default-configs/mips64-softmmu.mak   |    1 
 default-configs/mips64el-softmmu.mak |    1 
 default-configs/mipsel-softmmu.mak   |    1 
 default-configs/x86_64-softmmu.mak   |    1 
 exec-all.h                           |    3 
 exec.c                               |  121 +++--
 gdbstub.c                            |   16 
 hw/acpi.c                            |  745 -----------------------------------
 hw/acpi.h                            |   78 +++
 hw/acpi_piix4.c                      |  599 ++++++++++++++++++++++++++++
 hw/apb_pci.c                         |    7 
 hw/apm.c                             |   86 ++++
 hw/apm.h                             |   22 +
 hw/e1000.c                           |    4 
 hw/fdc.c                             |   35 +
 hw/fdc.h                             |    5 
 hw/hw.h                              |    5 
 hw/ide/core.c                        |   10 
 hw/iov.c                             |   70 ---
 hw/iov.h                             |   19 
 hw/lsi53c895a.c                      |   70 ++-
 hw/mc146818rtc.c                     |   47 +-
 hw/mc146818rtc.h                     |   10 
 hw/mips_jazz.c                       |    1 
 hw/mips_malta.c                      |    3 
 hw/mips_r4k.c                        |    3 
 hw/pc.c                              |  423 ++++---------------
 hw/pc.h                              |   48 +-
 hw/pc_piix.c                         |  316 ++++++++++++++
 hw/pci.c                             |   28 -
 hw/pci.h                             |    4 
 hw/pckbd.c                           |    4 
 hw/piix_pci.c                        |    5 
 hw/pm_smbus.c                        |  176 ++++++++
 hw/pm_smbus.h                        |   21 
 hw/ppc.c                             |   10 
 hw/ppc_prep.c                        |    1 
 hw/qdev.c                            |   16 
 hw/qdev.h                            |    4 
 hw/s390-virtio.c                     |   26 +
 hw/scsi-disk.c                       |   37 +
 hw/serial.c                          |   13 
 hw/sm501.c                           |  172 +++++++-
 hw/tmp105.c                          |    9 
 hw/vga.c                             |   10 
 hw/virtio-net.c                      |    2 
 hw/virtio.c                          |    2 
 ia64-dis.c                           |   10 
 iov.c                                |   70 +++
 iov.h                                |   19 
 kvm-all.c                            |   24 -
 kvm.h                                |    4 
 linux-user/elfload.c                 |   79 +++
 linux-user/main.c                    |    3 
 linux-user/mmap.c                    |   19 
 linux-user/signal.c                  |    4 
 linux-user/syscall.c                 |   30 +
 linux-user/syscall_defs.h            |    8 
 mips-dis.c                           |    4 
 monitor.c                            |    3 
 pc-bios/README                       |    9 
 pc-bios/bios.bin                     |binary
 pc-bios/openbios-ppc                 |binary
 pc-bios/openbios-sparc32             |binary
 pc-bios/openbios-sparc64             |binary
 pc-bios/s390-zipl.rom                |binary
 qemu-common.h                        |    8 
 qemu-monitor.hx                      |   26 -
 qemu-nbd.c                           |   34 +
 qemu-sockets.c                       |    3 
 roms/seabios                         |    2 
 savevm.c                             |   23 -
 softmmu_exec.h                       |   25 +
 sparc-dis.c                          |   22 +
 target-i386/kvm.c                    |   29 +
 target-i386/translate.c              |    1 
 target-mips/translate.c              |    6 
 target-ppc/kvm.c                     |   40 +
 target-ppc/translate.c               |    2 
 target-s390x/kvm.c                   |   27 +
 target-sh4/translate.c               |    6 
 target-sparc/cpu.h                   |  119 +----
 target-sparc/exec.h                  |    9 
 target-sparc/helper.c                |   82 ++-
 target-sparc/machine.c               |    4 
 target-sparc/op_helper.c             |  569 +++++++++++++++++++++-----
 target-sparc/translate.c             |   24 -
 tcg/i386/tcg-target.c                |   17 
 tcg/tcg.c                            |    4 
 tcg/tcg.h                            |    3 
 tests/qruncom.c                      |    2 
 tests/runcom.c                       |    2 
 vl.c                                 |    4 
 vnc.c                                |   14 
 116 files changed, 3499 insertions(+), 2238 deletions(-)

New commits:
commit 4ab50ccf6124eb2920262445e8ce0b2e95a2c13b
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Apr 13 15:26:17 2010 -0700

    tcg-i386: Tidy initialization of tcg_target_call_clobber_regs.
    
    Setting the registers one by one is easier to read, and gets
    optimized by the compiler just the same.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 352e427..4e33b25 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -1360,11 +1360,12 @@ void tcg_target_init(TCGContext *s)
 #endif
 
     tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xff);
-    tcg_regset_set32(tcg_target_call_clobber_regs, 0,
-                     (1 << TCG_REG_EAX) | 
-                     (1 << TCG_REG_EDX) | 
-                     (1 << TCG_REG_ECX));
-    
+
+    tcg_regset_clear(tcg_target_call_clobber_regs);
+    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_EAX);
+    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_EDX);
+    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_ECX);
+
     tcg_regset_clear(s->reserved_regs);
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_ESP);
 
commit 6648e29608ce17f6109d5696fb01f056238e2628
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Apr 13 15:23:53 2010 -0700

    tcg-i386: Allocate call-saved registers first.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index e684b33..352e427 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -36,13 +36,13 @@ static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
 #endif
 
 static const int tcg_target_reg_alloc_order[] = {
-    TCG_REG_EAX,
-    TCG_REG_EDX,
-    TCG_REG_ECX,
     TCG_REG_EBX,
     TCG_REG_ESI,
     TCG_REG_EDI,
     TCG_REG_EBP,
+    TCG_REG_ECX,
+    TCG_REG_EDX,
+    TCG_REG_EAX,
 };
 
 static const int tcg_target_call_iarg_regs[3] = { TCG_REG_EAX, TCG_REG_EDX, TCG_REG_ECX };
commit fec0e3e8a735790e903c6f2f82ca0070103f10c4
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Sun Apr 11 18:44:18 2010 +0200

    Fix cross compilation
    
    This patch enhances the algorithm which finds the correct settings for SDL.
    For cross compilations (when cross_prefix is set), it looks for sdl-config
    with cross prefix. Here is the complete search order:
    
    $(cross_prefix}pkg-config              (old, only used for cross compilation)
    ${cross_prefix}sdl_config              (new, only used for cross compilation)
    pkg-config                             (old, needs PATH)
    sdl-config                             (old, needs PATH)
    
    Cross SDL packages (or the user) now can simply set a link (for example
    /usr/bin/i586-mingw32msvc-sdl-config -> /usr/i586-mingw32msvc/bin/sdl-config)
    which allows cross compilations without PATH modifications.
    
    Without the patch, configure and make (which calls configure) typically
    need a non-standard PATH. Failing to set this special PATH results in
    broken builds.
    
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/configure b/configure
index 36d028f..3cd2c5f 100755
--- a/configure
+++ b/configure
@@ -1064,7 +1064,17 @@ fi
 ##########################################
 # SDL probe
 
-if $pkgconfig sdl --modversion >/dev/null 2>&1; then
+# Look for sdl configuration program (pkg-config or sdl-config).
+# Prefer variant with cross prefix if cross compiling,
+# and favour pkg-config with sdl over sdl-config.
+if test -n "$cross_prefix" -a $pkgconfig != pkg-config && \
+     $pkgconfig sdl --modversion >/dev/null 2>&1; then
+  sdlconfig="$pkgconfig sdl"
+  _sdlversion=`$sdlconfig --modversion 2>/dev/null | sed 's/[^0-9]//g'`
+elif test -n "$cross_prefix" && has ${cross_prefix}sdl-config; then
+  sdlconfig="${cross_prefix}sdl-config"
+  _sdlversion=`$sdlconfig --version | sed 's/[^0-9]//g'`
+elif $pkgconfig sdl --modversion >/dev/null 2>&1; then
   sdlconfig="$pkgconfig sdl"
   _sdlversion=`$sdlconfig --modversion 2>/dev/null | sed 's/[^0-9]//g'`
 elif has sdl-config; then
commit d5900813807e237b9f4251290f46125a817da66d
Author: Alexander Graf <agraf at suse.de>
Date:   Fri May 14 16:14:31 2010 +0200

    target-s390: enable SIGP Initial Reset
    
    For SMP to work with KVM, we need to properly emulate the SIGP Initial Reset
    Command. Recent (2.6.32) kernels issue that before the SIGP Reset command that
    actually wakes up the vcpu.
    
    This patch makes -smp work on S390x.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index a2d7741..9bf6abb 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -344,9 +344,20 @@ static int s390_store_status(CPUState *env, uint32_t parameter)
 
 static int s390_cpu_initial_reset(CPUState *env)
 {
-    /* XXX */
-    fprintf(stderr, "XXX SIGP init\n");
-    return -1;
+    int i;
+
+    if (kvm_vcpu_ioctl(env, KVM_S390_INITIAL_RESET, NULL) < 0) {
+        perror("cannot init reset vcpu");
+    }
+
+    /* Manually zero out all registers */
+    cpu_synchronize_state(env);
+    for (i = 0; i < 16; i++) {
+        env->regs[i] = 0;
+    }
+
+    dprintf("DONE: SIGP initial reset: %p\n", env);
+    return 0;
 }
 
 static int handle_sigp(CPUState *env, struct kvm_run *run, uint8_t ipa1)
commit 3d78499a4971132b075b067bdcd202dad50d9217
Author: Thomas Monjalon <thomas at monjalon.net>
Date:   Wed Apr 21 11:48:11 2010 +0200

    target-ppc: remove dead code
    
    This function had been disabled from the beginning:
    see 9fddaa0c0cabb610947146a79b4a9a38b0a216e5
    
    cpu_reset() function is in target-ppc/helper.c
    
    Signed-off-by: Thomas Monjalon <thomas at monjalon.net>
    Acked-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/ppc.c b/hw/ppc.c
index 5baeeaf..2a77eb9 100644
--- a/hw/ppc.c
+++ b/hw/ppc.c
@@ -1085,16 +1085,6 @@ int ppc_dcr_init (CPUState *env, int (*read_error)(int dcrn),
     return 0;
 }
 
-#if 0
-/*****************************************************************************/
-/* Handle system reset (for now, just stop emulation) */
-void cpu_reset(CPUState *env)
-{
-    printf("Reset asked... Stop emulation\n");
-    abort();
-}
-#endif
-
 /*****************************************************************************/
 /* Debug port */
 void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val)
commit fe270d044d512a308fb1fdf02cb11db46df29cdb
Author: Alexander Graf <agraf at suse.de>
Date:   Tue Apr 20 19:37:13 2010 +0200

    target-s390: add firmware code
    
    This patch adds a firmware blob to the S390 target. The blob is a simple
    implementation of a virtio client that tries to read the second stage
    bootloader from sectors described as of offset 0x20 in the MBR.
    
    In combination with an updated zipl this allows for booting from virtio
    block devices. This firmware is built from the same sources as the second
    stage bootloader. You can find a virtio capable s390-tools in this repo:
    
    git://repo.or.cz/s390-tools.git
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/Makefile b/Makefile
index eb9e02b..306a1a4 100644
--- a/Makefile
+++ b/Makefile
@@ -184,7 +184,8 @@ pxe-e1000.bin \
 pxe-ne2k_pci.bin pxe-pcnet.bin \
 pxe-rtl8139.bin pxe-virtio.bin \
 bamboo.dtb petalogix-s3adsp1800.dtb \
-multiboot.bin linuxboot.bin
+multiboot.bin linuxboot.bin \
+s390-zipl.rom
 else
 BLOBS=
 endif
diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c
index c36a8b2..898f442 100644
--- a/hw/s390-virtio.c
+++ b/hw/s390-virtio.c
@@ -52,6 +52,10 @@
 #define INITRD_PARM_SIZE                0x010410UL
 #define PARMFILE_START                  0x001000UL
 
+#define ZIPL_START			0x009000UL
+#define ZIPL_LOAD_ADDR			0x009000UL
+#define ZIPL_FILENAME			"s390-zipl.rom"
+
 #define MAX_BLK_DEVS                    10
 
 static VirtIOS390Bus *s390_bus;
@@ -188,6 +192,28 @@ static void s390_init(ram_addr_t ram_size,
 
         env->psw.addr = KERN_IMAGE_START;
         env->psw.mask = 0x0000000180000000ULL;
+    } else {
+        ram_addr_t bios_size = 0;
+        char *bios_filename;
+
+        /* Load zipl bootloader */
+        if (bios_name == NULL) {
+            bios_name = ZIPL_FILENAME;
+        }
+
+        bios_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+        bios_size = load_image(bios_filename, qemu_get_ram_ptr(ZIPL_LOAD_ADDR));
+
+        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");
+        }
+
+        env->psw.addr = ZIPL_START;
+        env->psw.mask = 0x0000000180000000ULL;
     }
 
     if (initrd_filename) {
diff --git a/pc-bios/README b/pc-bios/README
index fc940a7..e62b4cd 100644
--- a/pc-bios/README
+++ b/pc-bios/README
@@ -27,3 +27,7 @@
   virtio 1af4:1000
 
   http://rom-o-matic.net/
+
+- The S390 zipl loader is an addition to the official IBM s390-tools
+  package. That fork is maintained in its own git repository at:
+  git://repo.or.cz/s390-tools.git
diff --git a/pc-bios/s390-zipl.rom b/pc-bios/s390-zipl.rom
new file mode 100644
index 0000000..f7af9b1
Binary files /dev/null and b/pc-bios/s390-zipl.rom differ
commit c821c2bd4f5fcd3e91e3cd1e2bef76a408677425
Author: Alexander Graf <agraf at suse.de>
Date:   Sun Apr 18 23:10:17 2010 +0200

    PPC/KVM: make iothread work
    
    When running with --enable-io-thread the timer we have doesn't help,
    because it doesn't wake up the CPU thread. So instead we need to
    actually kick it.
    
    While at it I refined the logic a bit to not dumbly trigger a timer
    every 500ms, but rather do it more often after an interrupt got injected.
    If there's no level based interrupt to be expected, we don't need the
    timer anyways.
    
    This makes qemu-system-ppc with --enable-io-thread work when using KVM.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 2625cb8..1079ce1 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -37,20 +37,20 @@
     do { } while (0)
 #endif
 
-/* XXX For some odd reason we sometimes hang inside KVM forever. I'd guess it's
- *     a race condition where we actually have a level triggered interrupt, but
- *     the infrastructure can't expose that yet, so the guest ACKs it, goes to
- *     sleep and never gets notified that there's still an interrupt pending.
+/* 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
+ *     takes but ignores it, goes to sleep and never gets notified that there's
+ *     still an interrupt pending.
  *
- *     As a quick workaround, let's just wake up every 500 ms. That way we can
- *     assure that we're always reinjecting interrupts in time.
+ *     As a quick workaround, let's just wake up again 20 ms after we injected
+ *     an interrupt. That way we can assure that we're always reinjecting
+ *     interrupts in case the guest swallowed them.
  */
 static QEMUTimer *idle_timer;
 
-static void do_nothing(void *opaque)
+static void kvm_kick_env(void *env)
 {
-    qemu_mod_timer(idle_timer, qemu_get_clock(vm_clock) +
-                   (get_ticks_per_sec() / 2));
+    qemu_cpu_kick(env);
 }
 
 int kvm_arch_init(KVMState *s, int smp_cpus)
@@ -66,6 +66,8 @@ int kvm_arch_init_vcpu(CPUState *cenv)
     sregs.pvr = cenv->spr[SPR_PVR];
     ret = kvm_vcpu_ioctl(cenv, KVM_SET_SREGS, &sregs);
 
+    idle_timer = qemu_new_timer(vm_clock, kvm_kick_env, cenv);
+
     return ret;
 }
 
@@ -189,12 +191,6 @@ int kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
     int r;
     unsigned irq;
 
-    if (!idle_timer) {
-        idle_timer = qemu_new_timer(vm_clock, do_nothing, NULL);
-        qemu_mod_timer(idle_timer, qemu_get_clock(vm_clock) +
-                       (get_ticks_per_sec() / 2));
-    }
-
     /* PowerPC Qemu tracks the various core input pins (interrupt, critical
      * interrupt, reset, etc) in PPC-specific env->irq_input_state. */
     if (run->ready_for_interrupt_injection &&
@@ -211,6 +207,10 @@ int kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
         r = kvm_vcpu_ioctl(env, KVM_INTERRUPT, &irq);
         if (r < 0)
             printf("cpu %d fail inject %x\n", env->cpu_index, irq);
+
+        /* Always wake up soon in case the interrupt was level based */
+        qemu_mod_timer(idle_timer, qemu_get_clock(vm_clock) +
+                       (get_ticks_per_sec() / 50));
     }
 
     /* We don't know if there are more interrupts pending after this. However,
commit a5829fd9e6e49016188efd17a6bb34e80f50cd4c
Author: TeLeMan <geleman at gmail.com>
Date:   Thu Apr 15 12:37:55 2010 +0800

    fix chardev_init for win32
    
    chardev_init functions use socket,so socket_init() shoud be placed at
    the front of chardev_init on win32.
    
    Signed-off-by: TeLeMan <geleman at gmail.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/vl.c b/vl.c
index 85bcc84..d77b47c 100644
--- a/vl.c
+++ b/vl.c
@@ -3509,6 +3509,8 @@ int main(int argc, char **argv, char **envp)
     if (default_vga)
         vga_interface_type = VGA_CIRRUS;
 
+    socket_init();
+
     if (qemu_opts_foreach(&qemu_chardev_opts, chardev_init_func, NULL, 1) != 0)
         exit(1);
 #ifdef CONFIG_LINUX
@@ -3617,8 +3619,6 @@ int main(int argc, char **argv, char **envp)
     }
     configure_icount(icount_option);
 
-    socket_init();
-
     if (net_init_clients() < 0) {
         exit(1);
     }
commit e23a22e620e84f42bdbd473b82672654e7c8de73
Author: Jens Osterkamp <jens at linux.vnet.ibm.com>
Date:   Mon Apr 12 10:51:01 2010 +0200

    qemu-sockets: avoid strlen of NULL pointer
    
    If the user wants to create a chardev of type socket but forgets to give a
    host= option, qemu_opt_get returns NULL. This NULL pointer is then fed into
    strlen a few lines below without a check which results in a segfault.
    This fixes it.
    
    Signed-off-by: Jens Osterkamp <jens at linux.vnet.ibm.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/qemu-sockets.c b/qemu-sockets.c
index a7399aa..c526324 100644
--- a/qemu-sockets.c
+++ b/qemu-sockets.c
@@ -130,7 +130,8 @@ int inet_listen_opts(QemuOpts *opts, int port_offset)
     ai.ai_family = PF_UNSPEC;
     ai.ai_socktype = SOCK_STREAM;
 
-    if (qemu_opt_get(opts, "port") == NULL) {
+    if ((qemu_opt_get(opts, "host") == NULL) ||
+        (qemu_opt_get(opts, "port") == NULL)) {
         fprintf(stderr, "%s: host and/or port not specified\n", __FUNCTION__);
         return -1;
     }
commit 81bbe906c89b6b7af58a1eeb96ec5a0bfdc3386f
Author: takasi-y at ops.dti.ne.jp <takasi-y at ops.dti.ne.jp>
Date:   Mon Apr 12 04:07:35 2010 +0900

    linux-user: rlimit conversion between host and target.
    
    rlim_t conversion between host and target added.
    Otherwise there are some incorrect case like
    - RLIM_INFINITY on 32bit target -> 64bit host.
    - RLIM_INFINITY on 64bit host -> mips and sparc target ?
    - Big value(for 32bit target) on 64bit host -> 32bit target.
    
    One is added into getrlimit, setrlimit, and ugetrlimit. It converts both
    RLIM_INFINITY and value bigger than target can hold(>31bit) to RLIM_INFINITY.
    
    Another one is added to guest_stack_size calculation introduced by
    703e0e89. The rule is mostly same except the result on the case is keeping
    the value of guest_stack_size.
    
    Slightly tested for SH4, and x86_64 -linux-user on x86_64-pc-linux host.
    
    Signed-off-by: Takashi YOSHII <takasi-y at ops.dti.ne.jp>
    Acked-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/linux-user/main.c b/linux-user/main.c
index 18b52c0..99a7cde 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2706,7 +2706,8 @@ int main(int argc, char **argv, char **envp)
     {
         struct rlimit lim;
         if (getrlimit(RLIMIT_STACK, &lim) == 0
-            && lim.rlim_cur != RLIM_INFINITY) {
+            && lim.rlim_cur != RLIM_INFINITY
+            && lim.rlim_cur == (target_long)lim.rlim_cur) {
             guest_stack_size = lim.rlim_cur;
         }
     }
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 17599eb..ce728fa 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -831,6 +831,22 @@ static inline abi_long host_to_target_rusage(abi_ulong target_addr,
     return 0;
 }
 
+static inline rlim_t target_to_host_rlim(target_ulong target_rlim)
+{
+    if (target_rlim == TARGET_RLIM_INFINITY)
+        return RLIM_INFINITY;
+    else
+        return tswapl(target_rlim);
+}
+
+static inline target_ulong host_to_target_rlim(rlim_t rlim)
+{
+    if (rlim == RLIM_INFINITY || rlim != (target_long)rlim)
+        return TARGET_RLIM_INFINITY;
+    else
+        return tswapl(rlim);
+}
+
 static inline abi_long copy_from_user_timeval(struct timeval *tv,
                                               abi_ulong target_tv_addr)
 {
@@ -5124,21 +5140,19 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         break;
     case TARGET_NR_setrlimit:
         {
-            /* XXX: convert resource ? */
             int resource = arg1;
             struct target_rlimit *target_rlim;
             struct rlimit rlim;
             if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
                 goto efault;
-            rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
-            rlim.rlim_max = tswapl(target_rlim->rlim_max);
+            rlim.rlim_cur = target_to_host_rlim(target_rlim->rlim_cur);
+            rlim.rlim_max = target_to_host_rlim(target_rlim->rlim_max);
             unlock_user_struct(target_rlim, arg2, 0);
             ret = get_errno(setrlimit(resource, &rlim));
         }
         break;
     case TARGET_NR_getrlimit:
         {
-            /* XXX: convert resource ? */
             int resource = arg1;
             struct target_rlimit *target_rlim;
             struct rlimit rlim;
@@ -5147,8 +5161,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             if (!is_error(ret)) {
                 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
                     goto efault;
-                target_rlim->rlim_cur = tswapl(rlim.rlim_cur);
-                target_rlim->rlim_max = tswapl(rlim.rlim_max);
+                target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
+                target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
                 unlock_user_struct(target_rlim, arg2, 1);
             }
         }
@@ -6233,8 +6247,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 	    struct target_rlimit *target_rlim;
             if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
                 goto efault;
-	    target_rlim->rlim_cur = tswapl(rlim.rlim_cur);
-	    target_rlim->rlim_max = tswapl(rlim.rlim_max);
+	    target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
+	    target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
             unlock_user_struct(target_rlim, arg2, 1);
 	}
 	break;
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 63c2bc3..255e89c 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -669,6 +669,14 @@ struct target_rlimit {
         abi_ulong   rlim_max;
 };
 
+#if defined(TARGET_ALPHA)
+#define TARGET_RLIM_INFINITY	0x7ffffffffffffffful
+#elif defined(TARGET_MIPS) || defined(TARGET_SPARC)
+#define TARGET_RLIM_INFINITY	0x7fffffffUL
+#else
+#define TARGET_RLIM_INFINITY	((target_ulong)~0UL)
+#endif
+
 struct target_pollfd {
     int fd;           /* file descriptor */
     short events;     /* requested events */
commit c69ea0dff27ccc6663f8ecb4a70f762f4559672c
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Mon May 17 19:32:37 2010 +0000

    Compile acpi_piix4, apm and pm_smbus only once
    
    12 compilations less for the full build.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.objs b/Makefile.objs
index 110f8fd..acbaf22 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -153,7 +153,8 @@ hw-obj-$(CONFIG_I8254) += i8254.o
 hw-obj-$(CONFIG_PCSPK) += pcspk.o
 hw-obj-$(CONFIG_USB_UHCI) += usb-uhci.o
 hw-obj-$(CONFIG_FDC) += fdc.o
-hw-obj-$(CONFIG_ACPI) += acpi.o
+hw-obj-$(CONFIG_ACPI) += acpi.o acpi_piix4.o
+hw-obj-$(CONFIG_APM) += pm_smbus.o apm.o
 
 # PPC devices
 hw-obj-$(CONFIG_OPENPIC) += openpic.o
diff --git a/Makefile.target b/Makefile.target
index f2cd4ff..a22484e 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -195,7 +195,7 @@ obj-i386-y += cirrus_vga.o apic.o ioapic.o piix_pci.o
 obj-i386-y += vmmouse.o vmport.o hpet.o
 obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
 obj-i386-y += debugcon.o multiboot.o
-obj-i386-y += pm_smbus.o apm.o acpi_piix4.o pc_piix.o
+obj-i386-y += pc_piix.o
 
 # shared objects
 obj-ppc-y = ppc.o
@@ -221,7 +221,6 @@ obj-mips-y += dma.o vga.o i8259.o
 obj-mips-y += g364fb.o jazz_led.o
 obj-mips-y += gt64xxx.o pckbd.o mc146818rtc.o
 obj-mips-y += piix4.o cirrus_vga.o
-obj-mips-y += pm_smbus.o apm.o acpi_piix4.o
 
 obj-microblaze-y = petalogix_s3adsp1800_mmu.o
 
diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
index 4c1495f..4fbd8aa 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -11,6 +11,7 @@ CONFIG_PCSPK=y
 CONFIG_USB_UHCI=y
 CONFIG_FDC=y
 CONFIG_ACPI=y
+CONFIG_APM=y
 CONFIG_IDE_CORE=y
 CONFIG_IDE_QDEV=y
 CONFIG_IDE_PCI=y
diff --git a/default-configs/mips-softmmu.mak b/default-configs/mips-softmmu.mak
index 7793dbc..fd6fbc1 100644
--- a/default-configs/mips-softmmu.mak
+++ b/default-configs/mips-softmmu.mak
@@ -13,6 +13,7 @@ CONFIG_PCSPK=y
 CONFIG_USB_UHCI=y
 CONFIG_FDC=y
 CONFIG_ACPI=y
+CONFIG_APM=y
 CONFIG_IDE_CORE=y
 CONFIG_IDE_QDEV=y
 CONFIG_IDE_PCI=y
diff --git a/default-configs/mips64-softmmu.mak b/default-configs/mips64-softmmu.mak
index aa65d92..dfd30db 100644
--- a/default-configs/mips64-softmmu.mak
+++ b/default-configs/mips64-softmmu.mak
@@ -13,6 +13,7 @@ CONFIG_PCSPK=y
 CONFIG_USB_UHCI=y
 CONFIG_FDC=y
 CONFIG_ACPI=y
+CONFIG_APM=y
 CONFIG_IDE_CORE=y
 CONFIG_IDE_QDEV=y
 CONFIG_IDE_PCI=y
diff --git a/default-configs/mips64el-softmmu.mak b/default-configs/mips64el-softmmu.mak
index b9b8c71..6fa54a3 100644
--- a/default-configs/mips64el-softmmu.mak
+++ b/default-configs/mips64el-softmmu.mak
@@ -13,6 +13,7 @@ CONFIG_PCSPK=y
 CONFIG_USB_UHCI=y
 CONFIG_FDC=y
 CONFIG_ACPI=y
+CONFIG_APM=y
 CONFIG_IDE_CORE=y
 CONFIG_IDE_QDEV=y
 CONFIG_IDE_PCI=y
diff --git a/default-configs/mipsel-softmmu.mak b/default-configs/mipsel-softmmu.mak
index e14831e..8203997 100644
--- a/default-configs/mipsel-softmmu.mak
+++ b/default-configs/mipsel-softmmu.mak
@@ -13,6 +13,7 @@ CONFIG_PCSPK=y
 CONFIG_USB_UHCI=y
 CONFIG_FDC=y
 CONFIG_ACPI=y
+CONFIG_APM=y
 CONFIG_IDE_CORE=y
 CONFIG_IDE_QDEV=y
 CONFIG_IDE_PCI=y
diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak
index 6662b94..ffedfdb 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -11,6 +11,7 @@ CONFIG_PCSPK=y
 CONFIG_USB_UHCI=y
 CONFIG_FDC=y
 CONFIG_ACPI=y
+CONFIG_APM=y
 CONFIG_IDE_CORE=y
 CONFIG_IDE_QDEV=y
 CONFIG_IDE_PCI=y
commit 129414184e79e887a4028f153f3b50b92354a6fc
Merge: f7ce728... 35ed5de...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon May 17 13:17:34 2010 -0500

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

commit f7ce72878c05dacc5f52374b69e61d00556a185b
Merge: 21ffd18... 57c3229...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon May 17 12:41:39 2010 -0500

    Merge remote branch 'mst/for_anthony' into staging

commit 35ed5de6be186d46ff3e33554f32151fba0f401f
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed May 12 14:03:02 2010 +0200

    block: Remove special case for vvfat
    
    The special case doesn't really us buy anything. Without it vvfat works more
    consistently as a protocol. We get raw on top of vvfat now, which works just
    as well as using vvfat directly.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index 7822580..bfe46e3 100644
--- a/block.c
+++ b/block.c
@@ -326,11 +326,6 @@ static BlockDriver *find_image_format(const char *filename)
     uint8_t buf[2048];
     BlockDriverState *bs;
 
-    drv = find_protocol(filename);
-    /* no need to test disk image formats for vvfat */
-    if (drv && strcmp(drv->format_name, "vvfat") == 0)
-        return drv;
-
     ret = bdrv_file_open(&bs, filename, 0);
     if (ret < 0)
         return NULL;
commit 21955137eefb30e2137682046ea456f32c059300
Author: Daniel P. Berrange <berrange at redhat.com>
Date:   Thu May 13 06:30:50 2010 -0400

    Fix docs for block stats monitor command
    
    The 'parent' field in the 'query-blockstats' monitor command is
    part of the top level block device QDict, not part of the 2nd
    level 'stats' QDict.
    
    * block.c: Fix docs for 'parent' field in block stats monitor
      command output
    
    Signed-off-by: Daniel P. Berrange <berrange at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index 96ef1b1..7822580 100644
--- a/block.c
+++ b/block.c
@@ -1582,9 +1582,9 @@ static QObject* bdrv_info_stats_bs(BlockDriverState *bs)
  *     - "wr_operations": write operations
  *     - "wr_highest_offset": Highest offset of a sector written since the
  *       BlockDriverState has been opened
- *     - "parent": Contains recursively the statistics of the underlying
- *       protocol (e.g. the host file for a qcow2 image). If there is no
- *       underlying protocol, this field is omitted.
+ * - "parent": A QDict recursively holding the statistics of the underlying
+ *    protocol (e.g. the host file for a qcow2 image). If there is no
+ *    underlying protocol, this field is omitted.
  *
  * Example:
  *
@@ -1593,15 +1593,14 @@ static QObject* bdrv_info_stats_bs(BlockDriverState *bs)
  *                          "wr_bytes": 0,
  *                          "rd_operations": 1,
  *                          "wr_operations": 0,
- *                          "wr_highest_offset": 0,
- *                          "parent": {
- *                              "stats": { "rd_bytes": 1024,
- *                                         "wr_bytes": 0,
- *                                         "rd_operations": 2,
- *                                         "wr_operations": 0,
- *                                         "wr_highest_offset": 0,
- *                              }
- *                          } } },
+ *                          "wr_highest_offset": 0 },
+ *               "parent": {
+ *                      "stats": { "rd_bytes": 1024,
+ *                                 "wr_bytes": 0,
+ *                                 "rd_operations": 2,
+ *                                 "wr_operations": 0,
+ *                                 "wr_highest_offset": 0,
+ *                      } } },
  *   { "device": "ide1-cd0",
  *               "stats": { "rd_bytes": 0,
  *                          "wr_bytes": 0,
commit af474591e5521978194ee099497202c6818f2359
Author: Bruce Rogers <brogers at novell.com>
Date:   Thu May 13 15:14:33 2010 -0600

    use qemu_free() instead of free()
    
    There is a call to free() where qemu_free() should instead be used.
    
    Signed-off-by: Bruce Rogers <brogers at novell.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index c134c2b..96ef1b1 100644
--- a/block.c
+++ b/block.c
@@ -2075,7 +2075,7 @@ int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, int num_reqs)
     return 0;
 
 fail:
-    free(mcb);
+    qemu_free(mcb);
     return -1;
 }
 
commit f21dc3a4652eeb82117d7d55d975278fe1444b26
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Wed May 12 20:25:45 2010 +0200

    block/vdi: Fix image opening and creation for odd disk sizes
    
    The fix is based on a patch from Kevin Wolf. Here his comment:
    
    "The number of blocks needs to be rounded up to cover all of the virtual hard
    disk. Without this fix, we can't even open our own images if their size is not
    a multiple of the block size."
    
    While Kevin's patch addressed vdi_create, my modification also fixes
    vdi_open which now accepts images with odd disk sizes.
    
    v3:
    Don't allow reading of disk images with too large disk sizes.
    Neither VBoxManage nor old versions of qemu-img read such images.
    This change requires rounding of odd disk sizes before we do the checks.
    
    Cc: Kevin Wolf <kwolf at redhat.com>
    Cc: François Revol <revol at free.fr>
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vdi.c b/block/vdi.c
index 3ea4103..ee8cc7b 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -393,6 +393,15 @@ static int vdi_open(BlockDriverState *bs, int flags)
     vdi_header_print(&header);
 #endif
 
+    if (header.disk_size % SECTOR_SIZE != 0) {
+        /* 'VBoxManage convertfromraw' can create images with odd disk sizes.
+           We accept them but round the disk size to the next multiple of
+           SECTOR_SIZE. */
+        logout("odd disk size %" PRIu64 " B, round up\n", header.disk_size);
+        header.disk_size += SECTOR_SIZE - 1;
+        header.disk_size &= ~(SECTOR_SIZE - 1);
+    }
+
     if (header.version != VDI_VERSION_1_1) {
         logout("unsupported version %u.%u\n",
                header.version >> 16, header.version & 0xffff);
@@ -405,18 +414,15 @@ static int vdi_open(BlockDriverState *bs, int flags)
         /* We only support data blocks which start on a sector boundary. */
         logout("unsupported data offset 0x%x B\n", header.offset_data);
         goto fail;
-    } else if (header.disk_size % SECTOR_SIZE != 0) {
-        logout("unsupported disk size %" PRIu64 " B\n", header.disk_size);
-        goto fail;
     } else if (header.sector_size != SECTOR_SIZE) {
         logout("unsupported sector size %u B\n", header.sector_size);
         goto fail;
     } else if (header.block_size != 1 * MiB) {
         logout("unsupported block size %u B\n", header.block_size);
         goto fail;
-    } else if ((header.disk_size + header.block_size - 1) / header.block_size !=
-               (uint64_t)header.blocks_in_image) {
-        logout("unexpected block number %u B\n", header.blocks_in_image);
+    } else if (header.disk_size >
+               (uint64_t)header.blocks_in_image * header.block_size) {
+        logout("unsupported disk size %" PRIu64 " B\n", header.disk_size);
         goto fail;
     } else if (!uuid_is_null(header.uuid_link)) {
         logout("link uuid != 0, unsupported\n");
@@ -829,7 +835,10 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options)
         return -errno;
     }
 
-    blocks = bytes / block_size;
+    /* We need enough blocks to store the given disk size,
+       so always round up. */
+    blocks = (bytes + block_size - 1) / block_size;
+
     bmap_size = blocks * sizeof(uint32_t);
     bmap_size = ((bmap_size + SECTOR_SIZE - 1) & ~(SECTOR_SIZE -1));
 
commit 64a31d5c3d73396a88563d7a504654edc85aa854
Author: Christoph Hellwig <hch at lst.de>
Date:   Wed May 12 16:31:49 2010 +0200

    dmg: use qemu block API
    
    Use bdrv_pwrite to access the backing device instead of pread, and
    convert the driver to implementing the bdrv_open method which gives
    it an already opened BlockDriverState for the underlying device.
    
    Dmg actually does an lseek to a negative offset in the open routine,
    which we replace with offset arithmetics after doing a bdrv_getlength.
    
    Signed-off-by: Christoph Hellwig <hch at lst.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/dmg.c b/block/dmg.c
index a0ba34f..a3c815b 100644
--- a/block/dmg.c
+++ b/block/dmg.c
@@ -28,8 +28,6 @@
 #include <zlib.h>
 
 typedef struct BDRVDMGState {
-    int fd;
-
     /* each chunk contains a certain number of sectors,
      * offsets[i] is the offset in the .dmg file,
      * lengths[i] is the length of the compressed chunk,
@@ -58,23 +56,23 @@ static int dmg_probe(const uint8_t *buf, int buf_size, const char *filename)
     return 0;
 }
 
-static off_t read_off(int fd, int64_t offset)
+static off_t read_off(BlockDriverState *bs, int64_t offset)
 {
 	uint64_t buffer;
-	if (pread(fd, &buffer, 8, offset) < 8)
+	if (bdrv_pread(bs->file, offset, &buffer, 8) < 8)
 		return 0;
 	return be64_to_cpu(buffer);
 }
 
-static off_t read_uint32(int fd, int64_t offset)
+static off_t read_uint32(BlockDriverState *bs, int64_t offset)
 {
 	uint32_t buffer;
-	if (pread(fd, &buffer, 4, offset) < 4)
+	if (bdrv_pread(bs->file, offset, &buffer, 4) < 4)
 		return 0;
 	return be32_to_cpu(buffer);
 }
 
-static int dmg_open(BlockDriverState *bs, const char *filename, int flags)
+static int dmg_open(BlockDriverState *bs, int flags)
 {
     BDRVDMGState *s = bs->opaque;
     off_t info_begin,info_end,last_in_offset,last_out_offset;
@@ -82,29 +80,27 @@ static int dmg_open(BlockDriverState *bs, const char *filename, int flags)
     uint32_t max_compressed_size=1,max_sectors_per_chunk=1,i;
     int64_t offset;
 
-    s->fd = open(filename, O_RDONLY | O_BINARY);
-    if (s->fd < 0)
-        return -errno;
     bs->read_only = 1;
     s->n_chunks = 0;
     s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL;
 
     /* read offset of info blocks */
-    offset = lseek(s->fd, -0x1d8, SEEK_END);
+    offset = bdrv_getlength(bs->file);
     if (offset < 0) {
         goto fail;
     }
+    offset -= 0x1d8;
 
-    info_begin = read_off(s->fd, offset);
+    info_begin = read_off(bs, offset);
     if (info_begin == 0) {
 	goto fail;
     }
 
-    if (read_uint32(s->fd, info_begin) != 0x100) {
+    if (read_uint32(bs, info_begin) != 0x100) {
         goto fail;
     }
 
-    count = read_uint32(s->fd, info_begin + 4);
+    count = read_uint32(bs, info_begin + 4);
     if (count == 0) {
         goto fail;
     }
@@ -117,12 +113,12 @@ static int dmg_open(BlockDriverState *bs, const char *filename, int flags)
     while (offset < info_end) {
         uint32_t type;
 
-	count = read_uint32(s->fd, offset);
+	count = read_uint32(bs, offset);
 	if(count==0)
 	    goto fail;
         offset += 4;
 
-	type = read_uint32(s->fd, offset);
+	type = read_uint32(bs, offset);
 	if (type == 0x6d697368 && count >= 244) {
 	    int new_size, chunk_count;
 
@@ -138,7 +134,7 @@ static int dmg_open(BlockDriverState *bs, const char *filename, int flags)
 	    s->sectorcounts = qemu_realloc(s->sectorcounts, new_size);
 
 	    for(i=s->n_chunks;i<s->n_chunks+chunk_count;i++) {
-		s->types[i] = read_uint32(s->fd, offset);
+		s->types[i] = read_uint32(bs, offset);
 		offset += 4;
 		if(s->types[i]!=0x80000005 && s->types[i]!=1 && s->types[i]!=2) {
 		    if(s->types[i]==0xffffffff) {
@@ -152,16 +148,16 @@ static int dmg_open(BlockDriverState *bs, const char *filename, int flags)
 		}
 		offset += 4;
 
-		s->sectors[i] = last_out_offset+read_off(s->fd, offset);
+		s->sectors[i] = last_out_offset+read_off(bs, offset);
 		offset += 8;
 
-		s->sectorcounts[i] = read_off(s->fd, offset);
+		s->sectorcounts[i] = read_off(bs, offset);
 		offset += 8;
 
-		s->offsets[i] = last_in_offset+read_off(s->fd, offset);
+		s->offsets[i] = last_in_offset+read_off(bs, offset);
 		offset += 8;
 
-		s->lengths[i] = read_off(s->fd, offset);
+		s->lengths[i] = read_off(bs, offset);
 		offset += 8;
 
 		if(s->lengths[i]>max_compressed_size)
@@ -183,7 +179,6 @@ static int dmg_open(BlockDriverState *bs, const char *filename, int flags)
 
     return 0;
 fail:
-    close(s->fd);
     return -1;
 }
 
@@ -213,8 +208,10 @@ static inline uint32_t search_chunk(BDRVDMGState* s,int sector_num)
     return s->n_chunks; /* error */
 }
 
-static inline int dmg_read_chunk(BDRVDMGState *s,int sector_num)
+static inline int dmg_read_chunk(BlockDriverState *bs, int sector_num)
 {
+    BDRVDMGState *s = bs->opaque;
+
     if(!is_sector_in_chunk(s,s->current_chunk,sector_num)) {
 	int ret;
 	uint32_t chunk = search_chunk(s,sector_num);
@@ -231,8 +228,8 @@ static inline int dmg_read_chunk(BDRVDMGState *s,int sector_num)
 	     * inflated. */
 	    i=0;
 	    do {
-		ret = pread(s->fd, s->compressed_chunk+i, s->lengths[chunk]-i,
-                            s->offsets[chunk] + i);
+                ret = bdrv_pread(bs->file, s->offsets[chunk] + i,
+                                 s->compressed_chunk+i, s->lengths[chunk]-i);
 		if(ret<0 && errno==EINTR)
 		    ret=0;
 		i+=ret;
@@ -253,8 +250,8 @@ static inline int dmg_read_chunk(BDRVDMGState *s,int sector_num)
 		return -1;
 	    break; }
 	case 1: /* copy */
-	    ret = pread(s->fd, s->uncompressed_chunk, s->lengths[chunk],
-                        s->offsets[chunk]);
+	    ret = bdrv_pread(bs->file, s->offsets[chunk],
+                             s->uncompressed_chunk, s->lengths[chunk]);
 	    if (ret != s->lengths[chunk])
 		return -1;
 	    break;
@@ -275,7 +272,7 @@ static int dmg_read(BlockDriverState *bs, int64_t sector_num,
 
     for(i=0;i<nb_sectors;i++) {
 	uint32_t sector_offset_in_chunk;
-	if(dmg_read_chunk(s, sector_num+i) != 0)
+	if(dmg_read_chunk(bs, sector_num+i) != 0)
 	    return -1;
 	sector_offset_in_chunk = sector_num+i-s->sectors[s->current_chunk];
 	memcpy(buf+i*512,s->uncompressed_chunk+sector_offset_in_chunk*512,512);
@@ -286,7 +283,6 @@ static int dmg_read(BlockDriverState *bs, int64_t sector_num,
 static void dmg_close(BlockDriverState *bs)
 {
     BDRVDMGState *s = bs->opaque;
-    close(s->fd);
     if(s->n_chunks>0) {
 	free(s->types);
 	free(s->offsets);
@@ -303,7 +299,7 @@ static BlockDriver bdrv_dmg = {
     .format_name	= "dmg",
     .instance_size	= sizeof(BDRVDMGState),
     .bdrv_probe		= dmg_probe,
-    .bdrv_file_open	= dmg_open,
+    .bdrv_open		= dmg_open,
     .bdrv_read		= dmg_read,
     .bdrv_close		= dmg_close,
 };
commit 16cdf7ce1a53dcab75f5206a89bf98bb907a8b9e
Author: Christoph Hellwig <hch at lst.de>
Date:   Wed May 12 16:31:35 2010 +0200

    dmg: use pread
    
    Use pread instead of lseek + read in preparation of using the qemu
    block API.  Note that dmg actually uses the implicit file offset
    a lot in dmg_open, and we had to replace it with an offset variable.
    
    Signed-off-by: Christoph Hellwig <hch at lst.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/dmg.c b/block/dmg.c
index 02a3d67..a0ba34f 100644
--- a/block/dmg.c
+++ b/block/dmg.c
@@ -58,18 +58,18 @@ static int dmg_probe(const uint8_t *buf, int buf_size, const char *filename)
     return 0;
 }
 
-static off_t read_off(int fd)
+static off_t read_off(int fd, int64_t offset)
 {
 	uint64_t buffer;
-	if(read(fd,&buffer,8)<8)
+	if (pread(fd, &buffer, 8, offset) < 8)
 		return 0;
 	return be64_to_cpu(buffer);
 }
 
-static off_t read_uint32(int fd)
+static off_t read_uint32(int fd, int64_t offset)
 {
 	uint32_t buffer;
-	if(read(fd,&buffer,4)<4)
+	if (pread(fd, &buffer, 4, offset) < 4)
 		return 0;
 	return be32_to_cpu(buffer);
 }
@@ -80,6 +80,7 @@ static int dmg_open(BlockDriverState *bs, const char *filename, int flags)
     off_t info_begin,info_end,last_in_offset,last_out_offset;
     uint32_t count;
     uint32_t max_compressed_size=1,max_sectors_per_chunk=1,i;
+    int64_t offset;
 
     s->fd = open(filename, O_RDONLY | O_BINARY);
     if (s->fd < 0)
@@ -89,38 +90,45 @@ static int dmg_open(BlockDriverState *bs, const char *filename, int flags)
     s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL;
 
     /* read offset of info blocks */
-    if(lseek(s->fd,-0x1d8,SEEK_END)<0) {
+    offset = lseek(s->fd, -0x1d8, SEEK_END);
+    if (offset < 0) {
         goto fail;
     }
 
-    info_begin=read_off(s->fd);
-    if(info_begin==0)
-	goto fail;
-    if(lseek(s->fd,info_begin,SEEK_SET)<0)
-	goto fail;
-    if(read_uint32(s->fd)!=0x100)
-	goto fail;
-    if((count = read_uint32(s->fd))==0)
-	goto fail;
-    info_end = info_begin+count;
-    if(lseek(s->fd,0xf8,SEEK_CUR)<0)
+    info_begin = read_off(s->fd, offset);
+    if (info_begin == 0) {
 	goto fail;
+    }
+
+    if (read_uint32(s->fd, info_begin) != 0x100) {
+        goto fail;
+    }
+
+    count = read_uint32(s->fd, info_begin + 4);
+    if (count == 0) {
+        goto fail;
+    }
+    info_end = info_begin + count;
+
+    offset = info_begin + 0x100;
 
     /* read offsets */
     last_in_offset = last_out_offset = 0;
-    while(lseek(s->fd,0,SEEK_CUR)<info_end) {
+    while (offset < info_end) {
         uint32_t type;
 
-	count = read_uint32(s->fd);
+	count = read_uint32(s->fd, offset);
 	if(count==0)
 	    goto fail;
-	type = read_uint32(s->fd);
-	if(type!=0x6d697368 || count<244)
-	    lseek(s->fd,count-4,SEEK_CUR);
-	else {
+        offset += 4;
+
+	type = read_uint32(s->fd, offset);
+	if (type == 0x6d697368 && count >= 244) {
 	    int new_size, chunk_count;
-	    if(lseek(s->fd,200,SEEK_CUR)<0)
-	        goto fail;
+
+            offset += 4;
+            offset += 200;
+
 	    chunk_count = (count-204)/40;
 	    new_size = sizeof(uint64_t) * (s->n_chunks + chunk_count);
 	    s->types = qemu_realloc(s->types, new_size/2);
@@ -130,7 +138,8 @@ static int dmg_open(BlockDriverState *bs, const char *filename, int flags)
 	    s->sectorcounts = qemu_realloc(s->sectorcounts, new_size);
 
 	    for(i=s->n_chunks;i<s->n_chunks+chunk_count;i++) {
-		s->types[i] = read_uint32(s->fd);
+		s->types[i] = read_uint32(s->fd, offset);
+		offset += 4;
 		if(s->types[i]!=0x80000005 && s->types[i]!=1 && s->types[i]!=2) {
 		    if(s->types[i]==0xffffffff) {
 			last_in_offset = s->offsets[i-1]+s->lengths[i-1];
@@ -138,15 +147,23 @@ static int dmg_open(BlockDriverState *bs, const char *filename, int flags)
 		    }
 		    chunk_count--;
 		    i--;
-		    if(lseek(s->fd,36,SEEK_CUR)<0)
-			goto fail;
+		    offset += 36;
 		    continue;
 		}
-		read_uint32(s->fd);
-		s->sectors[i] = last_out_offset+read_off(s->fd);
-		s->sectorcounts[i] = read_off(s->fd);
-		s->offsets[i] = last_in_offset+read_off(s->fd);
-		s->lengths[i] = read_off(s->fd);
+		offset += 4;
+
+		s->sectors[i] = last_out_offset+read_off(s->fd, offset);
+		offset += 8;
+
+		s->sectorcounts[i] = read_off(s->fd, offset);
+		offset += 8;
+
+		s->offsets[i] = last_in_offset+read_off(s->fd, offset);
+		offset += 8;
+
+		s->lengths[i] = read_off(s->fd, offset);
+		offset += 8;
+
 		if(s->lengths[i]>max_compressed_size)
 		    max_compressed_size = s->lengths[i];
 		if(s->sectorcounts[i]>max_sectors_per_chunk)
@@ -210,15 +227,12 @@ static inline int dmg_read_chunk(BDRVDMGState *s,int sector_num)
 	case 0x80000005: { /* zlib compressed */
 	    int i;
 
-	    ret = lseek(s->fd, s->offsets[chunk], SEEK_SET);
-	    if(ret<0)
-		return -1;
-
 	    /* we need to buffer, because only the chunk as whole can be
 	     * inflated. */
 	    i=0;
 	    do {
-		ret = read(s->fd, s->compressed_chunk+i, s->lengths[chunk]-i);
+		ret = pread(s->fd, s->compressed_chunk+i, s->lengths[chunk]-i,
+                            s->offsets[chunk] + i);
 		if(ret<0 && errno==EINTR)
 		    ret=0;
 		i+=ret;
commit cd02a24b6112da50816a8021d97a2b26038f7190
Author: Christoph Hellwig <hch at lst.de>
Date:   Fri May 7 16:55:33 2010 +0200

    dmg: fix reading of uncompressed chunks
    
    When dmg_read_chunk encounters an uncompressed chunk it currently
    calls read without any previous adjustment of the file postion.
    
    This seems very wrong, and the "reference" implementation in
    dmg2img does a search to the same offset as done in the various
    compression cases, so do the same here.
    
    Signed-off-by: Christoph Hellwig <hch at lst.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/dmg.c b/block/dmg.c
index d5c1a68..02a3d67 100644
--- a/block/dmg.c
+++ b/block/dmg.c
@@ -239,7 +239,8 @@ static inline int dmg_read_chunk(BDRVDMGState *s,int sector_num)
 		return -1;
 	    break; }
 	case 1: /* copy */
-	    ret = read(s->fd, s->uncompressed_chunk, s->lengths[chunk]);
+	    ret = pread(s->fd, s->uncompressed_chunk, s->lengths[chunk],
+                        s->offsets[chunk]);
 	    if (ret != s->lengths[chunk])
 		return -1;
 	    break;
commit dede4188cc817a039154ed2ecd7f3285f6b94056
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Mon May 10 21:46:26 2010 +0200

    block/vpc: Fix conversion from size to disk geometry
    
    The VHD algorithm calculates a disk geometry
    which is usually smaller than the requested size.
    
    QEMU tried to round up but failed for certain sizes:
    
    qemu-img create -f vpc disk.vpc 9437184
    would create an image with 9435136 bytes
    (which is too small for qemu-img convert).
    
    Instead of hacking the geometry algorithm, the patch
    increases the number of sectors until we get enough
    sectors.
    
    Cc: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vpc.c b/block/vpc.c
index f94e469..214e9d1 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -463,9 +463,7 @@ static int calculate_geometry(int64_t total_sectors, uint16_t* cyls,
         }
     }
 
-    // Note: Rounding up deviates from the Virtual PC behaviour
-    // However, we need this to avoid truncating images in qemu-img convert
-    *cyls = (cyls_times_heads + *heads - 1) / *heads;
+    *cyls = cyls_times_heads / *heads;
 
     return 0;
 }
@@ -477,9 +475,9 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options)
     struct vhd_dyndisk_header* dyndisk_header =
         (struct vhd_dyndisk_header*) buf;
     int fd, i;
-    uint16_t cyls;
-    uint8_t heads;
-    uint8_t secs_per_cyl;
+    uint16_t cyls = 0;
+    uint8_t heads = 0;
+    uint8_t secs_per_cyl = 0;
     size_t block_size, num_bat_entries;
     int64_t total_sectors = 0;
 
@@ -496,9 +494,14 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options)
     if (fd < 0)
         return -EIO;
 
-    // Calculate matching total_size and geometry
-    if (calculate_geometry(total_sectors, &cyls, &heads, &secs_per_cyl))
-        return -EFBIG;
+    /* Calculate matching total_size and geometry. Increase the number of
+       sectors requested until we get enough (or fail). */
+    for (i = 0; total_sectors > (int64_t)cyls * heads * secs_per_cyl; i++) {
+        if (calculate_geometry(total_sectors + i,
+                               &cyls, &heads, &secs_per_cyl)) {
+            return -EFBIG;
+        }
+    }
     total_sectors = (int64_t) cyls * heads * secs_per_cyl;
 
     // Prepare the Hard Disk Footer
commit 1dec5a70973bde6138d7cf30e98e12a49397abf4
Author: Christoph Hellwig <hch at lst.de>
Date:   Thu May 6 22:04:50 2010 +0200

    parallels: use qemu block API
    
    Use bdrv_pwrite to access the backing device instead of pread, and
    convert the driver to implementing the bdrv_open method which gives
    it an already opened BlockDriverState for the underlying device.
    
    Signed-off-by: Christoph Hellwig <hch at lst.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/parallels.c b/block/parallels.c
index efb6d4d..35a14aa 100644
--- a/block/parallels.c
+++ b/block/parallels.c
@@ -46,7 +46,6 @@ struct parallels_header {
 } __attribute__((packed));
 
 typedef struct BDRVParallelsState {
-    int fd;
 
     uint32_t *catalog_bitmap;
     int catalog_size;
@@ -68,22 +67,15 @@ static int parallels_probe(const uint8_t *buf, int buf_size, const char *filenam
     return 0;
 }
 
-static int parallels_open(BlockDriverState *bs, const char *filename, int flags)
+static int parallels_open(BlockDriverState *bs, int flags)
 {
     BDRVParallelsState *s = bs->opaque;
-    int fd, i;
+    int i;
     struct parallels_header ph;
 
-    fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
-    if (fd < 0) {
-        return -1;
-    }
-
     bs->read_only = 1; // no write support yet
 
-    s->fd = fd;
-
-    if (pread(fd, &ph, sizeof(ph), 0) != sizeof(ph))
+    if (bdrv_pread(bs->file, 0, &ph, sizeof(ph)) != sizeof(ph))
         goto fail;
 
     if (memcmp(ph.magic, HEADER_MAGIC, 16) ||
@@ -97,7 +89,7 @@ static int parallels_open(BlockDriverState *bs, const char *filename, int flags)
 
     s->catalog_size = le32_to_cpu(ph.catalog_entries);
     s->catalog_bitmap = qemu_malloc(s->catalog_size * 4);
-    if (pread(s->fd, s->catalog_bitmap, s->catalog_size * 4, 64) !=
+    if (bdrv_pread(bs->file, 64, s->catalog_bitmap, s->catalog_size * 4) !=
 	s->catalog_size * 4)
 	goto fail;
     for (i = 0; i < s->catalog_size; i++)
@@ -107,7 +99,6 @@ static int parallels_open(BlockDriverState *bs, const char *filename, int flags)
 fail:
     if (s->catalog_bitmap)
 	qemu_free(s->catalog_bitmap);
-    close(fd);
     return -1;
 }
 
@@ -128,12 +119,10 @@ static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num)
 static int parallels_read(BlockDriverState *bs, int64_t sector_num,
                     uint8_t *buf, int nb_sectors)
 {
-    BDRVParallelsState *s = bs->opaque;
-
     while (nb_sectors > 0) {
         int64_t position = seek_to_sector(bs, sector_num);
         if (position >= 0) {
-            if (pread(s->fd, buf, 512, position) != 512)
+            if (bdrv_pread(bs->file, position, buf, 512) != 512)
                 return -1;
         } else {
             memset(buf, 0, 512);
@@ -149,14 +138,13 @@ static void parallels_close(BlockDriverState *bs)
 {
     BDRVParallelsState *s = bs->opaque;
     qemu_free(s->catalog_bitmap);
-    close(s->fd);
 }
 
 static BlockDriver bdrv_parallels = {
     .format_name	= "parallels",
     .instance_size	= sizeof(BDRVParallelsState),
     .bdrv_probe		= parallels_probe,
-    .bdrv_file_open	= parallels_open,
+    .bdrv_open		= parallels_open,
     .bdrv_read		= parallels_read,
     .bdrv_close		= parallels_close,
 };
commit 9d8b88f68c4f55e4f706408b39f720e1a7486da1
Author: Christoph Hellwig <hch at lst.de>
Date:   Thu May 6 22:04:34 2010 +0200

    parallels: use pread
    
    Use pread instead of lseek + read in preparation of using the qemu
    block API.
    
    Signed-off-by: Christoph Hellwig <hch at lst.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/parallels.c b/block/parallels.c
index b217101..efb6d4d 100644
--- a/block/parallels.c
+++ b/block/parallels.c
@@ -83,7 +83,7 @@ static int parallels_open(BlockDriverState *bs, const char *filename, int flags)
 
     s->fd = fd;
 
-    if (read(fd, &ph, sizeof(ph)) != sizeof(ph))
+    if (pread(fd, &ph, sizeof(ph), 0) != sizeof(ph))
         goto fail;
 
     if (memcmp(ph.magic, HEADER_MAGIC, 16) ||
@@ -93,14 +93,11 @@ static int parallels_open(BlockDriverState *bs, const char *filename, int flags)
 
     bs->total_sectors = le32_to_cpu(ph.nb_sectors);
 
-    if (lseek(s->fd, 64, SEEK_SET) != 64)
-	goto fail;
-
     s->tracks = le32_to_cpu(ph.tracks);
 
     s->catalog_size = le32_to_cpu(ph.catalog_entries);
     s->catalog_bitmap = qemu_malloc(s->catalog_size * 4);
-    if (read(s->fd, s->catalog_bitmap, s->catalog_size * 4) !=
+    if (pread(s->fd, s->catalog_bitmap, s->catalog_size * 4, 64) !=
 	s->catalog_size * 4)
 	goto fail;
     for (i = 0; i < s->catalog_size; i++)
@@ -114,28 +111,18 @@ fail:
     return -1;
 }
 
-static inline int seek_to_sector(BlockDriverState *bs, int64_t sector_num)
+static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num)
 {
     BDRVParallelsState *s = bs->opaque;
     uint32_t index, offset;
-    uint64_t position;
 
     index = sector_num / s->tracks;
     offset = sector_num % s->tracks;
 
-    // not allocated
+    /* not allocated */
     if ((index > s->catalog_size) || (s->catalog_bitmap[index] == 0))
 	return -1;
-
-    position = (uint64_t)(s->catalog_bitmap[index] + offset) * 512;
-
-//    fprintf(stderr, "sector: %llx index=%x offset=%x pointer=%x position=%x\n",
-//	sector_num, index, offset, s->catalog_bitmap[index], position);
-
-    if (lseek(s->fd, position, SEEK_SET) != position)
-	return -1;
-
-    return 0;
+    return (uint64_t)(s->catalog_bitmap[index] + offset) * 512;
 }
 
 static int parallels_read(BlockDriverState *bs, int64_t sector_num,
@@ -144,11 +131,13 @@ static int parallels_read(BlockDriverState *bs, int64_t sector_num,
     BDRVParallelsState *s = bs->opaque;
 
     while (nb_sectors > 0) {
-	if (!seek_to_sector(bs, sector_num)) {
-	    if (read(s->fd, buf, 512) != 512)
-		return -1;
-	} else
+        int64_t position = seek_to_sector(bs, sector_num);
+        if (position >= 0) {
+            if (pread(s->fd, buf, 512, position) != 512)
+                return -1;
+        } else {
             memset(buf, 0, 512);
+        }
         nb_sectors--;
         sector_num++;
         buf += 512;
commit b76b6e95b8edb1284ff41c75f6b5145cc79d09df
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Thu May 6 20:53:47 2010 +0200

    block/vdi: Allow disk images of size 0
    
    Even it is not very useful, users may create images of size 0.
    
    Without the special option CONFIG_ZERO_MALLOC, qemu_mallocz
    aborts execution when it is told to allocate 0 bytes,
    so avoid this kind of call.
    
    Cc: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vdi.c b/block/vdi.c
index 2b4d2c2..3ea4103 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -435,7 +435,9 @@ static int vdi_open(BlockDriverState *bs, int flags)
 
     bmap_size = header.blocks_in_image * sizeof(uint32_t);
     bmap_size = (bmap_size + SECTOR_SIZE - 1) / SECTOR_SIZE;
-    s->bmap = qemu_malloc(bmap_size * SECTOR_SIZE);
+    if (bmap_size > 0) {
+        s->bmap = qemu_malloc(bmap_size * SECTOR_SIZE);
+    }
     if (bdrv_read(bs->file, s->bmap_sector, (uint8_t *)s->bmap, bmap_size) < 0) {
         goto fail_free_bmap;
     }
@@ -857,7 +859,10 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options)
         result = -errno;
     }
 
-    bmap = (uint32_t *)qemu_mallocz(bmap_size);
+    bmap = NULL;
+    if (bmap_size > 0) {
+        bmap = (uint32_t *)qemu_mallocz(bmap_size);
+    }
     for (i = 0; i < blocks; i++) {
         if (image_type == VDI_TYPE_STATIC) {
             bmap[i] = i;
commit c33491978c5c4c746cc0272d5f2df50aa14d1f02
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Thu May 6 16:34:56 2010 +0200

    block: Fix bdrv_commit
    
    When reopening the image, don't guess the driver, but use the same driver as
    was used before. This is important if the format=... option was used for that
    image.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index 977d01f..c134c2b 100644
--- a/block.c
+++ b/block.c
@@ -701,12 +701,12 @@ int bdrv_commit(BlockDriverState *bs)
         bdrv_delete(bs->backing_hd);
         bs->backing_hd = NULL;
         bs_rw = bdrv_new("");
-        rw_ret = bdrv_open(bs_rw, filename, open_flags | BDRV_O_RDWR, NULL);
+        rw_ret = bdrv_open(bs_rw, filename, open_flags | BDRV_O_RDWR, drv);
         if (rw_ret < 0) {
             bdrv_delete(bs_rw);
             /* try to re-open read-only */
             bs_ro = bdrv_new("");
-            ret = bdrv_open(bs_ro, filename, open_flags & ~BDRV_O_RDWR, NULL);
+            ret = bdrv_open(bs_ro, filename, open_flags & ~BDRV_O_RDWR, drv);
             if (ret < 0) {
                 bdrv_delete(bs_ro);
                 /* drive not functional anymore */
@@ -758,7 +758,7 @@ ro_cleanup:
         bdrv_delete(bs->backing_hd);
         bs->backing_hd = NULL;
         bs_ro = bdrv_new("");
-        ret = bdrv_open(bs_ro, filename, open_flags & ~BDRV_O_RDWR, NULL);
+        ret = bdrv_open(bs_ro, filename, open_flags & ~BDRV_O_RDWR, drv);
         if (ret < 0) {
             bdrv_delete(bs_ro);
             /* drive not functional anymore */
commit 209930818bc0bb1400fbfa7d6448066c1b9e7b4c
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Thu May 6 13:04:58 2010 +0200

    block: Fix protocol detection for Windows devices
    
    We can't assume the file protocol for Windows devices, they need the same
    detection as other files for which an explicit protocol is not specified.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index 6345599..977d01f 100644
--- a/block.c
+++ b/block.c
@@ -287,16 +287,18 @@ static BlockDriver *find_protocol(const char *filename)
     char protocol[128];
     int len;
     const char *p;
+    int is_drive;
 
     /* TODO Drivers without bdrv_file_open must be specified explicitly */
 
 #ifdef _WIN32
-    if (is_windows_drive(filename) ||
-        is_windows_drive_prefix(filename))
-        return bdrv_find_format("file");
+    is_drive = is_windows_drive(filename) ||
+        is_windows_drive_prefix(filename);
+#else
+    is_drive = 0;
 #endif
     p = strchr(filename, ':');
-    if (!p) {
+    if (!p || is_drive) {
         drv1 = find_hdev_driver(filename);
         if (!drv1) {
             drv1 = bdrv_find_format("file");
commit b666d239509a0855740444c254a65cbf567bfb90
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed May 5 11:44:39 2010 +0200

    block: Avoid unchecked casts for AIOCBs
    
    Use container_of for one direction and &acb->common for the other one.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index 48305b7..6345599 100644
--- a/block.c
+++ b/block.c
@@ -2108,7 +2108,8 @@ typedef struct BlockDriverAIOCBSync {
 
 static void bdrv_aio_cancel_em(BlockDriverAIOCB *blockacb)
 {
-    BlockDriverAIOCBSync *acb = (BlockDriverAIOCBSync *)blockacb;
+    BlockDriverAIOCBSync *acb =
+        container_of(blockacb, BlockDriverAIOCBSync, common);
     qemu_bh_delete(acb->bh);
     acb->bh = NULL;
     qemu_aio_release(acb);
diff --git a/block/blkdebug.c b/block/blkdebug.c
index bb4a91a..8325f75 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -320,7 +320,7 @@ static void error_callback_bh(void *opaque)
 
 static void blkdebug_aio_cancel(BlockDriverAIOCB *blockacb)
 {
-    BlkdebugAIOCB *acb = (BlkdebugAIOCB*) blockacb;
+    BlkdebugAIOCB *acb = container_of(blockacb, BlkdebugAIOCB, common);
     qemu_aio_release(acb);
 }
 
@@ -347,7 +347,7 @@ static BlockDriverAIOCB *inject_error(BlockDriverState *bs,
     acb->bh = bh;
     qemu_bh_schedule(bh);
 
-    return (BlockDriverAIOCB*) acb;
+    return &acb->common;
 }
 
 static BlockDriverAIOCB *blkdebug_aio_readv(BlockDriverState *bs,
diff --git a/block/qcow.c b/block/qcow.c
index 2883c40..449858f 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -502,7 +502,7 @@ typedef struct QCowAIOCB {
 
 static void qcow_aio_cancel(BlockDriverAIOCB *blockacb)
 {
-    QCowAIOCB *acb = (QCowAIOCB *)blockacb;
+    QCowAIOCB *acb = container_of(blockacb, QCowAIOCB, common);
     if (acb->hd_aiocb)
         bdrv_aio_cancel(acb->hd_aiocb);
     qemu_aio_release(acb);
diff --git a/block/qcow2.c b/block/qcow2.c
index ebad4e1..0ce7150 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -338,7 +338,7 @@ typedef struct QCowAIOCB {
 
 static void qcow_aio_cancel(BlockDriverAIOCB *blockacb)
 {
-    QCowAIOCB *acb = (QCowAIOCB *)blockacb;
+    QCowAIOCB *acb = container_of(blockacb, QCowAIOCB, common);
     if (acb->hd_aiocb)
         bdrv_aio_cancel(acb->hd_aiocb);
     qemu_aio_release(acb);
diff --git a/block/vdi.c b/block/vdi.c
index 1d257b4..2b4d2c2 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -469,7 +469,7 @@ static int vdi_is_allocated(BlockDriverState *bs, int64_t sector_num,
 static void vdi_aio_cancel(BlockDriverAIOCB *blockacb)
 {
     /* TODO: This code is untested. How can I get it executed? */
-    VdiAIOCB *acb = (VdiAIOCB *)blockacb;
+    VdiAIOCB *acb = container_of(blockacb, VdiAIOCB, common);
     logout("\n");
     if (acb->hd_aiocb) {
         bdrv_aio_cancel(acb->hd_aiocb);
commit 7a6f391376c61af1dce2d624a4fcff8eec4fa097
Author: Christoph Hellwig <hch at lst.de>
Date:   Tue May 4 12:44:21 2010 +0200

    bochs: use qemu block API
    
    Use bdrv_pwrite to access the backing device instead of pread, and
    convert the driver to implementing the bdrv_open method which gives
    it an already opened BlockDriverState for the underlying device.
    
    Signed-off-by: Christoph Hellwig <hch at lst.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/bochs.c b/block/bochs.c
index b54f54d..5fe2fa3 100644
--- a/block/bochs.c
+++ b/block/bochs.c
@@ -80,8 +80,6 @@ struct bochs_header {
 };
 
 typedef struct BDRVBochsState {
-    int fd;
-
     uint32_t *catalog_bitmap;
     int catalog_size;
 
@@ -109,23 +107,16 @@ static int bochs_probe(const uint8_t *buf, int buf_size, const char *filename)
     return 0;
 }
 
-static int bochs_open(BlockDriverState *bs, const char *filename, int flags)
+static int bochs_open(BlockDriverState *bs, int flags)
 {
     BDRVBochsState *s = bs->opaque;
-    int fd, i;
+    int i;
     struct bochs_header bochs;
     struct bochs_header_v1 header_v1;
 
-    fd = open(filename, O_RDONLY | O_BINARY);
-    if (fd < 0) {
-        return -1;
-    }
-
     bs->read_only = 1; // no write support yet
 
-    s->fd = fd;
-
-    if (pread(fd, &bochs, sizeof(bochs), 0) != sizeof(bochs)) {
+    if (bdrv_pread(bs->file, 0, &bochs, sizeof(bochs)) != sizeof(bochs)) {
         goto fail;
     }
 
@@ -146,8 +137,8 @@ static int bochs_open(BlockDriverState *bs, const char *filename, int flags)
 
     s->catalog_size = le32_to_cpu(bochs.extra.redolog.catalog);
     s->catalog_bitmap = qemu_malloc(s->catalog_size * 4);
-    if (pread(s->fd, s->catalog_bitmap, s->catalog_size * 4,
-              le32_to_cpu(bochs.header)) != s->catalog_size * 4)
+    if (bdrv_pread(bs->file, le32_to_cpu(bochs.header), s->catalog_bitmap,
+                   s->catalog_size * 4) != s->catalog_size * 4)
 	goto fail;
     for (i = 0; i < s->catalog_size; i++)
 	le32_to_cpus(&s->catalog_bitmap[i]);
@@ -161,7 +152,6 @@ static int bochs_open(BlockDriverState *bs, const char *filename, int flags)
 
     return 0;
  fail:
-    close(fd);
     return -1;
 }
 
@@ -184,8 +174,8 @@ static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num)
 	(s->extent_blocks + s->bitmap_blocks));
 
     /* read in bitmap for current extent */
-    if (pread(s->fd, &bitmap_entry, 1, bitmap_offset + (extent_offset / 8))
-            != 1) {
+    if (bdrv_pread(bs->file, bitmap_offset + (extent_offset / 8),
+                   &bitmap_entry, 1) != 1) {
         return -1;
     }
 
@@ -199,13 +189,12 @@ static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num)
 static int bochs_read(BlockDriverState *bs, int64_t sector_num,
                     uint8_t *buf, int nb_sectors)
 {
-    BDRVBochsState *s = bs->opaque;
     int ret;
 
     while (nb_sectors > 0) {
         int64_t block_offset = seek_to_sector(bs, sector_num);
         if (block_offset >= 0) {
-            ret = pread(s->fd, buf, 512, block_offset);
+            ret = bdrv_pread(bs->file, block_offset, buf, 512);
             if (ret != 512) {
                 return -1;
             }
@@ -222,14 +211,13 @@ static void bochs_close(BlockDriverState *bs)
 {
     BDRVBochsState *s = bs->opaque;
     qemu_free(s->catalog_bitmap);
-    close(s->fd);
 }
 
 static BlockDriver bdrv_bochs = {
     .format_name	= "bochs",
     .instance_size	= sizeof(BDRVBochsState),
     .bdrv_probe		= bochs_probe,
-    .bdrv_file_open	= bochs_open,
+    .bdrv_open		= bochs_open,
     .bdrv_read		= bochs_read,
     .bdrv_close		= bochs_close,
 };
commit efbca10f10af2c0d7282e5dc49713479be98880b
Author: Christoph Hellwig <hch at lst.de>
Date:   Tue May 4 12:44:08 2010 +0200

    bochs: use pread
    
    Use pread instead of lseek + read in preparation of using the qemu
    block API.
    
    Signed-off-by: Christoph Hellwig <hch at lst.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/bochs.c b/block/bochs.c
index e952670..b54f54d 100644
--- a/block/bochs.c
+++ b/block/bochs.c
@@ -125,7 +125,7 @@ static int bochs_open(BlockDriverState *bs, const char *filename, int flags)
 
     s->fd = fd;
 
-    if (read(fd, &bochs, sizeof(bochs)) != sizeof(bochs)) {
+    if (pread(fd, &bochs, sizeof(bochs), 0) != sizeof(bochs)) {
         goto fail;
     }
 
@@ -144,14 +144,10 @@ static int bochs_open(BlockDriverState *bs, const char *filename, int flags)
       bs->total_sectors = le64_to_cpu(bochs.extra.redolog.disk) / 512;
     }
 
-    if (lseek(s->fd, le32_to_cpu(bochs.header), SEEK_SET) == (off_t)-1) {
-        goto fail;
-    }
-
     s->catalog_size = le32_to_cpu(bochs.extra.redolog.catalog);
     s->catalog_bitmap = qemu_malloc(s->catalog_size * 4);
-    if (read(s->fd, s->catalog_bitmap, s->catalog_size * 4) !=
-	s->catalog_size * 4)
+    if (pread(s->fd, s->catalog_bitmap, s->catalog_size * 4,
+              le32_to_cpu(bochs.header)) != s->catalog_size * 4)
 	goto fail;
     for (i = 0; i < s->catalog_size; i++)
 	le32_to_cpus(&s->catalog_bitmap[i]);
@@ -169,54 +165,35 @@ static int bochs_open(BlockDriverState *bs, const char *filename, int flags)
     return -1;
 }
 
-static inline int seek_to_sector(BlockDriverState *bs, int64_t sector_num)
+static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num)
 {
     BDRVBochsState *s = bs->opaque;
     int64_t offset = sector_num * 512;
-    int64_t extent_index, extent_offset, bitmap_offset, block_offset;
+    int64_t extent_index, extent_offset, bitmap_offset;
     char bitmap_entry;
 
     // seek to sector
     extent_index = offset / s->extent_size;
     extent_offset = (offset % s->extent_size) / 512;
 
-    if (s->catalog_bitmap[extent_index] == 0xffffffff)
-    {
-//	fprintf(stderr, "page not allocated [%x - %x:%x]\n",
-//	    sector_num, extent_index, extent_offset);
-	return -1; // not allocated
+    if (s->catalog_bitmap[extent_index] == 0xffffffff) {
+	return -1; /* not allocated */
     }
 
     bitmap_offset = s->data_offset + (512 * s->catalog_bitmap[extent_index] *
 	(s->extent_blocks + s->bitmap_blocks));
-    block_offset = bitmap_offset + (512 * (s->bitmap_blocks + extent_offset));
-
-//    fprintf(stderr, "sect: %x [ext i: %x o: %x] -> %x bitmap: %x block: %x\n",
-//	sector_num, extent_index, extent_offset,
-//	le32_to_cpu(s->catalog_bitmap[extent_index]),
-//	bitmap_offset, block_offset);
-
-    // read in bitmap for current extent
-    if (lseek(s->fd, bitmap_offset + (extent_offset / 8), SEEK_SET) ==
-        (off_t)-1) {
-        return -1;
-    }
 
-    if (read(s->fd, &bitmap_entry, 1) != 1)
+    /* read in bitmap for current extent */
+    if (pread(s->fd, &bitmap_entry, 1, bitmap_offset + (extent_offset / 8))
+            != 1) {
         return -1;
-
-    if (!((bitmap_entry >> (extent_offset % 8)) & 1))
-    {
-//	fprintf(stderr, "sector (%x) in bitmap not allocated\n",
-//	    sector_num);
-	return -1; // not allocated
     }
 
-    if (lseek(s->fd, block_offset, SEEK_SET) == (off_t)-1) {
-        return -1;
+    if (!((bitmap_entry >> (extent_offset % 8)) & 1)) {
+	return -1; /* not allocated */
     }
 
-    return 0;
+    return bitmap_offset + (512 * (s->bitmap_blocks + extent_offset));
 }
 
 static int bochs_read(BlockDriverState *bs, int64_t sector_num,
@@ -226,13 +203,13 @@ static int bochs_read(BlockDriverState *bs, int64_t sector_num,
     int ret;
 
     while (nb_sectors > 0) {
-	if (!seek_to_sector(bs, sector_num))
-	{
-	    ret = read(s->fd, buf, 512);
-	    if (ret != 512)
-		return -1;
-	}
-	else
+        int64_t block_offset = seek_to_sector(bs, sector_num);
+        if (block_offset >= 0) {
+            ret = pread(s->fd, buf, 512, block_offset);
+            if (ret != 512) {
+                return -1;
+            }
+        } else
             memset(buf, 0, 512);
         nb_sectors--;
         sector_num++;
commit 38d8dfa193e9a45f0f08b06aab2ba2a94f40a041
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue May 4 16:35:24 2010 +0200

    ide: Fix ide_dma_cancel
    
    When cancelling a request, bdrv_aio_cancel may decide that it waits for
    completion of a request rather than for cancellation. IDE therefore can't
    abandon its DMA status before calling bdrv_aio_cancel; otherwise the callback
    of a completed request would use invalid data.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide/core.c b/hw/ide/core.c
index b0165bc..066fecb 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -2838,10 +2838,6 @@ static void ide_dma_restart(IDEState *s, int is_read)
 void ide_dma_cancel(BMDMAState *bm)
 {
     if (bm->status & BM_STATUS_DMAING) {
-        bm->status &= ~BM_STATUS_DMAING;
-        /* cancel DMA request */
-        bm->unit = -1;
-        bm->dma_cb = NULL;
         if (bm->aiocb) {
 #ifdef DEBUG_AIO
             printf("aio_cancel\n");
@@ -2849,6 +2845,10 @@ void ide_dma_cancel(BMDMAState *bm)
             bdrv_aio_cancel(bm->aiocb);
             bm->aiocb = NULL;
         }
+        bm->status &= ~BM_STATUS_DMAING;
+        /* cancel DMA request */
+        bm->unit = -1;
+        bm->dma_cb = NULL;
     }
 }
 
commit 20be49e47e82f1b9fdc33810e1c4d7121871eafa
Author: Christoph Hellwig <hch at lst.de>
Date:   Tue May 4 12:44:52 2010 +0200

    cloop: use qemu block API
    
    Use bdrv_pwrite to access the backing device instead of pread, and
    convert the driver to implementing the bdrv_open method which gives
    it an already opened BlockDriverState for the underlying device.
    
    Signed-off-by: Christoph Hellwig <hch at lst.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/cloop.c b/block/cloop.c
index 9fe2a42..fe015c4 100644
--- a/block/cloop.c
+++ b/block/cloop.c
@@ -27,7 +27,6 @@
 #include <zlib.h>
 
 typedef struct BDRVCloopState {
-    int fd;
     uint32_t block_size;
     uint32_t n_blocks;
     uint64_t* offsets;
@@ -51,23 +50,20 @@ static int cloop_probe(const uint8_t *buf, int buf_size, const char *filename)
     return 0;
 }
 
-static int cloop_open(BlockDriverState *bs, const char *filename, int flags)
+static int cloop_open(BlockDriverState *bs, int flags)
 {
     BDRVCloopState *s = bs->opaque;
     uint32_t offsets_size,max_compressed_block_size=1,i;
 
-    s->fd = open(filename, O_RDONLY | O_BINARY);
-    if (s->fd < 0)
-        return -errno;
     bs->read_only = 1;
 
     /* read header */
-    if (pread(s->fd, &s->block_size, 4, 128) < 4) {
+    if (bdrv_pread(bs->file, 128, &s->block_size, 4) < 4) {
         goto cloop_close;
     }
     s->block_size = be32_to_cpu(s->block_size);
 
-    if (pread(s->fd, &s->n_blocks, 4, 128 + 4) < 4) {
+    if (bdrv_pread(bs->file, 128 + 4, &s->n_blocks, 4) < 4) {
         goto cloop_close;
     }
     s->n_blocks = be32_to_cpu(s->n_blocks);
@@ -75,7 +71,8 @@ static int cloop_open(BlockDriverState *bs, const char *filename, int flags)
     /* read offsets */
     offsets_size = s->n_blocks * sizeof(uint64_t);
     s->offsets = qemu_malloc(offsets_size);
-    if (pread(s->fd, s->offsets, offsets_size, 128 + 4 + 4) < offsets_size) {
+    if (bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size) <
+            offsets_size) {
 	goto cloop_close;
     }
     for(i=0;i<s->n_blocks;i++) {
@@ -99,17 +96,19 @@ static int cloop_open(BlockDriverState *bs, const char *filename, int flags)
     return 0;
 
 cloop_close:
-    close(s->fd);
     return -1;
 }
 
-static inline int cloop_read_block(BDRVCloopState *s,int block_num)
+static inline int cloop_read_block(BlockDriverState *bs, int block_num)
 {
+    BDRVCloopState *s = bs->opaque;
+
     if(s->current_block != block_num) {
 	int ret;
         uint32_t bytes = s->offsets[block_num+1]-s->offsets[block_num];
 
-        ret = pread(s->fd, s->compressed_block, bytes, s->offsets[block_num]);
+        ret = bdrv_pread(bs->file, s->offsets[block_num], s->compressed_block,
+                         bytes);
         if (ret != bytes)
             return -1;
 
@@ -138,7 +137,7 @@ static int cloop_read(BlockDriverState *bs, int64_t sector_num,
     for(i=0;i<nb_sectors;i++) {
 	uint32_t sector_offset_in_block=((sector_num+i)%s->sectors_per_block),
 	    block_num=(sector_num+i)/s->sectors_per_block;
-	if(cloop_read_block(s, block_num) != 0)
+	if(cloop_read_block(bs, block_num) != 0)
 	    return -1;
 	memcpy(buf+i*512,s->uncompressed_block+sector_offset_in_block*512,512);
     }
@@ -148,7 +147,6 @@ static int cloop_read(BlockDriverState *bs, int64_t sector_num,
 static void cloop_close(BlockDriverState *bs)
 {
     BDRVCloopState *s = bs->opaque;
-    close(s->fd);
     if(s->n_blocks>0)
 	free(s->offsets);
     free(s->compressed_block);
@@ -160,7 +158,7 @@ static BlockDriver bdrv_cloop = {
     .format_name	= "cloop",
     .instance_size	= sizeof(BDRVCloopState),
     .bdrv_probe		= cloop_probe,
-    .bdrv_file_open	= cloop_open,
+    .bdrv_open		= cloop_open,
     .bdrv_read		= cloop_read,
     .bdrv_close		= cloop_close,
 };
commit c94304be3f07fc038f0d8d48ffdca11a28b5aaca
Author: Christoph Hellwig <hch at lst.de>
Date:   Tue May 4 12:44:38 2010 +0200

    cloop: use pread
    
    Use pread instead of lseek + read in preparation of using the qemu
    block API.
    
    Signed-off-by: Christoph Hellwig <hch at lst.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/cloop.c b/block/cloop.c
index e4f995b..9fe2a42 100644
--- a/block/cloop.c
+++ b/block/cloop.c
@@ -62,23 +62,22 @@ static int cloop_open(BlockDriverState *bs, const char *filename, int flags)
     bs->read_only = 1;
 
     /* read header */
-    if(lseek(s->fd,128,SEEK_SET)<0) {
-cloop_close:
-	close(s->fd);
-	return -1;
+    if (pread(s->fd, &s->block_size, 4, 128) < 4) {
+        goto cloop_close;
     }
-    if(read(s->fd,&s->block_size,4)<4)
-	goto cloop_close;
-    s->block_size=be32_to_cpu(s->block_size);
-    if(read(s->fd,&s->n_blocks,4)<4)
-	goto cloop_close;
-    s->n_blocks=be32_to_cpu(s->n_blocks);
+    s->block_size = be32_to_cpu(s->block_size);
+
+    if (pread(s->fd, &s->n_blocks, 4, 128 + 4) < 4) {
+        goto cloop_close;
+    }
+    s->n_blocks = be32_to_cpu(s->n_blocks);
 
     /* read offsets */
-    offsets_size=s->n_blocks*sizeof(uint64_t);
-    s->offsets=(uint64_t*)qemu_malloc(offsets_size);
-    if(read(s->fd,s->offsets,offsets_size)<offsets_size)
+    offsets_size = s->n_blocks * sizeof(uint64_t);
+    s->offsets = qemu_malloc(offsets_size);
+    if (pread(s->fd, s->offsets, offsets_size, 128 + 4 + 4) < offsets_size) {
 	goto cloop_close;
+    }
     for(i=0;i<s->n_blocks;i++) {
 	s->offsets[i]=be64_to_cpu(s->offsets[i]);
 	if(i>0) {
@@ -98,6 +97,10 @@ cloop_close:
     s->sectors_per_block = s->block_size/512;
     bs->total_sectors = s->n_blocks*s->sectors_per_block;
     return 0;
+
+cloop_close:
+    close(s->fd);
+    return -1;
 }
 
 static inline int cloop_read_block(BDRVCloopState *s,int block_num)
@@ -106,8 +109,7 @@ static inline int cloop_read_block(BDRVCloopState *s,int block_num)
 	int ret;
         uint32_t bytes = s->offsets[block_num+1]-s->offsets[block_num];
 
-	lseek(s->fd, s->offsets[block_num], SEEK_SET);
-        ret = read(s->fd, s->compressed_block, bytes);
+        ret = pread(s->fd, s->compressed_block, bytes, s->offsets[block_num]);
         if (ret != bytes)
             return -1;
 
commit cb7cf0e3f471143136afb2ad1ff65890a978adc6
Author: Ryota Ozaki <ozaki.ryota at gmail.com>
Date:   Mon May 3 06:50:25 2010 +0900

    qemu-nbd: Improve error reporting
    
    - use err(3) instead of errx(3) if errno is available
      to report why failed
    - let fail prior to daemon(3) if opening a nbd file
      is likely to fail after daemonizing to avoid silent
      failure exit
    - add missing 'ret = 1' when unix_socket_outgoing failed
    
    Signed-off-by: Ryota Ozaki <ozaki.ryota at gmail.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qemu-nbd.c b/qemu-nbd.c
index 25aa913..4e607cf 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -112,9 +112,12 @@ static int find_partition(BlockDriverState *bs, int partition,
     uint8_t data[512];
     int i;
     int ext_partnum = 4;
+    int ret;
 
-    if (bdrv_read(bs, 0, data, 1))
-        errx(EXIT_FAILURE, "error while reading");
+    if ((ret = bdrv_read(bs, 0, data, 1)) < 0) {
+        errno = -ret;
+        err(EXIT_FAILURE, "error while reading");
+    }
 
     if (data[510] != 0x55 || data[511] != 0xaa) {
         errno = -EINVAL;
@@ -132,8 +135,10 @@ static int find_partition(BlockDriverState *bs, int partition,
             uint8_t data1[512];
             int j;
 
-            if (bdrv_read(bs, mbr[i].start_sector_abs, data1, 1))
-                errx(EXIT_FAILURE, "error while reading");
+            if ((ret = bdrv_read(bs, mbr[i].start_sector_abs, data1, 1)) < 0) {
+                errno = -ret;
+                err(EXIT_FAILURE, "error while reading");
+            }
 
             for (j = 0; j < 4; j++) {
                 read_partition(&data1[446 + 16 * j], &ext[j]);
@@ -316,7 +321,7 @@ int main(int argc, char **argv)
     if (disconnect) {
         fd = open(argv[optind], O_RDWR);
         if (fd == -1)
-            errx(EXIT_FAILURE, "Cannot open %s", argv[optind]);
+            err(EXIT_FAILURE, "Cannot open %s", argv[optind]);
 
         nbd_disconnect(fd);
 
@@ -333,23 +338,30 @@ int main(int argc, char **argv)
     if (bs == NULL)
         return 1;
 
-    if (bdrv_open(bs, argv[optind], flags, NULL) < 0)
-        return 1;
+    if ((ret = bdrv_open(bs, argv[optind], flags, NULL)) < 0) {
+        errno = -ret;
+        err(EXIT_FAILURE, "Failed to bdrv_open '%s'", argv[optind]);
+    }
 
     fd_size = bs->total_sectors * 512;
 
     if (partition != -1 &&
         find_partition(bs, partition, &dev_offset, &fd_size))
-        errx(EXIT_FAILURE, "Could not find partition %d", partition);
+        err(EXIT_FAILURE, "Could not find partition %d", partition);
 
     if (device) {
         pid_t pid;
         int sock;
 
+        /* want to fail before daemonizing */
+        if (access(device, R_OK|W_OK) == -1) {
+            err(EXIT_FAILURE, "Could not access '%s'", device);
+        }
+
         if (!verbose) {
             /* detach client and server */
             if (daemon(0, 0) == -1) {
-                errx(EXIT_FAILURE, "Failed to daemonize");
+                err(EXIT_FAILURE, "Failed to daemonize");
             }
         }
 
@@ -372,8 +384,10 @@ int main(int argc, char **argv)
             do {
                 sock = unix_socket_outgoing(socket);
                 if (sock == -1) {
-                    if (errno != ENOENT && errno != ECONNREFUSED)
+                    if (errno != ENOENT && errno != ECONNREFUSED) {
+                        ret = 1;
                         goto out;
+                    }
                     sleep(1);	/* wait children */
                 }
             } while (sock == -1);
commit 3abbc4d981159f2d53896808974ca7b07259ac58
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Sat May 1 07:23:32 2010 +0100

    block: Remove semicolon in BDRV_SECTOR_MASK macro
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.h b/block.h
index f87d24e..278259c 100644
--- a/block.h
+++ b/block.h
@@ -38,7 +38,7 @@ typedef struct QEMUSnapshotInfo {
 
 #define BDRV_SECTOR_BITS   9
 #define BDRV_SECTOR_SIZE   (1 << BDRV_SECTOR_BITS)
-#define BDRV_SECTOR_MASK   ~(BDRV_SECTOR_SIZE - 1);
+#define BDRV_SECTOR_MASK   ~(BDRV_SECTOR_SIZE - 1)
 
 typedef enum {
     BDRV_ACTION_REPORT, BDRV_ACTION_IGNORE, BDRV_ACTION_STOP
commit 21ffd18163d9ff8e965f91dd96433f37fa99f204
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun May 16 08:33:02 2010 +0000

    sparc: move DT and QT defines to op_helper.c
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/exec.h b/target-sparc/exec.h
index 1e9de82..c84e055 100644
--- a/target-sparc/exec.h
+++ b/target-sparc/exec.h
@@ -5,11 +5,6 @@
 
 register struct CPUSPARCState *env asm(AREG0);
 
-#define DT0 (env->dt0)
-#define DT1 (env->dt1)
-#define QT0 (env->qt0)
-#define QT1 (env->qt1)
-
 #include "cpu.h"
 #include "exec-all.h"
 
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index ec39244..b1451d3 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -44,6 +44,11 @@
 #endif
 #endif
 
+#define DT0 (env->dt0)
+#define DT1 (env->dt1)
+#define QT0 (env->qt0)
+#define QT1 (env->qt1)
+
 #if defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64)
 static void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
                           int is_asi, int size);
commit 88c8e03f5ddca8c8448dbb99d9de07d87b03ddd6
Author: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Date:   Sun May 16 04:11:29 2010 +0400

    sparc64: fix TT_WOTHER value
    
    - fix off by one error in spill trap number bit for other window (must be bit 5)
    - fixes invalid instruction issue with HelenOS
    
    Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 22f3ad0..27b020b 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -79,7 +79,7 @@
 #define TT_DPROT    0x6c
 #define TT_SPILL    0x80
 #define TT_FILL     0xc0
-#define TT_WOTHER   0x10
+#define TT_WOTHER   (1 << 5)
 #define TT_TRAP     0x100
 #endif
 
commit 170f4c550f472d4854bb0155605d4459a31ce3f4
Author: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Date:   Sun May 16 04:11:24 2010 +0400

    sparc64: fix mmu demap operand typo
    
    - must use store address operand to demap, not store value
    
    Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index fcfd3f3..ec39244 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -2877,7 +2877,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
             return;
         }
     case 0x57: // I-MMU demap
-        demap_tlb(env->itlb, val, "immu", env);
+        demap_tlb(env->itlb, addr, "immu", env);
         return;
     case 0x58: // D-MMU regs
         {
@@ -2942,7 +2942,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
             return;
         }
     case 0x5f: // D-MMU demap
-        demap_tlb(env->dtlb, val, "dmmu", env);
+        demap_tlb(env->dtlb, addr, "dmmu", env);
         return;
     case 0x49: // Interrupt data receive
         // XXX
commit 1012e960c747849e53db702c96b4c0f25a9bda95
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat May 15 17:52:49 2010 +0000

    Update to a hopefully more future proof FSF address
    
    See also 70539e1850ddd3a7ee6f9a8db7bd8e81b85225a4,
    8167ee883931cb20c6264fc19d040ce2dc6ceaaa,
    530e7615ce3c01882e582c84dc6304ab98a3d5c5 and
    fad6cb1a565bb73f83fc0e2654489457b489e436.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/acpi.h b/hw/acpi.h
index 51b56b6..5949958 100644
--- a/hw/acpi.h
+++ b/hw/acpi.h
@@ -15,8 +15,8 @@
  * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/>.
  */
 
 /* from linux include/acpi/actype.h */
diff --git a/hw/pm_smbus.c b/hw/pm_smbus.c
index cb8b7ee..5d6046d 100644
--- a/hw/pm_smbus.c
+++ b/hw/pm_smbus.c
@@ -14,8 +14,8 @@
  * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/>.
  */
 #include "hw.h"
 #include "pc.h"
diff --git a/ia64-dis.c b/ia64-dis.c
index a025178..da73a98 100644
--- a/ia64-dis.c
+++ b/ia64-dis.c
@@ -990,9 +990,8 @@ const struct ia64_operand elf64_ia64_operands[IA64_OPND_COUNT] =
    the GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this file; see the file COPYING.  If not, write to the
-   Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
-   02110-1301, USA.  */
+   along with this file; see the file COPYING.  If not, see
+   <http://www.gnu.org/licenses/>. */
 
 /* The primary opcode table is made up of the following: */
 struct ia64_main_table
@@ -9906,9 +9905,8 @@ static const struct ia64_dis_names ia64_dis_names[] = {
    the GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this file; see the file COPYING.  If not, write to the
-   Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
-   02110-1301, USA.  */
+   along with this file; see the file COPYING.  If not, see
+   <http://www.gnu.org/licenses/>. */
 
 static const struct ia64_templ_desc ia64_templ_desc[16] =
   {
commit 0b8f9be61cd89de3be7bfac8b5fe544fceca1af3
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat May 15 17:36:13 2010 +0000

    Trim unnecessary includes
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/acpi.c b/hw/acpi.c
index 4c4df56..c7044b1 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -17,8 +17,6 @@
  */
 #include "hw.h"
 #include "pc.h"
-#include "pci.h"
-#include "sysemu.h"
 #include "acpi.h"
 
 struct acpi_table_header
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index fdef697..0fce958 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -20,9 +20,6 @@
 #include "apm.h"
 #include "pm_smbus.h"
 #include "pci.h"
-#include "sysemu.h"
-#include "i2c.h"
-#include "smbus.h"
 #include "acpi.h"
 
 //#define DEBUG
diff --git a/hw/apm.c b/hw/apm.c
index 3cbde43..cdda72f 100644
--- a/hw/apm.c
+++ b/hw/apm.c
@@ -19,7 +19,6 @@
 
 #include "apm.h"
 #include "hw.h"
-#include "isa.h"
 
 //#define DEBUG
 
diff --git a/hw/pm_smbus.c b/hw/pm_smbus.c
index 9929d72..cb8b7ee 100644
--- a/hw/pm_smbus.c
+++ b/hw/pm_smbus.c
@@ -20,12 +20,7 @@
 #include "hw.h"
 #include "pc.h"
 #include "pm_smbus.h"
-#include "pci.h"
-#include "qemu-timer.h"
-#include "sysemu.h"
-#include "i2c.h"
 #include "smbus.h"
-#include "kvm.h"
 
 /* no save/load? */
 
commit ec51e364ed041c5526e388cc1e480f48ecb68c3c
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri May 14 16:29:24 2010 +0900

    mc146818rtc: remove #ifdef DEBUG_CMOS.
    
    remove #ifdef DEBUG_CMOS by using macro.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 450d218..571c593 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -32,6 +32,12 @@
 
 //#define DEBUG_CMOS
 
+#ifdef DEBUG_CMOS
+# define CMOS_DPRINTF(format, ...)      printf(format, ## __VA_ARGS__)
+#else
+# define CMOS_DPRINTF(format, ...)      do { } while (0)
+#endif
+
 #define RTC_REINJECT_ON_ACK_COUNT 20
 
 #define RTC_SECONDS             0
@@ -211,10 +217,8 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
     if ((addr & 1) == 0) {
         s->cmos_index = data & 0x7f;
     } else {
-#ifdef DEBUG_CMOS
-        printf("cmos: write index=0x%02x val=0x%02x\n",
-               s->cmos_index, data);
-#endif
+        CMOS_DPRINTF("cmos: write index=0x%02x val=0x%02x\n",
+                     s->cmos_index, data);
         switch(s->cmos_index) {
         case RTC_SECONDS_ALARM:
         case RTC_MINUTES_ALARM:
@@ -485,10 +489,8 @@ static uint32_t cmos_ioport_read(void *opaque, uint32_t addr)
             ret = s->cmos_data[s->cmos_index];
             break;
         }
-#ifdef DEBUG_CMOS
-        printf("cmos: read index=0x%02x val=0x%02x\n",
-               s->cmos_index, ret);
-#endif
+        CMOS_DPRINTF("cmos: read index=0x%02x val=0x%02x\n",
+                     s->cmos_index, ret);
         return ret;
     }
 }
commit 019ea978975cb8c4cf6102961e5fe5d23b9a5f98
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri May 14 16:29:23 2010 +0900

    apm: remove #ifdef DEBUG.
    
    remove #ifdef DEBUG by using macro.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/apm.c b/hw/apm.c
index d20db3d..3cbde43 100644
--- a/hw/apm.c
+++ b/hw/apm.c
@@ -23,6 +23,12 @@
 
 //#define DEBUG
 
+#ifdef DEBUG
+# define APM_DPRINTF(format, ...)       printf(format, ## __VA_ARGS__)
+#else
+# define APM_DPRINTF(format, ...)       do { } while (0)
+#endif
+
 /* fixed I/O location */
 #define APM_CNT_IOPORT  0xb2
 #define APM_STS_IOPORT  0xb3
@@ -31,9 +37,7 @@ static void apm_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
 {
     APMState *apm = opaque;
     addr &= 1;
-#ifdef DEBUG
-    printf("apm_ioport_writeb addr=0x%x val=0x%02x\n", addr, val);
-#endif
+    APM_DPRINTF("apm_ioport_writeb addr=0x%x val=0x%02x\n", addr, val);
     if (addr == 0) {
         apm->apmc = val;
 
@@ -56,9 +60,7 @@ static uint32_t apm_ioport_readb(void *opaque, uint32_t addr)
     } else {
         val = apm->apms;
     }
-#ifdef DEBUG
-    printf("apm_ioport_readb addr=0x%x val=0x%02x\n", addr, val);
-#endif
+    APM_DPRINTF("apm_ioport_readb addr=0x%x val=0x%02x\n", addr, val);
     return val;
 }
 
commit 50d8ff8b0d38af835aabba4d8512c4cc7b3e21f0
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri May 14 16:29:22 2010 +0900

    acpi_piix4: remove #ifdef DEBUG.
    
    removed #ifdef DEBUG by using macro.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index bb3d094..fdef697 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -27,6 +27,12 @@
 
 //#define DEBUG
 
+#ifdef DEBUG
+# define PIIX4_DPRINTF(format, ...)     printf(format, ## __VA_ARGS__)
+#else
+# define PIIX4_DPRINTF(format, ...)     do { } while (0)
+#endif
+
 #define ACPI_DBG_IO_ADDR  0xb044
 
 #define GPE_BASE 0xafe0
@@ -172,9 +178,7 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
     default:
         break;
     }
-#ifdef DEBUG
-    printf("PM writew port=0x%04x val=0x%04x\n", addr, val);
-#endif
+    PIIX4_DPRINTF("PM writew port=0x%04x val=0x%04x\n", addr, val);
 }
 
 static uint32_t pm_ioport_readw(void *opaque, uint32_t addr)
@@ -197,19 +201,14 @@ static uint32_t pm_ioport_readw(void *opaque, uint32_t addr)
         val = 0;
         break;
     }
-#ifdef DEBUG
-    printf("PM readw port=0x%04x val=0x%04x\n", addr, val);
-#endif
+    PIIX4_DPRINTF("PM readw port=0x%04x val=0x%04x\n", addr, val);
     return val;
 }
 
 static void pm_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
 {
     //    PIIX4PMState *s = opaque;
-#ifdef DEBUG
-    addr &= 0x3f;
-    printf("PM writel port=0x%04x val=0x%08x\n", addr, val);
-#endif
+    PIIX4_DPRINTF("PM writel port=0x%04x val=0x%08x\n", addr & 0x3f, val);
 }
 
 static uint32_t pm_ioport_readl(void *opaque, uint32_t addr)
@@ -226,9 +225,7 @@ static uint32_t pm_ioport_readl(void *opaque, uint32_t addr)
         val = 0;
         break;
     }
-#ifdef DEBUG
-    printf("PM readl port=0x%04x val=0x%08x\n", addr, val);
-#endif
+    PIIX4_DPRINTF("PM readl port=0x%04x val=0x%08x\n", addr, val);
     return val;
 }
 
@@ -252,9 +249,7 @@ static void apm_ctrl_changed(uint32_t val, void *arg)
 
 static void acpi_dbg_writel(void *opaque, uint32_t addr, uint32_t val)
 {
-#if defined(DEBUG)
-    printf("ACPI: DBG: 0x%08x\n", val);
-#endif
+    PIIX4_DPRINTF("ACPI: DBG: 0x%08x\n", val);
 }
 
 static void pm_io_space_update(PIIX4PMState *s)
@@ -266,9 +261,7 @@ static void pm_io_space_update(PIIX4PMState *s)
         pm_io_base &= 0xffc0;
 
         /* XXX: need to improve memory and ioport allocation */
-#if defined(DEBUG)
-        printf("PM: mapping to 0x%x\n", pm_io_base);
-#endif
+        PIIX4_DPRINTF("PM: mapping to 0x%x\n", pm_io_base);
         register_ioport_write(pm_io_base, 64, 2, pm_ioport_writew, s);
         register_ioport_read(pm_io_base, 64, 2, pm_ioport_readw, s);
         register_ioport_write(pm_io_base, 64, 4, pm_ioport_writel, s);
@@ -456,9 +449,7 @@ static uint32_t gpe_readb(void *opaque, uint32_t addr)
             break;
     }
 
-#if defined(DEBUG)
-    printf("gpe read %x == %x\n", addr, val);
-#endif
+    PIIX4_DPRINTF("gpe read %x == %x\n", addr, val);
     return val;
 }
 
@@ -498,9 +489,7 @@ static void gpe_writeb(void *opaque, uint32_t addr, uint32_t val)
             break;
    }
 
-#if defined(DEBUG)
-    printf("gpe write %x <== %d\n", addr, val);
-#endif
+    PIIX4_DPRINTF("gpe write %x <== %d\n", addr, val);
 }
 
 static uint32_t pcihotplug_read(void *opaque, uint32_t addr)
@@ -518,9 +507,7 @@ static uint32_t pcihotplug_read(void *opaque, uint32_t addr)
             break;
     }
 
-#if defined(DEBUG)
-    printf("pcihotplug read %x == %x\n", addr, val);
-#endif
+    PIIX4_DPRINTF("pcihotplug read %x == %x\n", addr, val);
     return val;
 }
 
@@ -536,16 +523,12 @@ static void pcihotplug_write(void *opaque, uint32_t addr, uint32_t val)
             break;
    }
 
-#if defined(DEBUG)
-    printf("pcihotplug write %x <== %d\n", addr, val);
-#endif
+    PIIX4_DPRINTF("pcihotplug write %x <== %d\n", addr, val);
 }
 
 static uint32_t pciej_read(void *opaque, uint32_t addr)
 {
-#if defined(DEBUG)
-    printf("pciej read %x\n", addr);
-#endif
+    PIIX4_DPRINTF("pciej read %x\n", addr);
     return 0;
 }
 
@@ -564,9 +547,7 @@ static void pciej_write(void *opaque, uint32_t addr, uint32_t val)
     }
 
 
-#if defined(DEBUG)
-    printf("pciej write %x <== %d\n", addr, val);
-#endif
+    PIIX4_DPRINTF("pciej write %x <== %d\n", addr, val);
 }
 
 static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev, int state);
commit b246eebb0acca216648c75e4f925ac0939a968c0
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri May 14 16:29:21 2010 +0900

    pm_smbus: remove #ifdef DEBUG.
    
    remove #ifdef DEBUG by using macro.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/pm_smbus.c b/hw/pm_smbus.c
index 6ef6b9e..9929d72 100644
--- a/hw/pm_smbus.c
+++ b/hw/pm_smbus.c
@@ -37,6 +37,15 @@
 #define SMBHSTDAT1      0x06
 #define SMBBLKDAT       0x07
 
+//#define DEBUG
+
+#ifdef DEBUG
+# define SMBUS_DPRINTF(format, ...)     printf(format, ## __VA_ARGS__)
+#else
+# define SMBUS_DPRINTF(format, ...)     do { } while (0)
+#endif
+
+
 static void smb_transaction(PMSMBus *s)
 {
     uint8_t prot = (s->smb_ctl >> 2) & 0x07;
@@ -45,9 +54,7 @@ static void smb_transaction(PMSMBus *s)
     uint8_t addr = s->smb_addr >> 1;
     i2c_bus *bus = s->smbus;
 
-#ifdef DEBUG
-    printf("SMBus trans addr=0x%02x prot=0x%02x\n", addr, prot);
-#endif
+    SMBUS_DPRINTF("SMBus trans addr=0x%02x prot=0x%02x\n", addr, prot);
     switch(prot) {
     case 0x0:
         smbus_quick_command(bus, addr, read);
@@ -96,9 +103,7 @@ void smb_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
 {
     PMSMBus *s = opaque;
     addr &= 0x3f;
-#ifdef DEBUG
-    printf("SMB writeb port=0x%04x val=0x%02x\n", addr, val);
-#endif
+    SMBUS_DPRINTF("SMB writeb port=0x%04x val=0x%02x\n", addr, val);
     switch(addr) {
     case SMBHSTSTS:
         s->smb_stat = 0;
@@ -166,9 +171,7 @@ uint32_t smb_ioport_readb(void *opaque, uint32_t addr)
         val = 0;
         break;
     }
-#ifdef DEBUG
-    printf("SMB readb port=0x%04x val=0x%02x\n", addr, val);
-#endif
+    SMBUS_DPRINTF("SMB readb port=0x%04x val=0x%02x\n", addr, val);
     return val;
 }
 
commit ac4040955b1669f0aac5937f623d6587d5210679
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri May 14 16:29:20 2010 +0900

    pci hotadd, acpi_piix4: remove global variables
    
    remove global variables, gpe and pci0_status by moving them
    into PIIX4PMState.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index c3e71e3..bb3d094 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -29,6 +29,20 @@
 
 #define ACPI_DBG_IO_ADDR  0xb044
 
+#define GPE_BASE 0xafe0
+#define PCI_BASE 0xae00
+#define PCI_EJ_BASE 0xae08
+
+struct gpe_regs {
+    uint16_t sts; /* status */
+    uint16_t en;  /* enabled */
+};
+
+struct pci_status {
+    uint32_t up;
+    uint32_t down;
+};
+
 typedef struct PIIX4PMState {
     PCIDevice dev;
     uint16_t pmsts;
@@ -47,13 +61,17 @@ typedef struct PIIX4PMState {
     qemu_irq cmos_s3;
     qemu_irq smi_irq;
     int kvm_enabled;
+
+    /* for pci hotplug */
+    struct gpe_regs gpe;
+    struct pci_status pci0_status;
 } PIIX4PMState;
 
+static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s);
+
 #define ACPI_ENABLE 0xf1
 #define ACPI_DISABLE 0xf0
 
-static PIIX4PMState *pm_state;
-
 static uint32_t get_pmtmr(PIIX4PMState *s)
 {
     uint32_t d;
@@ -325,7 +343,6 @@ static int piix4_pm_initfn(PCIDevice *dev)
     PIIX4PMState *s = DO_UPCAST(PIIX4PMState, dev, dev);
     uint8_t *pci_conf;
 
-    pm_state = s;
     pci_conf = s->dev.config;
     pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
     pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82371AB_3);
@@ -369,6 +386,7 @@ static int piix4_pm_initfn(PCIDevice *dev)
 
     pm_smbus_init(&s->dev.qdev, &s->smb);
     qemu_register_reset(piix4_reset, s);
+    piix4_acpi_system_hot_add_init(dev->bus, s);
 
     return 0;
 }
@@ -414,23 +432,6 @@ static void piix4_pm_register(void)
 
 device_init(piix4_pm_register);
 
-#define GPE_BASE 0xafe0
-#define PCI_BASE 0xae00
-#define PCI_EJ_BASE 0xae08
-
-struct gpe_regs {
-    uint16_t sts; /* status */
-    uint16_t en;  /* enabled */
-};
-
-struct pci_status {
-    uint32_t up;
-    uint32_t down;
-};
-
-static struct gpe_regs gpe;
-static struct pci_status pci0_status;
-
 static uint32_t gpe_read_val(uint16_t val, uint32_t addr)
 {
     if (addr & 1)
@@ -570,45 +571,51 @@ static void pciej_write(void *opaque, uint32_t addr, uint32_t val)
 
 static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev, int state);
 
-void piix4_acpi_system_hot_add_init(PCIBus *bus)
+static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s)
 {
-    register_ioport_write(GPE_BASE, 4, 1, gpe_writeb, &gpe);
-    register_ioport_read(GPE_BASE, 4, 1,  gpe_readb, &gpe);
+    struct gpe_regs *gpe = &s->gpe;
+    struct pci_status *pci0_status = &s->pci0_status;
 
-    register_ioport_write(PCI_BASE, 8, 4, pcihotplug_write, &pci0_status);
-    register_ioport_read(PCI_BASE, 8, 4,  pcihotplug_read, &pci0_status);
+    register_ioport_write(GPE_BASE, 4, 1, gpe_writeb, gpe);
+    register_ioport_read(GPE_BASE, 4, 1,  gpe_readb, gpe);
+
+    register_ioport_write(PCI_BASE, 8, 4, pcihotplug_write, pci0_status);
+    register_ioport_read(PCI_BASE, 8, 4,  pcihotplug_read, pci0_status);
 
     register_ioport_write(PCI_EJ_BASE, 4, 4, pciej_write, bus);
     register_ioport_read(PCI_EJ_BASE, 4, 4,  pciej_read, bus);
 
-    pci_bus_hotplug(bus, piix4_device_hotplug, NULL);
+    pci_bus_hotplug(bus, piix4_device_hotplug, &s->dev.qdev);
 }
 
-static void enable_device(struct pci_status *p, struct gpe_regs *g, int slot)
+static void enable_device(PIIX4PMState *s, int slot)
 {
-    g->sts |= 2;
-    p->up |= (1 << slot);
+    s->gpe.sts |= 2;
+    s->pci0_status.up |= (1 << slot);
 }
 
-static void disable_device(struct pci_status *p, struct gpe_regs *g, int slot)
+static void disable_device(PIIX4PMState *s, int slot)
 {
-    g->sts |= 2;
-    p->down |= (1 << slot);
+    s->gpe.sts |= 2;
+    s->pci0_status.down |= (1 << slot);
 }
 
 static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev, int state)
 {
     int slot = PCI_SLOT(dev->devfn);
+    PIIX4PMState *s = DO_UPCAST(PIIX4PMState, dev,
+                                DO_UPCAST(PCIDevice, qdev, qdev));
 
-    pci0_status.up = 0;
-    pci0_status.down = 0;
-    if (state)
-        enable_device(&pci0_status, &gpe, slot);
-    else
-        disable_device(&pci0_status, &gpe, slot);
-    if (gpe.en & 2) {
-        qemu_set_irq(pm_state->irq, 1);
-        qemu_set_irq(pm_state->irq, 0);
+    s->pci0_status.up = 0;
+    s->pci0_status.down = 0;
+    if (state) {
+        enable_device(s, slot);
+    } else {
+        disable_device(s, slot);
+    }
+    if (s->gpe.en & 2) {
+        qemu_set_irq(s->irq, 1);
+        qemu_set_irq(s->irq, 0);
     }
     return 0;
 }
diff --git a/hw/pc.h b/hw/pc.h
index 2e2f4e2..654b7b3 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -124,7 +124,6 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
                        qemu_irq sci_irq, qemu_irq cmos_s3, qemu_irq smi_irq,
                        int kvm_enabled);
 void piix4_smbus_register_device(SMBusDevice *dev, uint8_t addr);
-void piix4_acpi_system_hot_add_init(PCIBus *bus);
 
 /* hpet.c */
 extern int no_hpet;
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index a0ed7ad..70f563a 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -150,7 +150,6 @@ static void pc_init1(ram_addr_t ram_size,
             qdev_prop_set_ptr(eeprom, "data", eeprom_buf + (i * 256));
             qdev_init_nofail(eeprom);
         }
-        piix4_acpi_system_hot_add_init(pci_bus);
     }
 
     if (i440fx_state) {
commit 87c30546ef34f9eb6740d884c8b73e2cdd259e35
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri May 14 16:29:19 2010 +0900

    pci hotplug: add argument to pci hot plug callback.
    
    Add argument, DeviceState*, to pci hot plug callback.
    The argument will be used later to remove global variable.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index d4f4662..c3e71e3 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -568,7 +568,7 @@ static void pciej_write(void *opaque, uint32_t addr, uint32_t val)
 #endif
 }
 
-static int piix4_device_hotplug(PCIDevice *dev, int state);
+static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev, int state);
 
 void piix4_acpi_system_hot_add_init(PCIBus *bus)
 {
@@ -581,7 +581,7 @@ void piix4_acpi_system_hot_add_init(PCIBus *bus)
     register_ioport_write(PCI_EJ_BASE, 4, 4, pciej_write, bus);
     register_ioport_read(PCI_EJ_BASE, 4, 4,  pciej_read, bus);
 
-    pci_bus_hotplug(bus, piix4_device_hotplug);
+    pci_bus_hotplug(bus, piix4_device_hotplug, NULL);
 }
 
 static void enable_device(struct pci_status *p, struct gpe_regs *g, int slot)
@@ -596,7 +596,7 @@ static void disable_device(struct pci_status *p, struct gpe_regs *g, int slot)
     p->down |= (1 << slot);
 }
 
-static int piix4_device_hotplug(PCIDevice *dev, int state)
+static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev, int state)
 {
     int slot = PCI_SLOT(dev->devfn);
 
diff --git a/hw/pci.c b/hw/pci.c
index f167436..679f067 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -42,6 +42,7 @@ struct PCIBus {
     pci_set_irq_fn set_irq;
     pci_map_irq_fn map_irq;
     pci_hotplug_fn hotplug;
+    DeviceState *hotplug_qdev;
     void *irq_opaque;
     PCIDevice *devices[256];
     PCIDevice *parent_dev;
@@ -233,10 +234,11 @@ void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
     bus->irq_count = qemu_mallocz(nirq * sizeof(bus->irq_count[0]));
 }
 
-void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug)
+void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *qdev)
 {
     bus->qbus.allow_hotplug = 1;
     bus->hotplug = hotplug;
+    bus->hotplug_qdev = qdev;
 }
 
 void pci_bus_set_mem_base(PCIBus *bus, target_phys_addr_t base)
@@ -1661,7 +1663,7 @@ static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
     pci_add_option_rom(pci_dev);
 
     if (qdev->hotplugged)
-        bus->hotplug(pci_dev, 1);
+        bus->hotplug(bus->hotplug_qdev, pci_dev, 1);
     return 0;
 }
 
@@ -1669,7 +1671,7 @@ static int pci_unplug_device(DeviceState *qdev)
 {
     PCIDevice *dev = DO_UPCAST(PCIDevice, qdev, qdev);
 
-    dev->bus->hotplug(dev, 0);
+    dev->bus->hotplug(dev->bus->hotplug_qdev, dev, 0);
     return 0;
 }
 
diff --git a/hw/pci.h b/hw/pci.h
index 625188c..f6e6c5f 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -209,13 +209,13 @@ int pci_device_load(PCIDevice *s, QEMUFile *f);
 
 typedef void (*pci_set_irq_fn)(void *opaque, int irq_num, int level);
 typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num);
-typedef int (*pci_hotplug_fn)(PCIDevice *pci_dev, int state);
+typedef int (*pci_hotplug_fn)(DeviceState *qdev, PCIDevice *pci_dev, int state);
 void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
                          const char *name, int devfn_min);
 PCIBus *pci_bus_new(DeviceState *parent, const char *name, int devfn_min);
 void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
                   void *irq_opaque, int nirq);
-void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug);
+void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *dev);
 PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
                          void *irq_opaque, int devfn_min, int nirq);
commit e8ec0571e16115203f4d6cc7eb31f930167592f8
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri May 14 16:29:18 2010 +0900

    acpi_piix4: qdevfy.
    
    qdevfy acpi_piix4.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 1292d2b..d4f4662 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -41,6 +41,7 @@ typedef struct PIIX4PMState {
     int64_t tmr_overflow_time;
 
     PMSMBus smb;
+    uint32_t smb_io_base;
 
     qemu_irq irq;
     qemu_irq cmos_s3;
@@ -319,16 +320,11 @@ static void piix4_powerdown(void *opaque, int irq, int power_failing)
     }
 }
 
-i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
-                       qemu_irq sci_irq, qemu_irq cmos_s3, qemu_irq smi_irq,
-                       int kvm_enabled)
+static int piix4_pm_initfn(PCIDevice *dev)
 {
-    PIIX4PMState *s;
+    PIIX4PMState *s = DO_UPCAST(PIIX4PMState, dev, dev);
     uint8_t *pci_conf;
 
-    s = (PIIX4PMState *)pci_register_device(bus,
-                                         "PM", sizeof(PIIX4PMState),
-                                         devfn, NULL, pm_write_config);
     pm_state = s;
     pci_conf = s->dev.config;
     pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
@@ -348,7 +344,6 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
 
     register_ioport_write(ACPI_DBG_IO_ADDR, 4, 4, acpi_dbg_writel, s);
 
-    s->kvm_enabled = kvm_enabled;
     if (s->kvm_enabled) {
         /* Mark SMM as already inited to prevent SMM from running.  KVM does not
          * support SMM mode. */
@@ -362,27 +357,63 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
     pci_conf[0x67] = (serial_hds[0] != NULL ? 0x08 : 0) |
 	(serial_hds[1] != NULL ? 0x90 : 0);
 
-    pci_conf[0x90] = smb_io_base | 1;
-    pci_conf[0x91] = smb_io_base >> 8;
+    pci_conf[0x90] = s->smb_io_base | 1;
+    pci_conf[0x91] = s->smb_io_base >> 8;
     pci_conf[0xd2] = 0x09;
-    register_ioport_write(smb_io_base, 64, 1, smb_ioport_writeb, &s->smb);
-    register_ioport_read(smb_io_base, 64, 1, smb_ioport_readb, &s->smb);
+    register_ioport_write(s->smb_io_base, 64, 1, smb_ioport_writeb, &s->smb);
+    register_ioport_read(s->smb_io_base, 64, 1, smb_ioport_readb, &s->smb);
 
     s->tmr_timer = qemu_new_timer(vm_clock, pm_tmr_timer, s);
 
     qemu_system_powerdown = *qemu_allocate_irqs(piix4_powerdown, s, 1);
 
-    vmstate_register(0, &vmstate_acpi, s);
+    pm_smbus_init(&s->dev.qdev, &s->smb);
+    qemu_register_reset(piix4_reset, s);
+
+    return 0;
+}
 
-    pm_smbus_init(NULL, &s->smb);
+i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
+                       qemu_irq sci_irq, qemu_irq cmos_s3, qemu_irq smi_irq,
+                       int kvm_enabled)
+{
+    PCIDevice *dev;
+    PIIX4PMState *s;
+
+    dev = pci_create(bus, devfn, "PIIX4_PM");
+    qdev_prop_set_uint32(&dev->qdev, "smb_io_base", smb_io_base);
+
+    s = DO_UPCAST(PIIX4PMState, dev, dev);
     s->irq = sci_irq;
     s->cmos_s3 = cmos_s3;
     s->smi_irq = smi_irq;
-    qemu_register_reset(piix4_reset, s);
+    s->kvm_enabled = kvm_enabled;
+
+    qdev_init_nofail(&dev->qdev);
 
     return s->smb.smbus;
 }
 
+static PCIDeviceInfo piix4_pm_info = {
+    .qdev.name          = "PIIX4_PM",
+    .qdev.desc          = "PM",
+    .qdev.size          = sizeof(PIIX4PMState),
+    .qdev.vmsd          = &vmstate_acpi,
+    .init               = piix4_pm_initfn,
+    .config_write       = pm_write_config,
+    .qdev.props         = (Property[]) {
+        DEFINE_PROP_UINT32("smb_io_base", PIIX4PMState, smb_io_base, 0),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+
+static void piix4_pm_register(void)
+{
+    pci_qdev_register(&piix4_pm_info);
+}
+
+device_init(piix4_pm_register);
+
 #define GPE_BASE 0xafe0
 #define PCI_BASE 0xae00
 #define PCI_EJ_BASE 0xae08
commit 1d914fa0af66024faee8cc6fa3043a935f95f775
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri May 14 16:29:17 2010 +0900

    rtc: make rtc_xxx accept/return ISADevice instead of RTCState.
    
    To match rtc_xxx with qdev, make rtc_xxx accept and return ISADevice
    instead of RTCState.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 905e670..450d218 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -28,6 +28,7 @@
 #include "apic.h"
 #include "isa.h"
 #include "hpet_emul.h"
+#include "mc146818rtc.h"
 
 //#define DEBUG_CMOS
 
@@ -65,7 +66,7 @@
 #define REG_C_PF   0x40
 #define REG_C_AF   0x20
 
-struct RTCState {
+typedef struct RTCState {
     ISADevice dev;
     uint8_t cmos_data[128];
     uint8_t cmos_index;
@@ -85,7 +86,7 @@ struct RTCState {
     QEMUTimer *coalesced_timer;
     QEMUTimer *second_timer;
     QEMUTimer *second_timer2;
-};
+} RTCState;
 
 static void rtc_irq_raise(qemu_irq irq)
 {
@@ -492,14 +493,16 @@ static uint32_t cmos_ioport_read(void *opaque, uint32_t addr)
     }
 }
 
-void rtc_set_memory(RTCState *s, int addr, int val)
+void rtc_set_memory(ISADevice *dev, int addr, int val)
 {
+    RTCState *s = DO_UPCAST(RTCState, dev, dev);
     if (addr >= 0 && addr <= 127)
         s->cmos_data[addr] = val;
 }
 
-void rtc_set_date(RTCState *s, const struct tm *tm)
+void rtc_set_date(ISADevice *dev, const struct tm *tm)
 {
+    RTCState *s = DO_UPCAST(RTCState, dev, dev);
     s->current_tm = *tm;
     rtc_copy_date(s);
 }
@@ -508,18 +511,19 @@ void rtc_set_date(RTCState *s, const struct tm *tm)
 #define REG_IBM_CENTURY_BYTE        0x32
 #define REG_IBM_PS2_CENTURY_BYTE    0x37
 
-static void rtc_set_date_from_host(RTCState *s)
+static void rtc_set_date_from_host(ISADevice *dev)
 {
+    RTCState *s = DO_UPCAST(RTCState, dev, dev);
     struct tm tm;
     int val;
 
     /* set the CMOS date */
     qemu_get_timedate(&tm, 0);
-    rtc_set_date(s, &tm);
+    rtc_set_date(dev, &tm);
 
     val = rtc_to_bcd(s, (tm.tm_year / 100) + 19);
-    rtc_set_memory(s, REG_IBM_CENTURY_BYTE, val);
-    rtc_set_memory(s, REG_IBM_PS2_CENTURY_BYTE, val);
+    rtc_set_memory(dev, REG_IBM_CENTURY_BYTE, val);
+    rtc_set_memory(dev, REG_IBM_PS2_CENTURY_BYTE, val);
 }
 
 static int rtc_post_load(void *opaque, int version_id)
@@ -591,7 +595,7 @@ static int rtc_initfn(ISADevice *dev)
     s->cmos_data[RTC_REG_C] = 0x00;
     s->cmos_data[RTC_REG_D] = 0x80;
 
-    rtc_set_date_from_host(s);
+    rtc_set_date_from_host(dev);
 
     s->periodic_timer = qemu_new_timer(rtc_clock, rtc_periodic_timer, s);
 #ifdef TARGET_I386
@@ -614,14 +618,14 @@ static int rtc_initfn(ISADevice *dev)
     return 0;
 }
 
-RTCState *rtc_init(int base_year)
+ISADevice *rtc_init(int base_year)
 {
     ISADevice *dev;
 
     dev = isa_create("mc146818rtc");
     qdev_prop_set_int32(&dev->qdev, "base_year", base_year);
     qdev_init_nofail(&dev->qdev);
-    return DO_UPCAST(RTCState, dev, dev);
+    return dev;
 }
 
 static ISADeviceInfo mc146818rtc_info = {
diff --git a/hw/mc146818rtc.h b/hw/mc146818rtc.h
index 7211dae..6f46a68 100644
--- a/hw/mc146818rtc.h
+++ b/hw/mc146818rtc.h
@@ -1,10 +1,10 @@
 #ifndef MC146818RTC_H
 #define MC146818RTC_H
 
-typedef struct RTCState RTCState;
+#include "isa.h"
 
-RTCState *rtc_init(int base_year);
-void rtc_set_memory(RTCState *s, int addr, int val);
-void rtc_set_date(RTCState *s, const struct tm *tm);
+ISADevice *rtc_init(int base_year);
+void rtc_set_memory(ISADevice *dev, int addr, int val);
+void rtc_set_date(ISADevice *dev, const struct tm *tm);
 
 #endif /* !MC146818RTC_H */
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index 5609597..6e0ec8f 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -35,6 +35,7 @@
 #include "esp.h"
 #include "mips-bios.h"
 #include "loader.h"
+#include "mc146818rtc.h"
 
 enum jazz_model_e
 {
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 586c1c3..792709b 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -44,6 +44,7 @@
 #include "ide.h"
 #include "loader.h"
 #include "elf.h"
+#include "mc146818rtc.h"
 
 //#define DEBUG_BOARD_INIT
 
@@ -776,7 +777,7 @@ void mips_malta_init (ram_addr_t ram_size,
     PCIBus *pci_bus;
     ISADevice *isa_dev;
     CPUState *env;
-    RTCState *rtc_state;
+    ISADevice *rtc_state;
     FDCtrl *floppy_controller;
     MaltaFPGAState *malta_fpga;
     qemu_irq *i8259;
diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c
index 0d5e2a6..f1fcfcd 100644
--- a/hw/mips_r4k.c
+++ b/hw/mips_r4k.c
@@ -21,6 +21,7 @@
 #include "ide.h"
 #include "loader.h"
 #include "elf.h"
+#include "mc146818rtc.h"
 
 #define MAX_IDE_BUS 2
 
@@ -165,7 +166,7 @@ void mips_r4k_init (ram_addr_t ram_size,
     int bios_size;
     CPUState *env;
     ResetData *reset_info;
-    RTCState *rtc_state;
+    ISADevice *rtc_state;
     int i;
     qemu_irq *i8259;
     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
diff --git a/hw/pc.c b/hw/pc.c
index 4f65049..20dc7fd 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -34,6 +34,7 @@
 #include "loader.h"
 #include "elf.h"
 #include "multiboot.h"
+#include "mc146818rtc.h"
 
 /* output Bochs bios info messages */
 //#define DEBUG_BIOS
@@ -192,7 +193,7 @@ static int cmos_get_fd_drive_type(int fd0)
 }
 
 static void cmos_init_hd(int type_ofs, int info_ofs, BlockDriverState *hd,
-                         RTCState *s)
+                         ISADevice *s)
 {
     int cylinders, heads, sectors;
     bdrv_get_geometry_hint(hd, &cylinders, &heads, &sectors);
@@ -225,7 +226,7 @@ static int boot_device2nibble(char boot_device)
     return 0;
 }
 
-static int set_boot_dev(RTCState *s, const char *boot_device, int fd_bootchk)
+static int set_boot_dev(ISADevice *s, const char *boot_device, int fd_bootchk)
 {
 #define PC_MAX_BOOT_DEVICES 3
     int nbds, bds[3] = { 0, };
@@ -257,7 +258,7 @@ static int pc_boot_set(void *opaque, const char *boot_device)
 /* hd_table must contain 4 block drivers */
 void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
                   const char *boot_device, DriveInfo **hd_table,
-                  FDCtrl *floppy_controller, RTCState *s)
+                  FDCtrl *floppy_controller, ISADevice *s)
 {
     int val;
     int fd0, fd1, nb;
@@ -752,7 +753,7 @@ int cpu_is_bsp(CPUState *env)
    BIOS will read it and start S3 resume at POST Entry */
 void pc_cmos_set_s3_resume(void *opaque, int irq, int level)
 {
-    RTCState *s = opaque;
+    ISADevice *s = opaque;
 
     if (level) {
         rtc_set_memory(s, 0xF, 0xFE);
@@ -929,7 +930,7 @@ void pc_vga_init(PCIBus *pci_bus)
 
 void pc_basic_device_init(qemu_irq *isa_irq,
                           FDCtrl **floppy_controller,
-                          RTCState **rtc_state)
+                          ISADevice **rtc_state)
 {
     int i;
     DriveInfo *fd[MAX_FD];
diff --git a/hw/pc.h b/hw/pc.h
index e3cc0a5..2e2f4e2 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -5,7 +5,6 @@
 #include "ioport.h"
 #include "isa.h"
 #include "fdc.h"
-#include "mc146818rtc.h"
 
 /* PC-style peripherals (also used by other machines).  */
 
@@ -95,14 +94,14 @@ qemu_irq *pc_allocate_cpu_irq(void);
 void pc_vga_init(PCIBus *pci_bus);
 void pc_basic_device_init(qemu_irq *isa_irq,
                           FDCtrl **floppy_controller,
-                          RTCState **rtc_state);
+                          ISADevice **rtc_state);
 void pc_init_ne2k_isa(NICInfo *nd);
 #ifdef HAS_AUDIO
 void pc_audio_init (PCIBus *pci_bus, qemu_irq *pic);
 #endif
 void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
                   const char *boot_device, DriveInfo **hd_table,
-                  FDCtrl *floppy_controller, RTCState *s);
+                  FDCtrl *floppy_controller, ISADevice *s);
 void pc_pci_device_init(PCIBus *pci_bus);
 
 void ioport_set_a20(int enable);
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 52d8591..a0ed7ad 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -61,7 +61,7 @@ static void pc_init1(ram_addr_t ram_size,
     IsaIrqState *isa_irq_state;
     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
     FDCtrl *floppy_controller;
-    RTCState *rtc_state;
+    ISADevice *rtc_state;
 
     pc_cpus_init(cpu_model);
 
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index a5e25b5..09a9881 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -36,6 +36,7 @@
 #include "qemu-log.h"
 #include "ide.h"
 #include "loader.h"
+#include "mc146818rtc.h"
 
 //#define HARD_DEBUG_PPC_IO
 //#define DEBUG_PPC_IO
commit e1460e4707cd80982add597f5cb421289db84e4e
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri May 14 16:29:16 2010 +0900

    pc: move rtc declarations from pc.h into a dedicated header file.
    
    Move rtc_xxx declarations from pc.h into mc146818rtc.h.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/mc146818rtc.h b/hw/mc146818rtc.h
new file mode 100644
index 0000000..7211dae
--- /dev/null
+++ b/hw/mc146818rtc.h
@@ -0,0 +1,10 @@
+#ifndef MC146818RTC_H
+#define MC146818RTC_H
+
+typedef struct RTCState RTCState;
+
+RTCState *rtc_init(int base_year);
+void rtc_set_memory(RTCState *s, int addr, int val);
+void rtc_set_date(RTCState *s, const struct tm *tm);
+
+#endif /* !MC146818RTC_H */
diff --git a/hw/pc.h b/hw/pc.h
index 8cfec6c..e3cc0a5 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -5,6 +5,7 @@
 #include "ioport.h"
 #include "isa.h"
 #include "fdc.h"
+#include "mc146818rtc.h"
 
 /* PC-style peripherals (also used by other machines).  */
 
@@ -76,14 +77,6 @@ void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq,
                    target_phys_addr_t base, ram_addr_t size,
                    target_phys_addr_t mask);
 
-/* mc146818rtc.c */
-
-typedef struct RTCState RTCState;
-
-RTCState *rtc_init(int base_year);
-void rtc_set_memory(RTCState *s, int addr, int val);
-void rtc_set_date(RTCState *s, const struct tm *tm);
-
 /* pc.c */
 extern int fd_bootchk;
 
commit 845773ab03a8dde681ff1b929bbb41e67d0131a6
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri May 14 16:29:15 2010 +0900

    pc: split out piix specific part from pc.c into pc_piix.c
    
    Finally, we can safely split out the piix specific part from pc.c
    into pc_piix.c.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index 3998678..f2cd4ff 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -195,7 +195,7 @@ obj-i386-y += cirrus_vga.o apic.o ioapic.o piix_pci.o
 obj-i386-y += vmmouse.o vmport.o hpet.o
 obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
 obj-i386-y += debugcon.o multiboot.o
-obj-i386-y += pm_smbus.o apm.o acpi_piix4.o
+obj-i386-y += pm_smbus.o apm.o acpi_piix4.o pc_piix.o
 
 # shared objects
 obj-ppc-y = ppc.o
diff --git a/hw/fdc.h b/hw/fdc.h
index d173902..c48b5e0 100644
--- a/hw/fdc.h
+++ b/hw/fdc.h
@@ -1,3 +1,6 @@
+#ifndef HW_FDC_H
+#define HW_FDC_H
+
 /* fdc.c */
 #include "sysemu.h"
 #define MAX_FD 2
@@ -10,3 +13,5 @@ FDCtrl *fdctrl_init_sysbus(qemu_irq irq, int dma_chann,
 FDCtrl *sun4m_fdctrl_init(qemu_irq irq, target_phys_addr_t io_base,
                           DriveInfo **fds, qemu_irq *fdc_tc);
 int fdctrl_get_drive_type(FDCtrl *fdctrl, int drive_num);
+
+#endif
diff --git a/hw/pc.c b/hw/pc.c
index 5c8a11b..4f65049 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -27,26 +27,13 @@
 #include "fdc.h"
 #include "pci.h"
 #include "vmware_vga.h"
-#include "usb-uhci.h"
-#include "usb-ohci.h"
-#include "prep_pci.h"
-#include "apb_pci.h"
-#include "block.h"
-#include "sysemu.h"
-#include "audio/audio.h"
-#include "net.h"
-#include "smbus.h"
-#include "boards.h"
 #include "monitor.h"
 #include "fw_cfg.h"
 #include "hpet_emul.h"
-#include "watchdog.h"
 #include "smbios.h"
-#include "ide.h"
 #include "loader.h"
 #include "elf.h"
 #include "multiboot.h"
-#include "kvm.h"
 
 /* output Bochs bios info messages */
 //#define DEBUG_BIOS
@@ -63,8 +50,6 @@
 #define FW_CFG_IRQ0_OVERRIDE (FW_CFG_ARCH_LOCAL + 2)
 #define FW_CFG_E820_TABLE (FW_CFG_ARCH_LOCAL + 3)
 
-#define MAX_IDE_BUS 2
-
 #define E820_NR_ENTRIES		16
 
 struct e820_entry {
@@ -80,12 +65,7 @@ struct e820_table {
 
 static struct e820_table e820_table;
 
-typedef struct isa_irq_state {
-    qemu_irq *i8259;
-    qemu_irq *ioapic;
-} IsaIrqState;
-
-static void isa_irq_handler(void *opaque, int n, int level)
+void isa_irq_handler(void *opaque, int n, int level)
 {
     IsaIrqState *isa = (IsaIrqState *)opaque;
 
@@ -275,9 +255,9 @@ static int pc_boot_set(void *opaque, const char *boot_device)
 }
 
 /* hd_table must contain 4 block drivers */
-static void cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
-                      const char *boot_device, DriveInfo **hd_table,
-                      FDCtrl *floppy_controller, RTCState *s)
+void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
+                  const char *boot_device, DriveInfo **hd_table,
+                  FDCtrl *floppy_controller, RTCState *s)
 {
     int val;
     int fd0, fd1, nb;
@@ -723,10 +703,6 @@ static void load_linux(void *fw_cfg,
     nb_option_roms++;
 }
 
-static const int ide_iobase[2] = { 0x1f0, 0x170 };
-static const int ide_iobase2[2] = { 0x3f6, 0x376 };
-static const int ide_irq[2] = { 14, 15 };
-
 #define NE2000_NB_MAX 6
 
 static const int ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360,
@@ -737,7 +713,7 @@ static const int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc };
 static const int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };
 
 #ifdef HAS_AUDIO
-static void audio_init (PCIBus *pci_bus, qemu_irq *pic)
+void pc_audio_init (PCIBus *pci_bus, qemu_irq *pic)
 {
     struct soundhw *c;
 
@@ -755,7 +731,7 @@ static void audio_init (PCIBus *pci_bus, qemu_irq *pic)
 }
 #endif
 
-static void pc_init_ne2k_isa(NICInfo *nd)
+void pc_init_ne2k_isa(NICInfo *nd)
 {
     static int nb_ne2k = 0;
 
@@ -774,7 +750,7 @@ int cpu_is_bsp(CPUState *env)
 
 /* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE)
    BIOS will read it and start S3 resume at POST Entry */
-static void cmos_set_s3_resume(void *opaque, int irq, int level)
+void pc_cmos_set_s3_resume(void *opaque, int irq, int level)
 {
     RTCState *s = opaque;
 
@@ -783,7 +759,7 @@ static void cmos_set_s3_resume(void *opaque, int irq, int level)
     }
 }
 
-static void acpi_smi_interrupt(void *opaque, int irq, int level)
+void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
 {
     CPUState *s = opaque;
 
@@ -811,7 +787,7 @@ static CPUState *pc_new_cpu(const char *cpu_model)
     return env;
 }
 
-static void pc_cpus_init(const char *cpu_model)
+void pc_cpus_init(const char *cpu_model)
 {
     int i;
 
@@ -829,17 +805,12 @@ static void pc_cpus_init(const char *cpu_model)
     }
 }
 
-static qemu_irq *pc_allocate_cpu_irq(void)
-{
-    return qemu_allocate_irqs(pic_irq_request, NULL, 1);
-}
-
-static void pc_memory_init(ram_addr_t ram_size,
-                           const char *kernel_filename,
-                           const char *kernel_cmdline,
-                           const char *initrd_filename,
-                           ram_addr_t *below_4g_mem_size_p,
-                           ram_addr_t *above_4g_mem_size_p)
+void pc_memory_init(ram_addr_t ram_size,
+                    const char *kernel_filename,
+                    const char *kernel_cmdline,
+                    const char *initrd_filename,
+                    ram_addr_t *below_4g_mem_size_p,
+                    ram_addr_t *above_4g_mem_size_p)
 {
     char *filename;
     int ret, linux_boot, i;
@@ -929,7 +900,12 @@ static void pc_memory_init(ram_addr_t ram_size,
     }
 }
 
-static void pc_vga_init(PCIBus *pci_bus)
+qemu_irq *pc_allocate_cpu_irq(void)
+{
+    return qemu_allocate_irqs(pic_irq_request, NULL, 1);
+}
+
+void pc_vga_init(PCIBus *pci_bus)
 {
     if (cirrus_vga_enabled) {
         if (pci_bus) {
@@ -951,9 +927,9 @@ static void pc_vga_init(PCIBus *pci_bus)
     }
 }
 
-static void pc_basic_device_init(qemu_irq *isa_irq,
-                                 FDCtrl **floppy_controller,
-                                 RTCState **rtc_state)
+void pc_basic_device_init(qemu_irq *isa_irq,
+                          FDCtrl **floppy_controller,
+                          RTCState **rtc_state)
 {
     int i;
     DriveInfo *fd[MAX_FD];
@@ -997,7 +973,7 @@ static void pc_basic_device_init(qemu_irq *isa_irq,
     *floppy_controller = fdctrl_init_isa(fd);
 }
 
-static void pc_pci_device_init(PCIBus *pci_bus)
+void pc_pci_device_init(PCIBus *pci_bus)
 {
     int max_bus;
     int bus;
@@ -1007,280 +983,3 @@ static void pc_pci_device_init(PCIBus *pci_bus)
         pci_create_simple(pci_bus, -1, "lsi53c895a");
     }
 }
-
-/* PC hardware initialisation */
-static void pc_init1(ram_addr_t ram_size,
-                     const char *boot_device,
-                     const char *kernel_filename,
-                     const char *kernel_cmdline,
-                     const char *initrd_filename,
-                     const char *cpu_model,
-                     int pci_enabled)
-{
-    int i;
-    ram_addr_t below_4g_mem_size, above_4g_mem_size;
-    PCIBus *pci_bus;
-    PCII440FXState *i440fx_state;
-    int piix3_devfn = -1;
-    qemu_irq *cpu_irq;
-    qemu_irq *isa_irq;
-    qemu_irq *i8259;
-    qemu_irq *cmos_s3;
-    qemu_irq *smi_irq;
-    IsaIrqState *isa_irq_state;
-    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
-    FDCtrl *floppy_controller;
-    RTCState *rtc_state;
-
-    pc_cpus_init(cpu_model);
-
-    vmport_init();
-
-    /* allocate ram and load rom/bios */
-    pc_memory_init(ram_size, kernel_filename, kernel_cmdline, initrd_filename,
-                   &below_4g_mem_size, &above_4g_mem_size);
-
-    cpu_irq = pc_allocate_cpu_irq();
-    i8259 = i8259_init(cpu_irq[0]);
-    isa_irq_state = qemu_mallocz(sizeof(*isa_irq_state));
-    isa_irq_state->i8259 = i8259;
-    if (pci_enabled) {
-        isa_irq_state->ioapic = ioapic_init();
-    }
-    isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24);
-
-    if (pci_enabled) {
-        pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, isa_irq, ram_size);
-    } else {
-        pci_bus = NULL;
-        isa_bus_new(NULL);
-    }
-    isa_bus_irqs(isa_irq);
-
-    pc_register_ferr_irq(isa_reserve_irq(13));
-
-    pc_vga_init(pci_enabled? pci_bus: NULL);
-
-    /* init basic PC hardware */
-    pc_basic_device_init(isa_irq, &floppy_controller, &rtc_state);
-
-    for(i = 0; i < nb_nics; i++) {
-        NICInfo *nd = &nd_table[i];
-
-        if (!pci_enabled || (nd->model && strcmp(nd->model, "ne2k_isa") == 0))
-            pc_init_ne2k_isa(nd);
-        else
-            pci_nic_init_nofail(nd, "e1000", NULL);
-    }
-
-    if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
-        fprintf(stderr, "qemu: too many IDE bus\n");
-        exit(1);
-    }
-
-    for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
-        hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
-    }
-
-    if (pci_enabled) {
-        pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1);
-    } else {
-        for(i = 0; i < MAX_IDE_BUS; i++) {
-            isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
-	                 hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
-        }
-    }
-
-#ifdef HAS_AUDIO
-    audio_init(pci_enabled ? pci_bus : NULL, isa_irq);
-#endif
-
-    cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd,
-              floppy_controller, rtc_state);
-
-    if (pci_enabled && usb_enabled) {
-        usb_uhci_piix3_init(pci_bus, piix3_devfn + 2);
-    }
-
-    if (pci_enabled && acpi_enabled) {
-        uint8_t *eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
-        i2c_bus *smbus;
-
-        cmos_s3 = qemu_allocate_irqs(cmos_set_s3_resume, rtc_state, 1);
-        smi_irq = qemu_allocate_irqs(acpi_smi_interrupt, first_cpu, 1);
-        /* TODO: Populate SPD eeprom data.  */
-        smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
-                              isa_reserve_irq(9), *cmos_s3, *smi_irq,
-                              kvm_enabled());
-        for (i = 0; i < 8; i++) {
-            DeviceState *eeprom;
-            eeprom = qdev_create((BusState *)smbus, "smbus-eeprom");
-            qdev_prop_set_uint8(eeprom, "address", 0x50 + i);
-            qdev_prop_set_ptr(eeprom, "data", eeprom_buf + (i * 256));
-            qdev_init_nofail(eeprom);
-        }
-        piix4_acpi_system_hot_add_init(pci_bus);
-    }
-
-    if (i440fx_state) {
-        i440fx_init_memory_mappings(i440fx_state);
-    }
-
-    if (pci_enabled) {
-        pc_pci_device_init(pci_bus);
-    }
-}
-
-static void pc_init_pci(ram_addr_t ram_size,
-                        const char *boot_device,
-                        const char *kernel_filename,
-                        const char *kernel_cmdline,
-                        const char *initrd_filename,
-                        const char *cpu_model)
-{
-    pc_init1(ram_size, boot_device,
-             kernel_filename, kernel_cmdline,
-             initrd_filename, cpu_model, 1);
-}
-
-static void pc_init_isa(ram_addr_t ram_size,
-                        const char *boot_device,
-                        const char *kernel_filename,
-                        const char *kernel_cmdline,
-                        const char *initrd_filename,
-                        const char *cpu_model)
-{
-    if (cpu_model == NULL)
-        cpu_model = "486";
-    pc_init1(ram_size, boot_device,
-             kernel_filename, kernel_cmdline,
-             initrd_filename, cpu_model, 0);
-}
-
-static QEMUMachine pc_machine = {
-    .name = "pc-0.13",
-    .alias = "pc",
-    .desc = "Standard PC",
-    .init = pc_init_pci,
-    .max_cpus = 255,
-    .is_default = 1,
-};
-
-static QEMUMachine pc_machine_v0_12 = {
-    .name = "pc-0.12",
-    .desc = "Standard PC",
-    .init = pc_init_pci,
-    .max_cpus = 255,
-    .compat_props = (GlobalProperty[]) {
-        {
-            .driver   = "virtio-serial-pci",
-            .property = "max_nr_ports",
-            .value    = stringify(1),
-        },{
-            .driver   = "virtio-serial-pci",
-            .property = "vectors",
-            .value    = stringify(0),
-        },
-        { /* end of list */ }
-    }
-};
-
-static QEMUMachine pc_machine_v0_11 = {
-    .name = "pc-0.11",
-    .desc = "Standard PC, qemu 0.11",
-    .init = pc_init_pci,
-    .max_cpus = 255,
-    .compat_props = (GlobalProperty[]) {
-        {
-            .driver   = "virtio-blk-pci",
-            .property = "vectors",
-            .value    = stringify(0),
-        },{
-            .driver   = "virtio-serial-pci",
-            .property = "max_nr_ports",
-            .value    = stringify(1),
-        },{
-            .driver   = "virtio-serial-pci",
-            .property = "vectors",
-            .value    = stringify(0),
-        },{
-            .driver   = "ide-drive",
-            .property = "ver",
-            .value    = "0.11",
-        },{
-            .driver   = "scsi-disk",
-            .property = "ver",
-            .value    = "0.11",
-        },{
-            .driver   = "PCI",
-            .property = "rombar",
-            .value    = stringify(0),
-        },
-        { /* end of list */ }
-    }
-};
-
-static QEMUMachine pc_machine_v0_10 = {
-    .name = "pc-0.10",
-    .desc = "Standard PC, qemu 0.10",
-    .init = pc_init_pci,
-    .max_cpus = 255,
-    .compat_props = (GlobalProperty[]) {
-        {
-            .driver   = "virtio-blk-pci",
-            .property = "class",
-            .value    = stringify(PCI_CLASS_STORAGE_OTHER),
-        },{
-            .driver   = "virtio-serial-pci",
-            .property = "class",
-            .value    = stringify(PCI_CLASS_DISPLAY_OTHER),
-        },{
-            .driver   = "virtio-serial-pci",
-            .property = "max_nr_ports",
-            .value    = stringify(1),
-        },{
-            .driver   = "virtio-serial-pci",
-            .property = "vectors",
-            .value    = stringify(0),
-        },{
-            .driver   = "virtio-net-pci",
-            .property = "vectors",
-            .value    = stringify(0),
-        },{
-            .driver   = "virtio-blk-pci",
-            .property = "vectors",
-            .value    = stringify(0),
-        },{
-            .driver   = "ide-drive",
-            .property = "ver",
-            .value    = "0.10",
-        },{
-            .driver   = "scsi-disk",
-            .property = "ver",
-            .value    = "0.10",
-        },{
-            .driver   = "PCI",
-            .property = "rombar",
-            .value    = stringify(0),
-        },
-        { /* end of list */ }
-    },
-};
-
-static QEMUMachine isapc_machine = {
-    .name = "isapc",
-    .desc = "ISA-only PC",
-    .init = pc_init_isa,
-    .max_cpus = 1,
-};
-
-static void pc_machine_init(void)
-{
-    qemu_register_machine(&pc_machine);
-    qemu_register_machine(&pc_machine_v0_12);
-    qemu_register_machine(&pc_machine_v0_11);
-    qemu_register_machine(&pc_machine_v0_10);
-    qemu_register_machine(&isapc_machine);
-}
-
-machine_init(pc_machine_init);
diff --git a/hw/pc.h b/hw/pc.h
index abf02de..8cfec6c 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -3,6 +3,8 @@
 
 #include "qemu-common.h"
 #include "ioport.h"
+#include "isa.h"
+#include "fdc.h"
 
 /* PC-style peripherals (also used by other machines).  */
 
@@ -36,6 +38,14 @@ uint32_t pic_intack_read(PicState2 *s);
 void pic_info(Monitor *mon);
 void irq_info(Monitor *mon);
 
+/* ISA */
+typedef struct isa_irq_state {
+    qemu_irq *i8259;
+    qemu_irq *ioapic;
+} IsaIrqState;
+
+void isa_irq_handler(void *opaque, int n, int level);
+
 /* i8254.c */
 
 #define PIT_FREQ 1193182
@@ -78,6 +88,29 @@ void rtc_set_date(RTCState *s, const struct tm *tm);
 extern int fd_bootchk;
 
 void pc_register_ferr_irq(qemu_irq irq);
+void pc_cmos_set_s3_resume(void *opaque, int irq, int level);
+void pc_acpi_smi_interrupt(void *opaque, int irq, int level);
+
+void pc_cpus_init(const char *cpu_model);
+void pc_memory_init(ram_addr_t ram_size,
+                    const char *kernel_filename,
+                    const char *kernel_cmdline,
+                    const char *initrd_filename,
+                    ram_addr_t *below_4g_mem_size_p,
+                    ram_addr_t *above_4g_mem_size_p);
+qemu_irq *pc_allocate_cpu_irq(void);
+void pc_vga_init(PCIBus *pci_bus);
+void pc_basic_device_init(qemu_irq *isa_irq,
+                          FDCtrl **floppy_controller,
+                          RTCState **rtc_state);
+void pc_init_ne2k_isa(NICInfo *nd);
+#ifdef HAS_AUDIO
+void pc_audio_init (PCIBus *pci_bus, qemu_irq *pic);
+#endif
+void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
+                  const char *boot_device, DriveInfo **hd_table,
+                  FDCtrl *floppy_controller, RTCState *s);
+void pc_pci_device_init(PCIBus *pci_bus);
 
 void ioport_set_a20(int enable);
 int ioport_get_a20(void);
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
new file mode 100644
index 0000000..52d8591
--- /dev/null
+++ b/hw/pc_piix.c
@@ -0,0 +1,317 @@
+/*
+ * QEMU PC System Emulator
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw.h"
+#include "pc.h"
+#include "apic.h"
+#include "pci.h"
+#include "usb-uhci.h"
+#include "usb-ohci.h"
+#include "net.h"
+#include "boards.h"
+#include "ide.h"
+#include "kvm.h"
+
+#define MAX_IDE_BUS 2
+
+static const int ide_iobase[MAX_IDE_BUS] = { 0x1f0, 0x170 };
+static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 };
+static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
+
+/* PC hardware initialisation */
+static void pc_init1(ram_addr_t ram_size,
+                     const char *boot_device,
+                     const char *kernel_filename,
+                     const char *kernel_cmdline,
+                     const char *initrd_filename,
+                     const char *cpu_model,
+                     int pci_enabled)
+{
+    int i;
+    ram_addr_t below_4g_mem_size, above_4g_mem_size;
+    PCIBus *pci_bus;
+    PCII440FXState *i440fx_state;
+    int piix3_devfn = -1;
+    qemu_irq *cpu_irq;
+    qemu_irq *isa_irq;
+    qemu_irq *i8259;
+    qemu_irq *cmos_s3;
+    qemu_irq *smi_irq;
+    IsaIrqState *isa_irq_state;
+    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
+    FDCtrl *floppy_controller;
+    RTCState *rtc_state;
+
+    pc_cpus_init(cpu_model);
+
+    vmport_init();
+
+    /* allocate ram and load rom/bios */
+    pc_memory_init(ram_size, kernel_filename, kernel_cmdline, initrd_filename,
+                   &below_4g_mem_size, &above_4g_mem_size);
+
+    cpu_irq = pc_allocate_cpu_irq();
+    i8259 = i8259_init(cpu_irq[0]);
+    isa_irq_state = qemu_mallocz(sizeof(*isa_irq_state));
+    isa_irq_state->i8259 = i8259;
+    if (pci_enabled) {
+        isa_irq_state->ioapic = ioapic_init();
+    }
+    isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24);
+
+    if (pci_enabled) {
+        pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, isa_irq, ram_size);
+    } else {
+        pci_bus = NULL;
+        isa_bus_new(NULL);
+    }
+    isa_bus_irqs(isa_irq);
+
+    pc_register_ferr_irq(isa_reserve_irq(13));
+
+    pc_vga_init(pci_enabled? pci_bus: NULL);
+
+    /* init basic PC hardware */
+    pc_basic_device_init(isa_irq, &floppy_controller, &rtc_state);
+
+    for(i = 0; i < nb_nics; i++) {
+        NICInfo *nd = &nd_table[i];
+
+        if (!pci_enabled || (nd->model && strcmp(nd->model, "ne2k_isa") == 0))
+            pc_init_ne2k_isa(nd);
+        else
+            pci_nic_init_nofail(nd, "e1000", NULL);
+    }
+
+    if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
+        fprintf(stderr, "qemu: too many IDE bus\n");
+        exit(1);
+    }
+
+    for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
+        hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
+    }
+
+    if (pci_enabled) {
+        pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1);
+    } else {
+        for(i = 0; i < MAX_IDE_BUS; i++) {
+            isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
+	                 hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
+        }
+    }
+
+#ifdef HAS_AUDIO
+    pc_audio_init(pci_enabled ? pci_bus : NULL, isa_irq);
+#endif
+
+    pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd,
+                 floppy_controller, rtc_state);
+
+    if (pci_enabled && usb_enabled) {
+        usb_uhci_piix3_init(pci_bus, piix3_devfn + 2);
+    }
+
+    if (pci_enabled && acpi_enabled) {
+        uint8_t *eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
+        i2c_bus *smbus;
+
+        cmos_s3 = qemu_allocate_irqs(pc_cmos_set_s3_resume, rtc_state, 1);
+        smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt, first_cpu, 1);
+        /* TODO: Populate SPD eeprom data.  */
+        smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
+                              isa_reserve_irq(9), *cmos_s3, *smi_irq,
+                              kvm_enabled());
+        for (i = 0; i < 8; i++) {
+            DeviceState *eeprom;
+            eeprom = qdev_create((BusState *)smbus, "smbus-eeprom");
+            qdev_prop_set_uint8(eeprom, "address", 0x50 + i);
+            qdev_prop_set_ptr(eeprom, "data", eeprom_buf + (i * 256));
+            qdev_init_nofail(eeprom);
+        }
+        piix4_acpi_system_hot_add_init(pci_bus);
+    }
+
+    if (i440fx_state) {
+        i440fx_init_memory_mappings(i440fx_state);
+    }
+
+    if (pci_enabled) {
+        pc_pci_device_init(pci_bus);
+    }
+}
+
+static void pc_init_pci(ram_addr_t ram_size,
+                        const char *boot_device,
+                        const char *kernel_filename,
+                        const char *kernel_cmdline,
+                        const char *initrd_filename,
+                        const char *cpu_model)
+{
+    pc_init1(ram_size, boot_device,
+             kernel_filename, kernel_cmdline,
+             initrd_filename, cpu_model, 1);
+}
+
+static void pc_init_isa(ram_addr_t ram_size,
+                        const char *boot_device,
+                        const char *kernel_filename,
+                        const char *kernel_cmdline,
+                        const char *initrd_filename,
+                        const char *cpu_model)
+{
+    if (cpu_model == NULL)
+        cpu_model = "486";
+    pc_init1(ram_size, boot_device,
+             kernel_filename, kernel_cmdline,
+             initrd_filename, cpu_model, 0);
+}
+
+static QEMUMachine pc_machine = {
+    .name = "pc-0.13",
+    .alias = "pc",
+    .desc = "Standard PC",
+    .init = pc_init_pci,
+    .max_cpus = 255,
+    .is_default = 1,
+};
+
+static QEMUMachine pc_machine_v0_12 = {
+    .name = "pc-0.12",
+    .desc = "Standard PC",
+    .init = pc_init_pci,
+    .max_cpus = 255,
+    .compat_props = (GlobalProperty[]) {
+        {
+            .driver   = "virtio-serial-pci",
+            .property = "max_nr_ports",
+            .value    = stringify(1),
+        },{
+            .driver   = "virtio-serial-pci",
+            .property = "vectors",
+            .value    = stringify(0),
+        },
+        { /* end of list */ }
+    }
+};
+
+static QEMUMachine pc_machine_v0_11 = {
+    .name = "pc-0.11",
+    .desc = "Standard PC, qemu 0.11",
+    .init = pc_init_pci,
+    .max_cpus = 255,
+    .compat_props = (GlobalProperty[]) {
+        {
+            .driver   = "virtio-blk-pci",
+            .property = "vectors",
+            .value    = stringify(0),
+        },{
+            .driver   = "virtio-serial-pci",
+            .property = "max_nr_ports",
+            .value    = stringify(1),
+        },{
+            .driver   = "virtio-serial-pci",
+            .property = "vectors",
+            .value    = stringify(0),
+        },{
+            .driver   = "ide-drive",
+            .property = "ver",
+            .value    = "0.11",
+        },{
+            .driver   = "scsi-disk",
+            .property = "ver",
+            .value    = "0.11",
+        },{
+            .driver   = "PCI",
+            .property = "rombar",
+            .value    = stringify(0),
+        },
+        { /* end of list */ }
+    }
+};
+
+static QEMUMachine pc_machine_v0_10 = {
+    .name = "pc-0.10",
+    .desc = "Standard PC, qemu 0.10",
+    .init = pc_init_pci,
+    .max_cpus = 255,
+    .compat_props = (GlobalProperty[]) {
+        {
+            .driver   = "virtio-blk-pci",
+            .property = "class",
+            .value    = stringify(PCI_CLASS_STORAGE_OTHER),
+        },{
+            .driver   = "virtio-serial-pci",
+            .property = "class",
+            .value    = stringify(PCI_CLASS_DISPLAY_OTHER),
+        },{
+            .driver   = "virtio-serial-pci",
+            .property = "max_nr_ports",
+            .value    = stringify(1),
+        },{
+            .driver   = "virtio-serial-pci",
+            .property = "vectors",
+            .value    = stringify(0),
+        },{
+            .driver   = "virtio-net-pci",
+            .property = "vectors",
+            .value    = stringify(0),
+        },{
+            .driver   = "virtio-blk-pci",
+            .property = "vectors",
+            .value    = stringify(0),
+        },{
+            .driver   = "ide-drive",
+            .property = "ver",
+            .value    = "0.10",
+        },{
+            .driver   = "scsi-disk",
+            .property = "ver",
+            .value    = "0.10",
+        },{
+            .driver   = "PCI",
+            .property = "rombar",
+            .value    = stringify(0),
+        },
+        { /* end of list */ }
+    },
+};
+
+static QEMUMachine isapc_machine = {
+    .name = "isapc",
+    .desc = "ISA-only PC",
+    .init = pc_init_isa,
+    .max_cpus = 1,
+};
+
+static void pc_machine_init(void)
+{
+    qemu_register_machine(&pc_machine);
+    qemu_register_machine(&pc_machine_v0_12);
+    qemu_register_machine(&pc_machine_v0_11);
+    qemu_register_machine(&pc_machine_v0_10);
+    qemu_register_machine(&isapc_machine);
+}
+
+machine_init(pc_machine_init);
commit e3a5cf425032e03930a650788332e3d0ff8fc9c7
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri May 14 16:29:14 2010 +0900

    pc: split out pci device init from pc_init1() into pc_pci_device_init()
    
    Split out pci device initialization from pc_init1() into pc_pci_device_init().
    and removed unnecessary braces.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/pc.c b/hw/pc.c
index d820a51..5c8a11b 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -997,6 +997,17 @@ static void pc_basic_device_init(qemu_irq *isa_irq,
     *floppy_controller = fdctrl_init_isa(fd);
 }
 
+static void pc_pci_device_init(PCIBus *pci_bus)
+{
+    int max_bus;
+    int bus;
+
+    max_bus = drive_get_max_bus(IF_SCSI);
+    for (bus = 0; bus <= max_bus; bus++) {
+        pci_create_simple(pci_bus, -1, "lsi53c895a");
+    }
+}
+
 /* PC hardware initialisation */
 static void pc_init1(ram_addr_t ram_size,
                      const char *boot_device,
@@ -1116,13 +1127,7 @@ static void pc_init1(ram_addr_t ram_size,
     }
 
     if (pci_enabled) {
-	int max_bus;
-        int bus;
-
-        max_bus = drive_get_max_bus(IF_SCSI);
-	for (bus = 0; bus <= max_bus; bus++) {
-            pci_create_simple(pci_bus, -1, "lsi53c895a");
-        }
+        pc_pci_device_init(pci_bus);
     }
 }
 
commit ffe513da92c3ebbe47c6eab761146db4fcaf7883
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri May 14 16:29:13 2010 +0900

    pc: split out basic device init from pc_init1() into pc_basic_device_init()
    
    Split out basic device, i.e. legacy devices like floppy, initialization
    from pc_init1() into pc_basic_device_init().
    Later it will be used.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/pc.c b/hw/pc.c
index 53df13d..d820a51 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -951,6 +951,52 @@ static void pc_vga_init(PCIBus *pci_bus)
     }
 }
 
+static void pc_basic_device_init(qemu_irq *isa_irq,
+                                 FDCtrl **floppy_controller,
+                                 RTCState **rtc_state)
+{
+    int i;
+    DriveInfo *fd[MAX_FD];
+    PITState *pit;
+
+    register_ioport_write(0x80, 1, 1, ioport80_write, NULL);
+
+    register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
+
+    *rtc_state = rtc_init(2000);
+
+    qemu_register_boot_set(pc_boot_set, *rtc_state);
+
+    register_ioport_read(0x92, 1, 1, ioport92_read, NULL);
+    register_ioport_write(0x92, 1, 1, ioport92_write, NULL);
+
+    pit = pit_init(0x40, isa_reserve_irq(0));
+    pcspk_init(pit);
+    if (!no_hpet) {
+        hpet_init(isa_irq);
+    }
+
+    for(i = 0; i < MAX_SERIAL_PORTS; i++) {
+        if (serial_hds[i]) {
+            serial_isa_init(i, serial_hds[i]);
+        }
+    }
+
+    for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
+        if (parallel_hds[i]) {
+            parallel_init(i, parallel_hds[i]);
+        }
+    }
+
+    isa_create_simple("i8042");
+    DMA_init(0);
+
+    for(i = 0; i < MAX_FD; i++) {
+        fd[i] = drive_get(IF_FLOPPY, 0, i);
+    }
+    *floppy_controller = fdctrl_init_isa(fd);
+}
+
 /* PC hardware initialisation */
 static void pc_init1(ram_addr_t ram_size,
                      const char *boot_device,
@@ -972,10 +1018,8 @@ static void pc_init1(ram_addr_t ram_size,
     qemu_irq *smi_irq;
     IsaIrqState *isa_irq_state;
     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
-    DriveInfo *fd[MAX_FD];
     FDCtrl *floppy_controller;
     RTCState *rtc_state;
-    PITState *pit;
 
     pc_cpus_init(cpu_model);
 
@@ -1004,37 +1048,10 @@ static void pc_init1(ram_addr_t ram_size,
 
     pc_register_ferr_irq(isa_reserve_irq(13));
 
-    /* init basic PC hardware */
-    register_ioport_write(0x80, 1, 1, ioport80_write, NULL);
-
-    register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
-
     pc_vga_init(pci_enabled? pci_bus: NULL);
 
-    rtc_state = rtc_init(2000);
-
-    qemu_register_boot_set(pc_boot_set, rtc_state);
-
-    register_ioport_read(0x92, 1, 1, ioport92_read, NULL);
-    register_ioport_write(0x92, 1, 1, ioport92_write, NULL);
-
-    pit = pit_init(0x40, isa_reserve_irq(0));
-    pcspk_init(pit);
-    if (!no_hpet) {
-        hpet_init(isa_irq);
-    }
-
-    for(i = 0; i < MAX_SERIAL_PORTS; i++) {
-        if (serial_hds[i]) {
-            serial_isa_init(i, serial_hds[i]);
-        }
-    }
-
-    for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
-        if (parallel_hds[i]) {
-            parallel_init(i, parallel_hds[i]);
-        }
-    }
+    /* init basic PC hardware */
+    pc_basic_device_init(isa_irq, &floppy_controller, &rtc_state);
 
     for(i = 0; i < nb_nics; i++) {
         NICInfo *nd = &nd_table[i];
@@ -1063,17 +1080,10 @@ static void pc_init1(ram_addr_t ram_size,
         }
     }
 
-    isa_create_simple("i8042");
-    DMA_init(0);
 #ifdef HAS_AUDIO
     audio_init(pci_enabled ? pci_bus : NULL, isa_irq);
 #endif
 
-    for(i = 0; i < MAX_FD; i++) {
-        fd[i] = drive_get(IF_FLOPPY, 0, i);
-    }
-    floppy_controller = fdctrl_init_isa(fd);
-
     cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd,
               floppy_controller, rtc_state);
 
commit 765d79084b6a4666603d057a7602cdcf2a5c9415
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri May 14 16:29:12 2010 +0900

    pc: split out vga initialization from pc_init1() into pc_vga_init().
    
    Split out vga initialization which is independent of piix
    from pc_init1() as pc_vga_init().
    Later it will be used.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/pc.c b/hw/pc.c
index 2e37c63..53df13d 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -929,6 +929,28 @@ static void pc_memory_init(ram_addr_t ram_size,
     }
 }
 
+static void pc_vga_init(PCIBus *pci_bus)
+{
+    if (cirrus_vga_enabled) {
+        if (pci_bus) {
+            pci_cirrus_vga_init(pci_bus);
+        } else {
+            isa_cirrus_vga_init();
+        }
+    } else if (vmsvga_enabled) {
+        if (pci_bus)
+            pci_vmsvga_init(pci_bus);
+        else
+            fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __FUNCTION__);
+    } else if (std_vga_enabled) {
+        if (pci_bus) {
+            pci_vga_init(pci_bus, 0, 0);
+        } else {
+            isa_vga_init();
+        }
+    }
+}
+
 /* PC hardware initialisation */
 static void pc_init1(ram_addr_t ram_size,
                      const char *boot_device,
@@ -987,24 +1009,7 @@ static void pc_init1(ram_addr_t ram_size,
 
     register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
 
-    if (cirrus_vga_enabled) {
-        if (pci_enabled) {
-            pci_cirrus_vga_init(pci_bus);
-        } else {
-            isa_cirrus_vga_init();
-        }
-    } else if (vmsvga_enabled) {
-        if (pci_enabled)
-            pci_vmsvga_init(pci_bus);
-        else
-            fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __FUNCTION__);
-    } else if (std_vga_enabled) {
-        if (pci_enabled) {
-            pci_vga_init(pci_bus, 0, 0);
-        } else {
-            isa_vga_init();
-        }
-    }
+    pc_vga_init(pci_enabled? pci_bus: NULL);
 
     rtc_state = rtc_init(2000);
 
commit 3d53f5c36ff692ea379c34e185c153d3d3244c39
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri May 14 16:29:11 2010 +0900

    pc: split out memory allocation from pc_init1() into pc_memory_init()
    
    Split out memory allocation and rom/bios loading which doesn't depend
    on piix from pc_init1() into pc_memory_init().
    Later it will be used.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/pc.c b/hw/pc.c
index 9f720df..2e37c63 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -834,35 +834,19 @@ static qemu_irq *pc_allocate_cpu_irq(void)
     return qemu_allocate_irqs(pic_irq_request, NULL, 1);
 }
 
-/* PC hardware initialisation */
-static void pc_init1(ram_addr_t ram_size,
-                     const char *boot_device,
-                     const char *kernel_filename,
-                     const char *kernel_cmdline,
-                     const char *initrd_filename,
-                     const char *cpu_model,
-                     int pci_enabled)
+static void pc_memory_init(ram_addr_t ram_size,
+                           const char *kernel_filename,
+                           const char *kernel_cmdline,
+                           const char *initrd_filename,
+                           ram_addr_t *below_4g_mem_size_p,
+                           ram_addr_t *above_4g_mem_size_p)
 {
     char *filename;
     int ret, linux_boot, i;
     ram_addr_t ram_addr, bios_offset, option_rom_offset;
     ram_addr_t below_4g_mem_size, above_4g_mem_size = 0;
     int bios_size, isa_bios_size;
-    PCIBus *pci_bus;
-    PCII440FXState *i440fx_state;
-    int piix3_devfn = -1;
-    qemu_irq *cpu_irq;
-    qemu_irq *isa_irq;
-    qemu_irq *i8259;
-    qemu_irq *cmos_s3;
-    qemu_irq *smi_irq;
-    IsaIrqState *isa_irq_state;
-    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
-    DriveInfo *fd[MAX_FD];
-    void *fw_cfg;
-    FDCtrl *floppy_controller;
-    RTCState *rtc_state;
-    PITState *pit;
+    void **fw_cfg;
 
     if (ram_size >= 0xe0000000 ) {
         above_4g_mem_size = ram_size - 0xe0000000;
@@ -870,13 +854,11 @@ static void pc_init1(ram_addr_t ram_size,
     } else {
         below_4g_mem_size = ram_size;
     }
+    *above_4g_mem_size_p = above_4g_mem_size;
+    *below_4g_mem_size_p = below_4g_mem_size;
 
     linux_boot = (kernel_filename != NULL);
 
-    pc_cpus_init(cpu_model);
-
-    vmport_init();
-
     /* allocate RAM */
     ram_addr = qemu_ram_alloc(below_4g_mem_size);
     cpu_register_physical_memory(0, 0xa0000, ram_addr);
@@ -939,12 +921,47 @@ static void pc_init1(ram_addr_t ram_size,
     rom_set_fw(fw_cfg);
 
     if (linux_boot) {
-        load_linux(fw_cfg, kernel_filename, initrd_filename, kernel_cmdline, below_4g_mem_size);
+        load_linux(*fw_cfg, kernel_filename, initrd_filename, kernel_cmdline, below_4g_mem_size);
     }
 
     for (i = 0; i < nb_option_roms; i++) {
         rom_add_option(option_rom[i]);
     }
+}
+
+/* PC hardware initialisation */
+static void pc_init1(ram_addr_t ram_size,
+                     const char *boot_device,
+                     const char *kernel_filename,
+                     const char *kernel_cmdline,
+                     const char *initrd_filename,
+                     const char *cpu_model,
+                     int pci_enabled)
+{
+    int i;
+    ram_addr_t below_4g_mem_size, above_4g_mem_size;
+    PCIBus *pci_bus;
+    PCII440FXState *i440fx_state;
+    int piix3_devfn = -1;
+    qemu_irq *cpu_irq;
+    qemu_irq *isa_irq;
+    qemu_irq *i8259;
+    qemu_irq *cmos_s3;
+    qemu_irq *smi_irq;
+    IsaIrqState *isa_irq_state;
+    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
+    DriveInfo *fd[MAX_FD];
+    FDCtrl *floppy_controller;
+    RTCState *rtc_state;
+    PITState *pit;
+
+    pc_cpus_init(cpu_model);
+
+    vmport_init();
+
+    /* allocate ram and load rom/bios */
+    pc_memory_init(ram_size, kernel_filename, kernel_cmdline, initrd_filename,
+                   &below_4g_mem_size, &above_4g_mem_size);
 
     cpu_irq = pc_allocate_cpu_irq();
     i8259 = i8259_init(cpu_irq[0]);
commit 70166477269d6cb9978a60ede1d570656987d15c
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri May 14 16:29:10 2010 +0900

    pc: split out cpu initialization from pc_init1() into pc_cpus_init().
    
    split out cpu initialization which is piix independent from pc_init1()
    into pc_cpus_init(). Later it will be used.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/pc.c b/hw/pc.c
index 18c025b..9f720df 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -811,6 +811,24 @@ static CPUState *pc_new_cpu(const char *cpu_model)
     return env;
 }
 
+static void pc_cpus_init(const char *cpu_model)
+{
+    int i;
+
+    /* init CPUs */
+    if (cpu_model == NULL) {
+#ifdef TARGET_X86_64
+        cpu_model = "qemu64";
+#else
+        cpu_model = "qemu32";
+#endif
+    }
+
+    for(i = 0; i < smp_cpus; i++) {
+        pc_new_cpu(cpu_model);
+    }
+}
+
 static qemu_irq *pc_allocate_cpu_irq(void)
 {
     return qemu_allocate_irqs(pic_irq_request, NULL, 1);
@@ -855,18 +873,7 @@ static void pc_init1(ram_addr_t ram_size,
 
     linux_boot = (kernel_filename != NULL);
 
-    /* init CPUs */
-    if (cpu_model == NULL) {
-#ifdef TARGET_X86_64
-        cpu_model = "qemu64";
-#else
-        cpu_model = "qemu32";
-#endif
-    }
-
-    for (i = 0; i < smp_cpus; i++) {
-        pc_new_cpu(cpu_model);
-    }
+    pc_cpus_init(cpu_model);
 
     vmport_init();
 
commit 8e78eb28c6bc532f103857ca485ea4976b3514da
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri May 14 16:29:09 2010 +0900

    pc: make pc_init1() not refer ferr_irq directly.
    
    By introducing a registering function, make pc_init1() not refer to
    ferr_irq directly in order to make ferr_irq piix independent.
    Later pc_init1() will be split out into another file keeping ferr_irq
    static.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/pc.c b/hw/pc.c
index fa11477..18c025b 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -102,6 +102,12 @@ static void ioport80_write(void *opaque, uint32_t addr, uint32_t data)
 
 /* MSDOS compatibility mode FPU exception support */
 static qemu_irq ferr_irq;
+
+void pc_register_ferr_irq(qemu_irq irq)
+{
+    ferr_irq = irq;
+}
+
 /* XXX: add IGNNE support */
 void cpu_set_ferr(CPUX86State *s)
 {
@@ -950,7 +956,7 @@ static void pc_init1(ram_addr_t ram_size,
     }
     isa_bus_irqs(isa_irq);
 
-    ferr_irq = isa_reserve_irq(13);
+    pc_register_ferr_irq(isa_reserve_irq(13));
 
     /* init basic PC hardware */
     register_ioport_write(0x80, 1, 1, ioport80_write, NULL);
diff --git a/hw/pc.h b/hw/pc.h
index 77239a0..abf02de 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -77,6 +77,8 @@ void rtc_set_date(RTCState *s, const struct tm *tm);
 /* pc.c */
 extern int fd_bootchk;
 
+void pc_register_ferr_irq(qemu_irq irq);
+
 void ioport_set_a20(int enable);
 int ioport_get_a20(void);
 
commit 6f09e686f807611aa03a91e37e9fb5cfc5283703
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri May 14 16:29:08 2010 +0900

    pc: introduce a function to allocate cpu irq.
    
    Introduce a function, pc_allocate_cpu_irq(), to allocate cpu irq
    in order to make pic_irq_request() piix independent.
    Later piix code will be split out to another file keeping pic_irq_request()
    static.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/pc.c b/hw/pc.c
index c88158c..fa11477 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -805,6 +805,11 @@ static CPUState *pc_new_cpu(const char *cpu_model)
     return env;
 }
 
+static qemu_irq *pc_allocate_cpu_irq(void)
+{
+    return qemu_allocate_irqs(pic_irq_request, NULL, 1);
+}
+
 /* PC hardware initialisation */
 static void pc_init1(ram_addr_t ram_size,
                      const char *boot_device,
@@ -928,7 +933,7 @@ static void pc_init1(ram_addr_t ram_size,
         rom_add_option(option_rom[i]);
     }
 
-    cpu_irq = qemu_allocate_irqs(pic_irq_request, NULL, 1);
+    cpu_irq = pc_allocate_cpu_irq();
     i8259 = i8259_init(cpu_irq[0]);
     isa_irq_state = qemu_mallocz(sizeof(*isa_irq_state));
     isa_irq_state->i8259 = i8259;
commit ec2654fb299306941e80c4907b7a9798cb6c6f05
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri May 14 16:29:07 2010 +0900

    pc: remove global variable rtc_state by using qemu_irq.
    
    Remove the reference to the global variable, rtc_state, by passing
    function argument to cmos_init_hd(), cmos_init().
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Cc: Paolo Bonzini <bonzini at gnu.org>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>
    Cc: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/pc.c b/hw/pc.c
index 3b6da4a..c88158c 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -65,8 +65,6 @@
 
 #define MAX_IDE_BUS 2
 
-static RTCState *rtc_state;
-
 #define E820_NR_ENTRIES		16
 
 struct e820_entry {
@@ -207,9 +205,9 @@ static int cmos_get_fd_drive_type(int fd0)
     return val;
 }
 
-static void cmos_init_hd(int type_ofs, int info_ofs, BlockDriverState *hd)
+static void cmos_init_hd(int type_ofs, int info_ofs, BlockDriverState *hd,
+                         RTCState *s)
 {
-    RTCState *s = rtc_state;
     int cylinders, heads, sectors;
     bdrv_get_geometry_hint(hd, &cylinders, &heads, &sectors);
     rtc_set_memory(s, type_ofs, 47);
@@ -273,9 +271,8 @@ static int pc_boot_set(void *opaque, const char *boot_device)
 /* hd_table must contain 4 block drivers */
 static void cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
                       const char *boot_device, DriveInfo **hd_table,
-                      FDCtrl *floppy_controller)
+                      FDCtrl *floppy_controller, RTCState *s)
 {
-    RTCState *s = rtc_state;
     int val;
     int fd0, fd1, nb;
     int i;
@@ -350,9 +347,9 @@ static void cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
 
     rtc_set_memory(s, 0x12, (hd_table[0] ? 0xf0 : 0) | (hd_table[1] ? 0x0f : 0));
     if (hd_table[0])
-        cmos_init_hd(0x19, 0x1b, hd_table[0]->bdrv);
+        cmos_init_hd(0x19, 0x1b, hd_table[0]->bdrv, s);
     if (hd_table[1])
-        cmos_init_hd(0x1a, 0x24, hd_table[1]->bdrv);
+        cmos_init_hd(0x1a, 0x24, hd_table[1]->bdrv, s);
 
     val = 0;
     for (i = 0; i < 4; i++) {
@@ -835,6 +832,7 @@ static void pc_init1(ram_addr_t ram_size,
     DriveInfo *fd[MAX_FD];
     void *fw_cfg;
     FDCtrl *floppy_controller;
+    RTCState *rtc_state;
     PITState *pit;
 
     if (ram_size >= 0xe0000000 ) {
@@ -1037,7 +1035,7 @@ static void pc_init1(ram_addr_t ram_size,
     floppy_controller = fdctrl_init_isa(fd);
 
     cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd,
-              floppy_controller);
+              floppy_controller, rtc_state);
 
     if (pci_enabled && usb_enabled) {
         usb_uhci_piix3_init(pci_bus, piix3_devfn + 2);
commit 01b9e8c10e95446b2800b1403f1c3ff8defb54c5
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri May 14 16:29:06 2010 +0900

    pc: remove a global variable, floppy_controller.
    
    Remove a global variable, floppy_controller.
    Since it is unnecessarily global, make it local and pass it as
    a function argument.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/pc.c b/hw/pc.c
index b23684e..3b6da4a 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -65,7 +65,6 @@
 
 #define MAX_IDE_BUS 2
 
-static FDCtrl *floppy_controller;
 static RTCState *rtc_state;
 
 #define E820_NR_ENTRIES		16
@@ -273,7 +272,8 @@ static int pc_boot_set(void *opaque, const char *boot_device)
 
 /* hd_table must contain 4 block drivers */
 static void cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
-                      const char *boot_device, DriveInfo **hd_table)
+                      const char *boot_device, DriveInfo **hd_table,
+                      FDCtrl *floppy_controller)
 {
     RTCState *s = rtc_state;
     int val;
@@ -834,6 +834,7 @@ static void pc_init1(ram_addr_t ram_size,
     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
     DriveInfo *fd[MAX_FD];
     void *fw_cfg;
+    FDCtrl *floppy_controller;
     PITState *pit;
 
     if (ram_size >= 0xe0000000 ) {
@@ -1035,7 +1036,8 @@ static void pc_init1(ram_addr_t ram_size,
     }
     floppy_controller = fdctrl_init_isa(fd);
 
-    cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd);
+    cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd,
+              floppy_controller);
 
     if (pci_enabled && usb_enabled) {
         usb_uhci_piix3_init(pci_bus, piix3_devfn + 2);
commit 57864959a4279dbea07e039a54f5022488f135cb
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri May 14 16:29:05 2010 +0900

    pc: make an unnecessary global variable, pit, local.
    
    remove unnecessary global static variables, pit.
    Make it local.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/pc.c b/hw/pc.c
index 691803f..b23684e 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -67,7 +67,6 @@
 
 static FDCtrl *floppy_controller;
 static RTCState *rtc_state;
-static PITState *pit;
 
 #define E820_NR_ENTRIES		16
 
@@ -835,6 +834,7 @@ static void pc_init1(ram_addr_t ram_size,
     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
     DriveInfo *fd[MAX_FD];
     void *fw_cfg;
+    PITState *pit;
 
     if (ram_size >= 0xe0000000 ) {
         above_4g_mem_size = ram_size - 0xe0000000;
commit f885f1eaa8711c06033ceb1599e3750fb37c306f
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri May 14 16:29:04 2010 +0900

    pc, i440fx: Make smm enable/disable function i440fx independent.
    
    make cpu_smm_update() generic to be independent on i440fx by
    registering a callback.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/pc.c b/hw/pc.c
index 8842766..691803f 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -68,7 +68,6 @@
 static FDCtrl *floppy_controller;
 static RTCState *rtc_state;
 static PITState *pit;
-static PCII440FXState *i440fx_state;
 
 #define E820_NR_ENTRIES		16
 
@@ -125,10 +124,22 @@ uint64_t cpu_get_tsc(CPUX86State *env)
 }
 
 /* SMM support */
+
+static cpu_set_smm_t smm_set;
+static void *smm_arg;
+
+void cpu_smm_register(cpu_set_smm_t callback, void *arg)
+{
+    assert(smm_set == NULL);
+    assert(smm_arg == NULL);
+    smm_set = callback;
+    smm_arg = arg;
+}
+
 void cpu_smm_update(CPUState *env)
 {
-    if (i440fx_state && env == first_cpu)
-        i440fx_set_smm(i440fx_state, (env->hflags >> HF_SMM_SHIFT) & 1);
+    if (smm_set && smm_arg && env == first_cpu)
+        smm_set(!!(env->hflags & HF_SMM_MASK), smm_arg);
 }
 
 
@@ -813,6 +824,7 @@ static void pc_init1(ram_addr_t ram_size,
     ram_addr_t below_4g_mem_size, above_4g_mem_size = 0;
     int bios_size, isa_bios_size;
     PCIBus *pci_bus;
+    PCII440FXState *i440fx_state;
     int piix3_devfn = -1;
     qemu_irq *cpu_irq;
     qemu_irq *isa_irq;
diff --git a/hw/pc.h b/hw/pc.h
index d11a576..77239a0 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -80,6 +80,9 @@ extern int fd_bootchk;
 void ioport_set_a20(int enable);
 int ioport_get_a20(void);
 
+typedef void (*cpu_set_smm_t)(int smm, void *arg);
+void cpu_smm_register(cpu_set_smm_t callback, void *arg);
+
 /* acpi.c */
 extern int acpi_enabled;
 extern char *acpi_tables;
@@ -108,7 +111,6 @@ struct PCII440FXState;
 typedef struct PCII440FXState PCII440FXState;
 
 PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix_devfn, qemu_irq *pic, int ram_size);
-void i440fx_set_smm(PCII440FXState *d, int val);
 void i440fx_init_memory_mappings(PCII440FXState *d);
 
 /* piix4.c */
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index 97519db..aff7f6d 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -114,8 +114,10 @@ static void i440fx_update_memory_mappings(PCII440FXState *d)
     }
 }
 
-void i440fx_set_smm(PCII440FXState *d, int val)
+static void i440fx_set_smm(int val, void *arg)
 {
+    PCII440FXState *d = arg;
+
     val = (val != 0);
     if (d->smm_enabled != val) {
         d->smm_enabled = val;
@@ -210,6 +212,7 @@ static int i440fx_initfn(PCIDevice *dev)
 
     d->dev.config[I440FX_SMRAM] = 0x02;
 
+    cpu_smm_register(&i440fx_set_smm, d);
     return 0;
 }
 
commit b8d6f53986c56dfcffe1961cb01877e81d0f8bb5
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri May 14 16:29:03 2010 +0900

    pc: initialize ioapic before use.
    
    The changeset of 2c8d9340203c7f19265fd4cb2341f568217a3af6
    prevents isa_irq_handler() from NULL refering of IsaIrqState::ioapic.
    However it would be better to initialize the member before reference.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/pc.c b/hw/pc.c
index db2b9a2..8842766 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -921,6 +921,9 @@ static void pc_init1(ram_addr_t ram_size,
     i8259 = i8259_init(cpu_irq[0]);
     isa_irq_state = qemu_mallocz(sizeof(*isa_irq_state));
     isa_irq_state->i8259 = i8259;
+    if (pci_enabled) {
+        isa_irq_state->ioapic = ioapic_init();
+    }
     isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24);
 
     if (pci_enabled) {
@@ -964,9 +967,6 @@ static void pc_init1(ram_addr_t ram_size,
     register_ioport_read(0x92, 1, 1, ioport92_read, NULL);
     register_ioport_write(0x92, 1, 1, ioport92_write, NULL);
 
-    if (pci_enabled) {
-        isa_irq_state->ioapic = ioapic_init();
-    }
     pit = pit_init(0x40, isa_reserve_irq(0));
     pcspk_init(pit);
     if (!no_hpet) {
commit 93d89f63e5a297f8672daf5d8b7b4df2a999af61
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri May 14 16:29:02 2010 +0900

    acpi: split acpi.c into the common part and the piix4 part.
    
    Split acpi.c into the common part and the piix4 specific part.
    The common part will be used later.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index 25414f3..3998678 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -195,7 +195,7 @@ obj-i386-y += cirrus_vga.o apic.o ioapic.o piix_pci.o
 obj-i386-y += vmmouse.o vmport.o hpet.o
 obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
 obj-i386-y += debugcon.o multiboot.o
-obj-i386-y += pm_smbus.o apm.o
+obj-i386-y += pm_smbus.o apm.o acpi_piix4.o
 
 # shared objects
 obj-ppc-y = ppc.o
@@ -221,7 +221,7 @@ obj-mips-y += dma.o vga.o i8259.o
 obj-mips-y += g364fb.o jazz_led.o
 obj-mips-y += gt64xxx.o pckbd.o mc146818rtc.o
 obj-mips-y += piix4.o cirrus_vga.o
-obj-mips-y += pm_smbus.o apm.o
+obj-mips-y += pm_smbus.o apm.o acpi_piix4.o
 
 obj-microblaze-y = petalogix_s3adsp1800_mmu.o
 
diff --git a/hw/acpi.c b/hw/acpi.c
index 891378c..4c4df56 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -17,572 +17,10 @@
  */
 #include "hw.h"
 #include "pc.h"
-#include "apm.h"
-#include "pm_smbus.h"
 #include "pci.h"
-#include "qemu-timer.h"
 #include "sysemu.h"
-#include "i2c.h"
-#include "smbus.h"
 #include "acpi.h"
 
-//#define DEBUG
-
-#define ACPI_DBG_IO_ADDR  0xb044
-
-typedef struct PIIX4PMState {
-    PCIDevice dev;
-    uint16_t pmsts;
-    uint16_t pmen;
-    uint16_t pmcntrl;
-
-    APMState apm;
-
-    QEMUTimer *tmr_timer;
-    int64_t tmr_overflow_time;
-
-    PMSMBus smb;
-
-    qemu_irq irq;
-    qemu_irq cmos_s3;
-    qemu_irq smi_irq;
-    int kvm_enabled;
-} PIIX4PMState;
-
-#define ACPI_ENABLE 0xf1
-#define ACPI_DISABLE 0xf0
-
-static PIIX4PMState *pm_state;
-
-static uint32_t get_pmtmr(PIIX4PMState *s)
-{
-    uint32_t d;
-    d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY, get_ticks_per_sec());
-    return d & 0xffffff;
-}
-
-static int get_pmsts(PIIX4PMState *s)
-{
-    int64_t d;
-
-    d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY,
-                 get_ticks_per_sec());
-    if (d >= s->tmr_overflow_time)
-        s->pmsts |= ACPI_BITMASK_TIMER_STATUS;
-    return s->pmsts;
-}
-
-static void pm_update_sci(PIIX4PMState *s)
-{
-    int sci_level, pmsts;
-    int64_t expire_time;
-
-    pmsts = get_pmsts(s);
-    sci_level = (((pmsts & s->pmen) &
-                  (ACPI_BITMASK_RT_CLOCK_ENABLE |
-                   ACPI_BITMASK_POWER_BUTTON_ENABLE |
-                   ACPI_BITMASK_GLOBAL_LOCK_ENABLE |
-                   ACPI_BITMASK_TIMER_ENABLE)) != 0);
-    qemu_set_irq(s->irq, sci_level);
-    /* schedule a timer interruption if needed */
-    if ((s->pmen & ACPI_BITMASK_TIMER_ENABLE) &&
-        !(pmsts & ACPI_BITMASK_TIMER_STATUS)) {
-        expire_time = muldiv64(s->tmr_overflow_time, get_ticks_per_sec(),
-                               PM_TIMER_FREQUENCY);
-        qemu_mod_timer(s->tmr_timer, expire_time);
-    } else {
-        qemu_del_timer(s->tmr_timer);
-    }
-}
-
-static void pm_tmr_timer(void *opaque)
-{
-    PIIX4PMState *s = opaque;
-    pm_update_sci(s);
-}
-
-static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
-{
-    PIIX4PMState *s = opaque;
-    addr &= 0x3f;
-    switch(addr) {
-    case 0x00:
-        {
-            int64_t d;
-            int pmsts;
-            pmsts = get_pmsts(s);
-            if (pmsts & val & ACPI_BITMASK_TIMER_STATUS) {
-                /* if TMRSTS is reset, then compute the new overflow time */
-                d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY,
-                             get_ticks_per_sec());
-                s->tmr_overflow_time = (d + 0x800000LL) & ~0x7fffffLL;
-            }
-            s->pmsts &= ~val;
-            pm_update_sci(s);
-        }
-        break;
-    case 0x02:
-        s->pmen = val;
-        pm_update_sci(s);
-        break;
-    case 0x04:
-        {
-            int sus_typ;
-            s->pmcntrl = val & ~(ACPI_BITMASK_SLEEP_ENABLE);
-            if (val & ACPI_BITMASK_SLEEP_ENABLE) {
-                /* change suspend type */
-                sus_typ = (val >> 10) & 7;
-                switch(sus_typ) {
-                case 0: /* soft power off */
-                    qemu_system_shutdown_request();
-                    break;
-                case 1:
-                    /* ACPI_BITMASK_WAKE_STATUS should be set on resume.
-                       Pretend that resume was caused by power button */
-                    s->pmsts |= (ACPI_BITMASK_WAKE_STATUS |
-                                 ACPI_BITMASK_POWER_BUTTON_STATUS);
-                    qemu_system_reset_request();
-                    if (s->cmos_s3) {
-                        qemu_irq_raise(s->cmos_s3);
-                    }
-                default:
-                    break;
-                }
-            }
-        }
-        break;
-    default:
-        break;
-    }
-#ifdef DEBUG
-    printf("PM writew port=0x%04x val=0x%04x\n", addr, val);
-#endif
-}
-
-static uint32_t pm_ioport_readw(void *opaque, uint32_t addr)
-{
-    PIIX4PMState *s = opaque;
-    uint32_t val;
-
-    addr &= 0x3f;
-    switch(addr) {
-    case 0x00:
-        val = get_pmsts(s);
-        break;
-    case 0x02:
-        val = s->pmen;
-        break;
-    case 0x04:
-        val = s->pmcntrl;
-        break;
-    default:
-        val = 0;
-        break;
-    }
-#ifdef DEBUG
-    printf("PM readw port=0x%04x val=0x%04x\n", addr, val);
-#endif
-    return val;
-}
-
-static void pm_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
-{
-    //    PIIX4PMState *s = opaque;
-#ifdef DEBUG
-    addr &= 0x3f;
-    printf("PM writel port=0x%04x val=0x%08x\n", addr, val);
-#endif
-}
-
-static uint32_t pm_ioport_readl(void *opaque, uint32_t addr)
-{
-    PIIX4PMState *s = opaque;
-    uint32_t val;
-
-    addr &= 0x3f;
-    switch(addr) {
-    case 0x08:
-        val = get_pmtmr(s);
-        break;
-    default:
-        val = 0;
-        break;
-    }
-#ifdef DEBUG
-    printf("PM readl port=0x%04x val=0x%08x\n", addr, val);
-#endif
-    return val;
-}
-
-static void apm_ctrl_changed(uint32_t val, void *arg)
-{
-    PIIX4PMState *s = arg;
-
-    /* ACPI specs 3.0, 4.7.2.5 */
-    if (val == ACPI_ENABLE) {
-        s->pmcntrl |= ACPI_BITMASK_SCI_ENABLE;
-    } else if (val == ACPI_DISABLE) {
-        s->pmcntrl &= ~ACPI_BITMASK_SCI_ENABLE;
-    }
-
-    if (s->dev.config[0x5b] & (1 << 1)) {
-        if (s->smi_irq) {
-            qemu_irq_raise(s->smi_irq);
-        }
-    }
-}
-
-static void acpi_dbg_writel(void *opaque, uint32_t addr, uint32_t val)
-{
-#if defined(DEBUG)
-    printf("ACPI: DBG: 0x%08x\n", val);
-#endif
-}
-
-static void pm_io_space_update(PIIX4PMState *s)
-{
-    uint32_t pm_io_base;
-
-    if (s->dev.config[0x80] & 1) {
-        pm_io_base = le32_to_cpu(*(uint32_t *)(s->dev.config + 0x40));
-        pm_io_base &= 0xffc0;
-
-        /* XXX: need to improve memory and ioport allocation */
-#if defined(DEBUG)
-        printf("PM: mapping to 0x%x\n", pm_io_base);
-#endif
-        register_ioport_write(pm_io_base, 64, 2, pm_ioport_writew, s);
-        register_ioport_read(pm_io_base, 64, 2, pm_ioport_readw, s);
-        register_ioport_write(pm_io_base, 64, 4, pm_ioport_writel, s);
-        register_ioport_read(pm_io_base, 64, 4, pm_ioport_readl, s);
-    }
-}
-
-static void pm_write_config(PCIDevice *d,
-                            uint32_t address, uint32_t val, int len)
-{
-    pci_default_write_config(d, address, val, len);
-    if (range_covers_byte(address, len, 0x80))
-        pm_io_space_update((PIIX4PMState *)d);
-}
-
-static int vmstate_acpi_post_load(void *opaque, int version_id)
-{
-    PIIX4PMState *s = opaque;
-
-    pm_io_space_update(s);
-    return 0;
-}
-
-static const VMStateDescription vmstate_acpi = {
-    .name = "piix4_pm",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .post_load = vmstate_acpi_post_load,
-    .fields      = (VMStateField []) {
-        VMSTATE_PCI_DEVICE(dev, PIIX4PMState),
-        VMSTATE_UINT16(pmsts, PIIX4PMState),
-        VMSTATE_UINT16(pmen, PIIX4PMState),
-        VMSTATE_UINT16(pmcntrl, PIIX4PMState),
-        VMSTATE_STRUCT(apm, PIIX4PMState, 0, vmstate_apm, APMState),
-        VMSTATE_TIMER(tmr_timer, PIIX4PMState),
-        VMSTATE_INT64(tmr_overflow_time, PIIX4PMState),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void piix4_reset(void *opaque)
-{
-    PIIX4PMState *s = opaque;
-    uint8_t *pci_conf = s->dev.config;
-
-    pci_conf[0x58] = 0;
-    pci_conf[0x59] = 0;
-    pci_conf[0x5a] = 0;
-    pci_conf[0x5b] = 0;
-
-    if (s->kvm_enabled) {
-        /* Mark SMM as already inited (until KVM supports SMM). */
-        pci_conf[0x5B] = 0x02;
-    }
-}
-
-static void piix4_powerdown(void *opaque, int irq, int power_failing)
-{
-    PIIX4PMState *s = opaque;
-
-    if (!s) {
-        qemu_system_shutdown_request();
-    } else if (s->pmen & ACPI_BITMASK_POWER_BUTTON_ENABLE) {
-        s->pmsts |= ACPI_BITMASK_POWER_BUTTON_STATUS;
-        pm_update_sci(s);
-    }
-}
-
-i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
-                       qemu_irq sci_irq, qemu_irq cmos_s3, qemu_irq smi_irq,
-                       int kvm_enabled)
-{
-    PIIX4PMState *s;
-    uint8_t *pci_conf;
-
-    s = (PIIX4PMState *)pci_register_device(bus,
-                                         "PM", sizeof(PIIX4PMState),
-                                         devfn, NULL, pm_write_config);
-    pm_state = s;
-    pci_conf = s->dev.config;
-    pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
-    pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82371AB_3);
-    pci_conf[0x06] = 0x80;
-    pci_conf[0x07] = 0x02;
-    pci_conf[0x08] = 0x03; // revision number
-    pci_conf[0x09] = 0x00;
-    pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_OTHER);
-    pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
-    pci_conf[0x3d] = 0x01; // interrupt pin 1
-
-    pci_conf[0x40] = 0x01; /* PM io base read only bit */
-
-    /* APM */
-    apm_init(&s->apm, apm_ctrl_changed, s);
-
-    register_ioport_write(ACPI_DBG_IO_ADDR, 4, 4, acpi_dbg_writel, s);
-
-    s->kvm_enabled = kvm_enabled;
-    if (s->kvm_enabled) {
-        /* Mark SMM as already inited to prevent SMM from running.  KVM does not
-         * support SMM mode. */
-        pci_conf[0x5B] = 0x02;
-    }
-
-    /* XXX: which specification is used ? The i82731AB has different
-       mappings */
-    pci_conf[0x5f] = (parallel_hds[0] != NULL ? 0x80 : 0) | 0x10;
-    pci_conf[0x63] = 0x60;
-    pci_conf[0x67] = (serial_hds[0] != NULL ? 0x08 : 0) |
-	(serial_hds[1] != NULL ? 0x90 : 0);
-
-    pci_conf[0x90] = smb_io_base | 1;
-    pci_conf[0x91] = smb_io_base >> 8;
-    pci_conf[0xd2] = 0x09;
-    register_ioport_write(smb_io_base, 64, 1, smb_ioport_writeb, &s->smb);
-    register_ioport_read(smb_io_base, 64, 1, smb_ioport_readb, &s->smb);
-
-    s->tmr_timer = qemu_new_timer(vm_clock, pm_tmr_timer, s);
-
-    qemu_system_powerdown = *qemu_allocate_irqs(piix4_powerdown, s, 1);
-
-    vmstate_register(0, &vmstate_acpi, s);
-
-    pm_smbus_init(NULL, &s->smb);
-    s->irq = sci_irq;
-    s->cmos_s3 = cmos_s3;
-    s->smi_irq = smi_irq;
-    qemu_register_reset(piix4_reset, s);
-
-    return s->smb.smbus;
-}
-
-#define GPE_BASE 0xafe0
-#define PCI_BASE 0xae00
-#define PCI_EJ_BASE 0xae08
-
-struct gpe_regs {
-    uint16_t sts; /* status */
-    uint16_t en;  /* enabled */
-};
-
-struct pci_status {
-    uint32_t up;
-    uint32_t down;
-};
-
-static struct gpe_regs gpe;
-static struct pci_status pci0_status;
-
-static uint32_t gpe_read_val(uint16_t val, uint32_t addr)
-{
-    if (addr & 1)
-        return (val >> 8) & 0xff;
-    return val & 0xff;
-}
-
-static uint32_t gpe_readb(void *opaque, uint32_t addr)
-{
-    uint32_t val = 0;
-    struct gpe_regs *g = opaque;
-    switch (addr) {
-        case GPE_BASE:
-        case GPE_BASE + 1:
-            val = gpe_read_val(g->sts, addr);
-            break;
-        case GPE_BASE + 2:
-        case GPE_BASE + 3:
-            val = gpe_read_val(g->en, addr);
-            break;
-        default:
-            break;
-    }
-
-#if defined(DEBUG)
-    printf("gpe read %x == %x\n", addr, val);
-#endif
-    return val;
-}
-
-static void gpe_write_val(uint16_t *cur, int addr, uint32_t val)
-{
-    if (addr & 1)
-        *cur = (*cur & 0xff) | (val << 8);
-    else
-        *cur = (*cur & 0xff00) | (val & 0xff);
-}
-
-static void gpe_reset_val(uint16_t *cur, int addr, uint32_t val)
-{
-    uint16_t x1, x0 = val & 0xff;
-    int shift = (addr & 1) ? 8 : 0;
-
-    x1 = (*cur >> shift) & 0xff;
-
-    x1 = x1 & ~x0;
-
-    *cur = (*cur & (0xff << (8 - shift))) | (x1 << shift);
-}
-
-static void gpe_writeb(void *opaque, uint32_t addr, uint32_t val)
-{
-    struct gpe_regs *g = opaque;
-    switch (addr) {
-        case GPE_BASE:
-        case GPE_BASE + 1:
-            gpe_reset_val(&g->sts, addr, val);
-            break;
-        case GPE_BASE + 2:
-        case GPE_BASE + 3:
-            gpe_write_val(&g->en, addr, val);
-            break;
-        default:
-            break;
-   }
-
-#if defined(DEBUG)
-    printf("gpe write %x <== %d\n", addr, val);
-#endif
-}
-
-static uint32_t pcihotplug_read(void *opaque, uint32_t addr)
-{
-    uint32_t val = 0;
-    struct pci_status *g = opaque;
-    switch (addr) {
-        case PCI_BASE:
-            val = g->up;
-            break;
-        case PCI_BASE + 4:
-            val = g->down;
-            break;
-        default:
-            break;
-    }
-
-#if defined(DEBUG)
-    printf("pcihotplug read %x == %x\n", addr, val);
-#endif
-    return val;
-}
-
-static void pcihotplug_write(void *opaque, uint32_t addr, uint32_t val)
-{
-    struct pci_status *g = opaque;
-    switch (addr) {
-        case PCI_BASE:
-            g->up = val;
-            break;
-        case PCI_BASE + 4:
-            g->down = val;
-            break;
-   }
-
-#if defined(DEBUG)
-    printf("pcihotplug write %x <== %d\n", addr, val);
-#endif
-}
-
-static uint32_t pciej_read(void *opaque, uint32_t addr)
-{
-#if defined(DEBUG)
-    printf("pciej read %x\n", addr);
-#endif
-    return 0;
-}
-
-static void pciej_write(void *opaque, uint32_t addr, uint32_t val)
-{
-    BusState *bus = opaque;
-    DeviceState *qdev, *next;
-    PCIDevice *dev;
-    int slot = ffs(val) - 1;
-
-    QLIST_FOREACH_SAFE(qdev, &bus->children, sibling, next) {
-        dev = DO_UPCAST(PCIDevice, qdev, qdev);
-        if (PCI_SLOT(dev->devfn) == slot) {
-            qdev_free(qdev);
-        }
-    }
-
-
-#if defined(DEBUG)
-    printf("pciej write %x <== %d\n", addr, val);
-#endif
-}
-
-static int piix4_device_hotplug(PCIDevice *dev, int state);
-
-void piix4_acpi_system_hot_add_init(PCIBus *bus)
-{
-    register_ioport_write(GPE_BASE, 4, 1, gpe_writeb, &gpe);
-    register_ioport_read(GPE_BASE, 4, 1,  gpe_readb, &gpe);
-
-    register_ioport_write(PCI_BASE, 8, 4, pcihotplug_write, &pci0_status);
-    register_ioport_read(PCI_BASE, 8, 4,  pcihotplug_read, &pci0_status);
-
-    register_ioport_write(PCI_EJ_BASE, 4, 4, pciej_write, bus);
-    register_ioport_read(PCI_EJ_BASE, 4, 4,  pciej_read, bus);
-
-    pci_bus_hotplug(bus, piix4_device_hotplug);
-}
-
-static void enable_device(struct pci_status *p, struct gpe_regs *g, int slot)
-{
-    g->sts |= 2;
-    p->up |= (1 << slot);
-}
-
-static void disable_device(struct pci_status *p, struct gpe_regs *g, int slot)
-{
-    g->sts |= 2;
-    p->down |= (1 << slot);
-}
-
-static int piix4_device_hotplug(PCIDevice *dev, int state)
-{
-    int slot = PCI_SLOT(dev->devfn);
-
-    pci0_status.up = 0;
-    pci0_status.down = 0;
-    if (state)
-        enable_device(&pci0_status, &gpe, slot);
-    else
-        disable_device(&pci0_status, &gpe, slot);
-    if (gpe.en & 2) {
-        qemu_set_irq(pm_state->irq, 1);
-        qemu_set_irq(pm_state->irq, 0);
-    }
-    return 0;
-}
-
 struct acpi_table_header
 {
     char signature [4];    /* ACPI signature (4 ASCII characters) */
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
new file mode 100644
index 0000000..1292d2b
--- /dev/null
+++ b/hw/acpi_piix4.c
@@ -0,0 +1,583 @@
+/*
+ * ACPI implementation
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>
+ */
+#include "hw.h"
+#include "pc.h"
+#include "apm.h"
+#include "pm_smbus.h"
+#include "pci.h"
+#include "sysemu.h"
+#include "i2c.h"
+#include "smbus.h"
+#include "acpi.h"
+
+//#define DEBUG
+
+#define ACPI_DBG_IO_ADDR  0xb044
+
+typedef struct PIIX4PMState {
+    PCIDevice dev;
+    uint16_t pmsts;
+    uint16_t pmen;
+    uint16_t pmcntrl;
+
+    APMState apm;
+
+    QEMUTimer *tmr_timer;
+    int64_t tmr_overflow_time;
+
+    PMSMBus smb;
+
+    qemu_irq irq;
+    qemu_irq cmos_s3;
+    qemu_irq smi_irq;
+    int kvm_enabled;
+} PIIX4PMState;
+
+#define ACPI_ENABLE 0xf1
+#define ACPI_DISABLE 0xf0
+
+static PIIX4PMState *pm_state;
+
+static uint32_t get_pmtmr(PIIX4PMState *s)
+{
+    uint32_t d;
+    d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY, get_ticks_per_sec());
+    return d & 0xffffff;
+}
+
+static int get_pmsts(PIIX4PMState *s)
+{
+    int64_t d;
+
+    d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY,
+                 get_ticks_per_sec());
+    if (d >= s->tmr_overflow_time)
+        s->pmsts |= ACPI_BITMASK_TIMER_STATUS;
+    return s->pmsts;
+}
+
+static void pm_update_sci(PIIX4PMState *s)
+{
+    int sci_level, pmsts;
+    int64_t expire_time;
+
+    pmsts = get_pmsts(s);
+    sci_level = (((pmsts & s->pmen) &
+                  (ACPI_BITMASK_RT_CLOCK_ENABLE |
+                   ACPI_BITMASK_POWER_BUTTON_ENABLE |
+                   ACPI_BITMASK_GLOBAL_LOCK_ENABLE |
+                   ACPI_BITMASK_TIMER_ENABLE)) != 0);
+    qemu_set_irq(s->irq, sci_level);
+    /* schedule a timer interruption if needed */
+    if ((s->pmen & ACPI_BITMASK_TIMER_ENABLE) &&
+        !(pmsts & ACPI_BITMASK_TIMER_STATUS)) {
+        expire_time = muldiv64(s->tmr_overflow_time, get_ticks_per_sec(),
+                               PM_TIMER_FREQUENCY);
+        qemu_mod_timer(s->tmr_timer, expire_time);
+    } else {
+        qemu_del_timer(s->tmr_timer);
+    }
+}
+
+static void pm_tmr_timer(void *opaque)
+{
+    PIIX4PMState *s = opaque;
+    pm_update_sci(s);
+}
+
+static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
+{
+    PIIX4PMState *s = opaque;
+    addr &= 0x3f;
+    switch(addr) {
+    case 0x00:
+        {
+            int64_t d;
+            int pmsts;
+            pmsts = get_pmsts(s);
+            if (pmsts & val & ACPI_BITMASK_TIMER_STATUS) {
+                /* if TMRSTS is reset, then compute the new overflow time */
+                d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY,
+                             get_ticks_per_sec());
+                s->tmr_overflow_time = (d + 0x800000LL) & ~0x7fffffLL;
+            }
+            s->pmsts &= ~val;
+            pm_update_sci(s);
+        }
+        break;
+    case 0x02:
+        s->pmen = val;
+        pm_update_sci(s);
+        break;
+    case 0x04:
+        {
+            int sus_typ;
+            s->pmcntrl = val & ~(ACPI_BITMASK_SLEEP_ENABLE);
+            if (val & ACPI_BITMASK_SLEEP_ENABLE) {
+                /* change suspend type */
+                sus_typ = (val >> 10) & 7;
+                switch(sus_typ) {
+                case 0: /* soft power off */
+                    qemu_system_shutdown_request();
+                    break;
+                case 1:
+                    /* ACPI_BITMASK_WAKE_STATUS should be set on resume.
+                       Pretend that resume was caused by power button */
+                    s->pmsts |= (ACPI_BITMASK_WAKE_STATUS |
+                                 ACPI_BITMASK_POWER_BUTTON_STATUS);
+                    qemu_system_reset_request();
+                    if (s->cmos_s3) {
+                        qemu_irq_raise(s->cmos_s3);
+                    }
+                default:
+                    break;
+                }
+            }
+        }
+        break;
+    default:
+        break;
+    }
+#ifdef DEBUG
+    printf("PM writew port=0x%04x val=0x%04x\n", addr, val);
+#endif
+}
+
+static uint32_t pm_ioport_readw(void *opaque, uint32_t addr)
+{
+    PIIX4PMState *s = opaque;
+    uint32_t val;
+
+    addr &= 0x3f;
+    switch(addr) {
+    case 0x00:
+        val = get_pmsts(s);
+        break;
+    case 0x02:
+        val = s->pmen;
+        break;
+    case 0x04:
+        val = s->pmcntrl;
+        break;
+    default:
+        val = 0;
+        break;
+    }
+#ifdef DEBUG
+    printf("PM readw port=0x%04x val=0x%04x\n", addr, val);
+#endif
+    return val;
+}
+
+static void pm_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
+{
+    //    PIIX4PMState *s = opaque;
+#ifdef DEBUG
+    addr &= 0x3f;
+    printf("PM writel port=0x%04x val=0x%08x\n", addr, val);
+#endif
+}
+
+static uint32_t pm_ioport_readl(void *opaque, uint32_t addr)
+{
+    PIIX4PMState *s = opaque;
+    uint32_t val;
+
+    addr &= 0x3f;
+    switch(addr) {
+    case 0x08:
+        val = get_pmtmr(s);
+        break;
+    default:
+        val = 0;
+        break;
+    }
+#ifdef DEBUG
+    printf("PM readl port=0x%04x val=0x%08x\n", addr, val);
+#endif
+    return val;
+}
+
+static void apm_ctrl_changed(uint32_t val, void *arg)
+{
+    PIIX4PMState *s = arg;
+
+    /* ACPI specs 3.0, 4.7.2.5 */
+    if (val == ACPI_ENABLE) {
+        s->pmcntrl |= ACPI_BITMASK_SCI_ENABLE;
+    } else if (val == ACPI_DISABLE) {
+        s->pmcntrl &= ~ACPI_BITMASK_SCI_ENABLE;
+    }
+
+    if (s->dev.config[0x5b] & (1 << 1)) {
+        if (s->smi_irq) {
+            qemu_irq_raise(s->smi_irq);
+        }
+    }
+}
+
+static void acpi_dbg_writel(void *opaque, uint32_t addr, uint32_t val)
+{
+#if defined(DEBUG)
+    printf("ACPI: DBG: 0x%08x\n", val);
+#endif
+}
+
+static void pm_io_space_update(PIIX4PMState *s)
+{
+    uint32_t pm_io_base;
+
+    if (s->dev.config[0x80] & 1) {
+        pm_io_base = le32_to_cpu(*(uint32_t *)(s->dev.config + 0x40));
+        pm_io_base &= 0xffc0;
+
+        /* XXX: need to improve memory and ioport allocation */
+#if defined(DEBUG)
+        printf("PM: mapping to 0x%x\n", pm_io_base);
+#endif
+        register_ioport_write(pm_io_base, 64, 2, pm_ioport_writew, s);
+        register_ioport_read(pm_io_base, 64, 2, pm_ioport_readw, s);
+        register_ioport_write(pm_io_base, 64, 4, pm_ioport_writel, s);
+        register_ioport_read(pm_io_base, 64, 4, pm_ioport_readl, s);
+    }
+}
+
+static void pm_write_config(PCIDevice *d,
+                            uint32_t address, uint32_t val, int len)
+{
+    pci_default_write_config(d, address, val, len);
+    if (range_covers_byte(address, len, 0x80))
+        pm_io_space_update((PIIX4PMState *)d);
+}
+
+static int vmstate_acpi_post_load(void *opaque, int version_id)
+{
+    PIIX4PMState *s = opaque;
+
+    pm_io_space_update(s);
+    return 0;
+}
+
+static const VMStateDescription vmstate_acpi = {
+    .name = "piix4_pm",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .post_load = vmstate_acpi_post_load,
+    .fields      = (VMStateField []) {
+        VMSTATE_PCI_DEVICE(dev, PIIX4PMState),
+        VMSTATE_UINT16(pmsts, PIIX4PMState),
+        VMSTATE_UINT16(pmen, PIIX4PMState),
+        VMSTATE_UINT16(pmcntrl, PIIX4PMState),
+        VMSTATE_STRUCT(apm, PIIX4PMState, 0, vmstate_apm, APMState),
+        VMSTATE_TIMER(tmr_timer, PIIX4PMState),
+        VMSTATE_INT64(tmr_overflow_time, PIIX4PMState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void piix4_reset(void *opaque)
+{
+    PIIX4PMState *s = opaque;
+    uint8_t *pci_conf = s->dev.config;
+
+    pci_conf[0x58] = 0;
+    pci_conf[0x59] = 0;
+    pci_conf[0x5a] = 0;
+    pci_conf[0x5b] = 0;
+
+    if (s->kvm_enabled) {
+        /* Mark SMM as already inited (until KVM supports SMM). */
+        pci_conf[0x5B] = 0x02;
+    }
+}
+
+static void piix4_powerdown(void *opaque, int irq, int power_failing)
+{
+    PIIX4PMState *s = opaque;
+
+    if (!s) {
+        qemu_system_shutdown_request();
+    } else if (s->pmen & ACPI_BITMASK_POWER_BUTTON_ENABLE) {
+        s->pmsts |= ACPI_BITMASK_POWER_BUTTON_STATUS;
+        pm_update_sci(s);
+    }
+}
+
+i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
+                       qemu_irq sci_irq, qemu_irq cmos_s3, qemu_irq smi_irq,
+                       int kvm_enabled)
+{
+    PIIX4PMState *s;
+    uint8_t *pci_conf;
+
+    s = (PIIX4PMState *)pci_register_device(bus,
+                                         "PM", sizeof(PIIX4PMState),
+                                         devfn, NULL, pm_write_config);
+    pm_state = s;
+    pci_conf = s->dev.config;
+    pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
+    pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82371AB_3);
+    pci_conf[0x06] = 0x80;
+    pci_conf[0x07] = 0x02;
+    pci_conf[0x08] = 0x03; // revision number
+    pci_conf[0x09] = 0x00;
+    pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_OTHER);
+    pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
+    pci_conf[0x3d] = 0x01; // interrupt pin 1
+
+    pci_conf[0x40] = 0x01; /* PM io base read only bit */
+
+    /* APM */
+    apm_init(&s->apm, apm_ctrl_changed, s);
+
+    register_ioport_write(ACPI_DBG_IO_ADDR, 4, 4, acpi_dbg_writel, s);
+
+    s->kvm_enabled = kvm_enabled;
+    if (s->kvm_enabled) {
+        /* Mark SMM as already inited to prevent SMM from running.  KVM does not
+         * support SMM mode. */
+        pci_conf[0x5B] = 0x02;
+    }
+
+    /* XXX: which specification is used ? The i82731AB has different
+       mappings */
+    pci_conf[0x5f] = (parallel_hds[0] != NULL ? 0x80 : 0) | 0x10;
+    pci_conf[0x63] = 0x60;
+    pci_conf[0x67] = (serial_hds[0] != NULL ? 0x08 : 0) |
+	(serial_hds[1] != NULL ? 0x90 : 0);
+
+    pci_conf[0x90] = smb_io_base | 1;
+    pci_conf[0x91] = smb_io_base >> 8;
+    pci_conf[0xd2] = 0x09;
+    register_ioport_write(smb_io_base, 64, 1, smb_ioport_writeb, &s->smb);
+    register_ioport_read(smb_io_base, 64, 1, smb_ioport_readb, &s->smb);
+
+    s->tmr_timer = qemu_new_timer(vm_clock, pm_tmr_timer, s);
+
+    qemu_system_powerdown = *qemu_allocate_irqs(piix4_powerdown, s, 1);
+
+    vmstate_register(0, &vmstate_acpi, s);
+
+    pm_smbus_init(NULL, &s->smb);
+    s->irq = sci_irq;
+    s->cmos_s3 = cmos_s3;
+    s->smi_irq = smi_irq;
+    qemu_register_reset(piix4_reset, s);
+
+    return s->smb.smbus;
+}
+
+#define GPE_BASE 0xafe0
+#define PCI_BASE 0xae00
+#define PCI_EJ_BASE 0xae08
+
+struct gpe_regs {
+    uint16_t sts; /* status */
+    uint16_t en;  /* enabled */
+};
+
+struct pci_status {
+    uint32_t up;
+    uint32_t down;
+};
+
+static struct gpe_regs gpe;
+static struct pci_status pci0_status;
+
+static uint32_t gpe_read_val(uint16_t val, uint32_t addr)
+{
+    if (addr & 1)
+        return (val >> 8) & 0xff;
+    return val & 0xff;
+}
+
+static uint32_t gpe_readb(void *opaque, uint32_t addr)
+{
+    uint32_t val = 0;
+    struct gpe_regs *g = opaque;
+    switch (addr) {
+        case GPE_BASE:
+        case GPE_BASE + 1:
+            val = gpe_read_val(g->sts, addr);
+            break;
+        case GPE_BASE + 2:
+        case GPE_BASE + 3:
+            val = gpe_read_val(g->en, addr);
+            break;
+        default:
+            break;
+    }
+
+#if defined(DEBUG)
+    printf("gpe read %x == %x\n", addr, val);
+#endif
+    return val;
+}
+
+static void gpe_write_val(uint16_t *cur, int addr, uint32_t val)
+{
+    if (addr & 1)
+        *cur = (*cur & 0xff) | (val << 8);
+    else
+        *cur = (*cur & 0xff00) | (val & 0xff);
+}
+
+static void gpe_reset_val(uint16_t *cur, int addr, uint32_t val)
+{
+    uint16_t x1, x0 = val & 0xff;
+    int shift = (addr & 1) ? 8 : 0;
+
+    x1 = (*cur >> shift) & 0xff;
+
+    x1 = x1 & ~x0;
+
+    *cur = (*cur & (0xff << (8 - shift))) | (x1 << shift);
+}
+
+static void gpe_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+    struct gpe_regs *g = opaque;
+    switch (addr) {
+        case GPE_BASE:
+        case GPE_BASE + 1:
+            gpe_reset_val(&g->sts, addr, val);
+            break;
+        case GPE_BASE + 2:
+        case GPE_BASE + 3:
+            gpe_write_val(&g->en, addr, val);
+            break;
+        default:
+            break;
+   }
+
+#if defined(DEBUG)
+    printf("gpe write %x <== %d\n", addr, val);
+#endif
+}
+
+static uint32_t pcihotplug_read(void *opaque, uint32_t addr)
+{
+    uint32_t val = 0;
+    struct pci_status *g = opaque;
+    switch (addr) {
+        case PCI_BASE:
+            val = g->up;
+            break;
+        case PCI_BASE + 4:
+            val = g->down;
+            break;
+        default:
+            break;
+    }
+
+#if defined(DEBUG)
+    printf("pcihotplug read %x == %x\n", addr, val);
+#endif
+    return val;
+}
+
+static void pcihotplug_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    struct pci_status *g = opaque;
+    switch (addr) {
+        case PCI_BASE:
+            g->up = val;
+            break;
+        case PCI_BASE + 4:
+            g->down = val;
+            break;
+   }
+
+#if defined(DEBUG)
+    printf("pcihotplug write %x <== %d\n", addr, val);
+#endif
+}
+
+static uint32_t pciej_read(void *opaque, uint32_t addr)
+{
+#if defined(DEBUG)
+    printf("pciej read %x\n", addr);
+#endif
+    return 0;
+}
+
+static void pciej_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    BusState *bus = opaque;
+    DeviceState *qdev, *next;
+    PCIDevice *dev;
+    int slot = ffs(val) - 1;
+
+    QLIST_FOREACH_SAFE(qdev, &bus->children, sibling, next) {
+        dev = DO_UPCAST(PCIDevice, qdev, qdev);
+        if (PCI_SLOT(dev->devfn) == slot) {
+            qdev_free(qdev);
+        }
+    }
+
+
+#if defined(DEBUG)
+    printf("pciej write %x <== %d\n", addr, val);
+#endif
+}
+
+static int piix4_device_hotplug(PCIDevice *dev, int state);
+
+void piix4_acpi_system_hot_add_init(PCIBus *bus)
+{
+    register_ioport_write(GPE_BASE, 4, 1, gpe_writeb, &gpe);
+    register_ioport_read(GPE_BASE, 4, 1,  gpe_readb, &gpe);
+
+    register_ioport_write(PCI_BASE, 8, 4, pcihotplug_write, &pci0_status);
+    register_ioport_read(PCI_BASE, 8, 4,  pcihotplug_read, &pci0_status);
+
+    register_ioport_write(PCI_EJ_BASE, 4, 4, pciej_write, bus);
+    register_ioport_read(PCI_EJ_BASE, 4, 4,  pciej_read, bus);
+
+    pci_bus_hotplug(bus, piix4_device_hotplug);
+}
+
+static void enable_device(struct pci_status *p, struct gpe_regs *g, int slot)
+{
+    g->sts |= 2;
+    p->up |= (1 << slot);
+}
+
+static void disable_device(struct pci_status *p, struct gpe_regs *g, int slot)
+{
+    g->sts |= 2;
+    p->down |= (1 << slot);
+}
+
+static int piix4_device_hotplug(PCIDevice *dev, int state)
+{
+    int slot = PCI_SLOT(dev->devfn);
+
+    pci0_status.up = 0;
+    pci0_status.down = 0;
+    if (state)
+        enable_device(&pci0_status, &gpe, slot);
+    else
+        disable_device(&pci0_status, &gpe, slot);
+    if (gpe.en & 2) {
+        qemu_set_irq(pm_state->irq, 1);
+        qemu_set_irq(pm_state->irq, 0);
+    }
+    return 0;
+}
commit 990b150e7c207cf00cc1ec61baa17d770307fac4
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri May 14 16:29:01 2010 +0900

    acpi: add acpi constants from linux header files and use them.
    
    add acpi constants from linux header files and
    replace the old constants with them.
    The acpi constants will be used by other file.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/acpi.c b/hw/acpi.c
index 8dc9538..891378c 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -24,12 +24,10 @@
 #include "sysemu.h"
 #include "i2c.h"
 #include "smbus.h"
+#include "acpi.h"
 
 //#define DEBUG
 
-/* i82731AB (PIIX4) compatible power management function */
-#define PM_FREQ 3579545
-
 #define ACPI_DBG_IO_ADDR  0xb044
 
 typedef struct PIIX4PMState {
@@ -51,17 +49,6 @@ typedef struct PIIX4PMState {
     int kvm_enabled;
 } PIIX4PMState;
 
-#define RSM_STS (1 << 15)
-#define PWRBTN_STS (1 << 8)
-#define RTC_EN (1 << 10)
-#define PWRBTN_EN (1 << 8)
-#define GBL_EN (1 << 5)
-#define TMROF_EN (1 << 0)
-
-#define SCI_EN (1 << 0)
-
-#define SUS_EN (1 << 13)
-
 #define ACPI_ENABLE 0xf1
 #define ACPI_DISABLE 0xf0
 
@@ -70,7 +57,7 @@ static PIIX4PMState *pm_state;
 static uint32_t get_pmtmr(PIIX4PMState *s)
 {
     uint32_t d;
-    d = muldiv64(qemu_get_clock(vm_clock), PM_FREQ, get_ticks_per_sec());
+    d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY, get_ticks_per_sec());
     return d & 0xffffff;
 }
 
@@ -78,9 +65,10 @@ static int get_pmsts(PIIX4PMState *s)
 {
     int64_t d;
 
-    d = muldiv64(qemu_get_clock(vm_clock), PM_FREQ, get_ticks_per_sec());
+    d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY,
+                 get_ticks_per_sec());
     if (d >= s->tmr_overflow_time)
-        s->pmsts |= TMROF_EN;
+        s->pmsts |= ACPI_BITMASK_TIMER_STATUS;
     return s->pmsts;
 }
 
@@ -91,11 +79,16 @@ static void pm_update_sci(PIIX4PMState *s)
 
     pmsts = get_pmsts(s);
     sci_level = (((pmsts & s->pmen) &
-                  (RTC_EN | PWRBTN_EN | GBL_EN | TMROF_EN)) != 0);
+                  (ACPI_BITMASK_RT_CLOCK_ENABLE |
+                   ACPI_BITMASK_POWER_BUTTON_ENABLE |
+                   ACPI_BITMASK_GLOBAL_LOCK_ENABLE |
+                   ACPI_BITMASK_TIMER_ENABLE)) != 0);
     qemu_set_irq(s->irq, sci_level);
     /* schedule a timer interruption if needed */
-    if ((s->pmen & TMROF_EN) && !(pmsts & TMROF_EN)) {
-        expire_time = muldiv64(s->tmr_overflow_time, get_ticks_per_sec(), PM_FREQ);
+    if ((s->pmen & ACPI_BITMASK_TIMER_ENABLE) &&
+        !(pmsts & ACPI_BITMASK_TIMER_STATUS)) {
+        expire_time = muldiv64(s->tmr_overflow_time, get_ticks_per_sec(),
+                               PM_TIMER_FREQUENCY);
         qemu_mod_timer(s->tmr_timer, expire_time);
     } else {
         qemu_del_timer(s->tmr_timer);
@@ -118,9 +111,9 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
             int64_t d;
             int pmsts;
             pmsts = get_pmsts(s);
-            if (pmsts & val & TMROF_EN) {
+            if (pmsts & val & ACPI_BITMASK_TIMER_STATUS) {
                 /* if TMRSTS is reset, then compute the new overflow time */
-                d = muldiv64(qemu_get_clock(vm_clock), PM_FREQ,
+                d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY,
                              get_ticks_per_sec());
                 s->tmr_overflow_time = (d + 0x800000LL) & ~0x7fffffLL;
             }
@@ -135,8 +128,8 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
     case 0x04:
         {
             int sus_typ;
-            s->pmcntrl = val & ~(SUS_EN);
-            if (val & SUS_EN) {
+            s->pmcntrl = val & ~(ACPI_BITMASK_SLEEP_ENABLE);
+            if (val & ACPI_BITMASK_SLEEP_ENABLE) {
                 /* change suspend type */
                 sus_typ = (val >> 10) & 7;
                 switch(sus_typ) {
@@ -144,9 +137,10 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
                     qemu_system_shutdown_request();
                     break;
                 case 1:
-                    /* RSM_STS should be set on resume. Pretend that resume
-                       was caused by power button */
-                    s->pmsts |= (RSM_STS | PWRBTN_STS);
+                    /* ACPI_BITMASK_WAKE_STATUS should be set on resume.
+                       Pretend that resume was caused by power button */
+                    s->pmsts |= (ACPI_BITMASK_WAKE_STATUS |
+                                 ACPI_BITMASK_POWER_BUTTON_STATUS);
                     qemu_system_reset_request();
                     if (s->cmos_s3) {
                         qemu_irq_raise(s->cmos_s3);
@@ -226,9 +220,9 @@ static void apm_ctrl_changed(uint32_t val, void *arg)
 
     /* ACPI specs 3.0, 4.7.2.5 */
     if (val == ACPI_ENABLE) {
-        s->pmcntrl |= SCI_EN;
+        s->pmcntrl |= ACPI_BITMASK_SCI_ENABLE;
     } else if (val == ACPI_DISABLE) {
-        s->pmcntrl &= ~SCI_EN;
+        s->pmcntrl &= ~ACPI_BITMASK_SCI_ENABLE;
     }
 
     if (s->dev.config[0x5b] & (1 << 1)) {
@@ -320,8 +314,8 @@ static void piix4_powerdown(void *opaque, int irq, int power_failing)
 
     if (!s) {
         qemu_system_shutdown_request();
-    } else if (s->pmen & PWRBTN_EN) {
-        s->pmsts |= PWRBTN_EN;
+    } else if (s->pmen & ACPI_BITMASK_POWER_BUTTON_ENABLE) {
+        s->pmsts |= ACPI_BITMASK_POWER_BUTTON_STATUS;
         pm_update_sci(s);
     }
 }
diff --git a/hw/acpi.h b/hw/acpi.h
new file mode 100644
index 0000000..51b56b6
--- /dev/null
+++ b/hw/acpi.h
@@ -0,0 +1,78 @@
+#ifndef QEMU_HW_ACPI_H
+#define QEMU_HW_ACPI_H
+/*
+ *  Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ *                     VA Linux Systems Japan K.K.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+
+/* from linux include/acpi/actype.h */
+/* Default ACPI register widths */
+
+#define ACPI_GPE_REGISTER_WIDTH         8
+#define ACPI_PM1_REGISTER_WIDTH         16
+#define ACPI_PM2_REGISTER_WIDTH         8
+#define ACPI_PM_TIMER_WIDTH             32
+
+/* PM Timer ticks per second (HZ) */
+#define PM_TIMER_FREQUENCY  3579545
+
+
+/* ACPI fixed hardware registers */
+
+/* from linux/drivers/acpi/acpica/aclocal.h */
+/* Masks used to access the bit_registers */
+
+/* PM1x_STS */
+#define ACPI_BITMASK_TIMER_STATUS               0x0001
+#define ACPI_BITMASK_BUS_MASTER_STATUS          0x0010
+#define ACPI_BITMASK_GLOBAL_LOCK_STATUS         0x0020
+#define ACPI_BITMASK_POWER_BUTTON_STATUS        0x0100
+#define ACPI_BITMASK_SLEEP_BUTTON_STATUS        0x0200
+#define ACPI_BITMASK_RT_CLOCK_STATUS            0x0400
+#define ACPI_BITMASK_PCIEXP_WAKE_STATUS         0x4000	/* ACPI 3.0 */
+#define ACPI_BITMASK_WAKE_STATUS                0x8000
+
+#define ACPI_BITMASK_ALL_FIXED_STATUS           (\
+	ACPI_BITMASK_TIMER_STATUS          | \
+	ACPI_BITMASK_BUS_MASTER_STATUS     | \
+	ACPI_BITMASK_GLOBAL_LOCK_STATUS    | \
+	ACPI_BITMASK_POWER_BUTTON_STATUS   | \
+	ACPI_BITMASK_SLEEP_BUTTON_STATUS   | \
+	ACPI_BITMASK_RT_CLOCK_STATUS       | \
+	ACPI_BITMASK_WAKE_STATUS)
+
+/* PM1x_EN */
+#define ACPI_BITMASK_TIMER_ENABLE               0x0001
+#define ACPI_BITMASK_GLOBAL_LOCK_ENABLE         0x0020
+#define ACPI_BITMASK_POWER_BUTTON_ENABLE        0x0100
+#define ACPI_BITMASK_SLEEP_BUTTON_ENABLE        0x0200
+#define ACPI_BITMASK_RT_CLOCK_ENABLE            0x0400
+#define ACPI_BITMASK_PCIEXP_WAKE_DISABLE        0x4000	/* ACPI 3.0 */
+
+/* PM1x_CNT */
+#define ACPI_BITMASK_SCI_ENABLE                 0x0001
+#define ACPI_BITMASK_BUS_MASTER_RLD             0x0002
+#define ACPI_BITMASK_GLOBAL_LOCK_RELEASE        0x0004
+#define ACPI_BITMASK_SLEEP_TYPE                 0x1C00
+#define ACPI_BITMASK_SLEEP_ENABLE               0x2000
+
+/* PM2_CNT */
+#define ACPI_BITMASK_ARB_DISABLE                0x0001
+
+/* PM_TMR */
+
+#endif /* !QEMU_HW_ACPI_H */
commit 04762841d8803429fd9bf71eff481d3c5915fa3e
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri May 14 16:29:00 2010 +0900

    acpi: split out apm register emulation from acpi.c
    
    Split out apm register emulation for acpi.c into apm.c.
    The apm emulation will be used later.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>
    Cc: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index 05c04e5..25414f3 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -195,7 +195,7 @@ obj-i386-y += cirrus_vga.o apic.o ioapic.o piix_pci.o
 obj-i386-y += vmmouse.o vmport.o hpet.o
 obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
 obj-i386-y += debugcon.o multiboot.o
-obj-i386-y += pm_smbus.o
+obj-i386-y += pm_smbus.o apm.o
 
 # shared objects
 obj-ppc-y = ppc.o
@@ -221,7 +221,7 @@ obj-mips-y += dma.o vga.o i8259.o
 obj-mips-y += g364fb.o jazz_led.o
 obj-mips-y += gt64xxx.o pckbd.o mc146818rtc.o
 obj-mips-y += piix4.o cirrus_vga.o
-obj-mips-y += pm_smbus.o
+obj-mips-y += pm_smbus.o apm.o
 
 obj-microblaze-y = petalogix_s3adsp1800_mmu.o
 
diff --git a/hw/acpi.c b/hw/acpi.c
index ad8f4c7..8dc9538 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -17,6 +17,7 @@
  */
 #include "hw.h"
 #include "pc.h"
+#include "apm.h"
 #include "pm_smbus.h"
 #include "pci.h"
 #include "qemu-timer.h"
@@ -36,8 +37,9 @@ typedef struct PIIX4PMState {
     uint16_t pmsts;
     uint16_t pmen;
     uint16_t pmcntrl;
-    uint8_t apmc;
-    uint8_t apms;
+
+    APMState apm;
+
     QEMUTimer *tmr_timer;
     int64_t tmr_overflow_time;
 
@@ -218,48 +220,22 @@ static uint32_t pm_ioport_readl(void *opaque, uint32_t addr)
     return val;
 }
 
-static void pm_smi_writeb(void *opaque, uint32_t addr, uint32_t val)
+static void apm_ctrl_changed(uint32_t val, void *arg)
 {
-    PIIX4PMState *s = opaque;
-    addr &= 1;
-#ifdef DEBUG
-    printf("pm_smi_writeb addr=0x%x val=0x%02x\n", addr, val);
-#endif
-    if (addr == 0) {
-        s->apmc = val;
-
-        /* ACPI specs 3.0, 4.7.2.5 */
-        if (val == ACPI_ENABLE) {
-            s->pmcntrl |= SCI_EN;
-        } else if (val == ACPI_DISABLE) {
-            s->pmcntrl &= ~SCI_EN;
-        }
+    PIIX4PMState *s = arg;
 
-        if (s->dev.config[0x5b] & (1 << 1)) {
-            if (s->smi_irq) {
-                qemu_irq_raise(s->smi_irq);
-            }
-        }
-    } else {
-        s->apms = val;
+    /* ACPI specs 3.0, 4.7.2.5 */
+    if (val == ACPI_ENABLE) {
+        s->pmcntrl |= SCI_EN;
+    } else if (val == ACPI_DISABLE) {
+        s->pmcntrl &= ~SCI_EN;
     }
-}
 
-static uint32_t pm_smi_readb(void *opaque, uint32_t addr)
-{
-    PIIX4PMState *s = opaque;
-    uint32_t val;
-
-    addr &= 1;
-    if (addr == 0) {
-        val = s->apmc;
-    } else {
-        val = s->apms;
+    if (s->dev.config[0x5b] & (1 << 1)) {
+        if (s->smi_irq) {
+            qemu_irq_raise(s->smi_irq);
+        }
     }
-#ifdef DEBUG
-    printf("pm_smi_readb addr=0x%x val=0x%02x\n", addr, val);
-#endif
-    return val;
 }
 
 static void acpi_dbg_writel(void *opaque, uint32_t addr, uint32_t val)
@@ -315,8 +291,7 @@ static const VMStateDescription vmstate_acpi = {
         VMSTATE_UINT16(pmsts, PIIX4PMState),
         VMSTATE_UINT16(pmen, PIIX4PMState),
         VMSTATE_UINT16(pmcntrl, PIIX4PMState),
-        VMSTATE_UINT8(apmc, PIIX4PMState),
-        VMSTATE_UINT8(apms, PIIX4PMState),
+        VMSTATE_STRUCT(apm, PIIX4PMState, 0, vmstate_apm, APMState),
         VMSTATE_TIMER(tmr_timer, PIIX4PMState),
         VMSTATE_INT64(tmr_overflow_time, PIIX4PMState),
         VMSTATE_END_OF_LIST()
@@ -375,8 +350,8 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
 
     pci_conf[0x40] = 0x01; /* PM io base read only bit */
 
-    register_ioport_write(0xb2, 2, 1, pm_smi_writeb, s);
-    register_ioport_read(0xb2, 2, 1, pm_smi_readb, s);
+    /* APM */
+    apm_init(&s->apm, apm_ctrl_changed, s);
 
     register_ioport_write(ACPI_DBG_IO_ADDR, 4, 4, acpi_dbg_writel, s);
 
diff --git a/hw/apm.c b/hw/apm.c
new file mode 100644
index 0000000..d20db3d
--- /dev/null
+++ b/hw/apm.c
@@ -0,0 +1,85 @@
+/*
+ * QEMU PC APM controller Emulation
+ * This is split out from acpi.c
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * 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 "apm.h"
+#include "hw.h"
+#include "isa.h"
+
+//#define DEBUG
+
+/* fixed I/O location */
+#define APM_CNT_IOPORT  0xb2
+#define APM_STS_IOPORT  0xb3
+
+static void apm_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+    APMState *apm = opaque;
+    addr &= 1;
+#ifdef DEBUG
+    printf("apm_ioport_writeb addr=0x%x val=0x%02x\n", addr, val);
+#endif
+    if (addr == 0) {
+        apm->apmc = val;
+
+        if (apm->callback) {
+            (apm->callback)(val, apm->arg);
+        }
+    } else {
+        apm->apms = val;
+    }
+}
+
+static uint32_t apm_ioport_readb(void *opaque, uint32_t addr)
+{
+    APMState *apm = opaque;
+    uint32_t val;
+
+    addr &= 1;
+    if (addr == 0) {
+        val = apm->apmc;
+    } else {
+        val = apm->apms;
+    }
+#ifdef DEBUG
+    printf("apm_ioport_readb addr=0x%x val=0x%02x\n", addr, val);
+#endif
+    return val;
+}
+
+const VMStateDescription vmstate_apm = {
+    .name = "APM State",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8(apmc, APMState),
+        VMSTATE_UINT8(apms, APMState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+void apm_init(APMState *apm, apm_ctrl_changed_t callback, void *arg)
+{
+    apm->callback = callback;
+    apm->arg = arg;
+
+    /* ioport 0xb2, 0xb3 */
+    register_ioport_write(APM_CNT_IOPORT, 2, 1, apm_ioport_writeb, apm);
+    register_ioport_read(APM_CNT_IOPORT, 2, 1, apm_ioport_readb, apm);
+}
diff --git a/hw/apm.h b/hw/apm.h
new file mode 100644
index 0000000..f7c741e
--- /dev/null
+++ b/hw/apm.h
@@ -0,0 +1,22 @@
+#ifndef APM_H
+#define APM_H
+
+#include <stdint.h>
+#include "qemu-common.h"
+#include "hw.h"
+
+typedef void (*apm_ctrl_changed_t)(uint32_t val, void *arg);
+
+typedef struct APMState {
+    uint8_t apmc;
+    uint8_t apms;
+
+    apm_ctrl_changed_t callback;
+    void *arg;
+} APMState;
+
+void apm_init(APMState *s, apm_ctrl_changed_t callback, void *arg);
+
+extern const VMStateDescription vmstate_apm;
+
+#endif /* APM_H */
commit fc0bdd995ca36a34cc576ee706df239dd5ff79a9
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri May 14 16:28:59 2010 +0900

    acpi: split out piix4 smbus routines from acpi.c into pm_smbus.c
    
    Split out piix4 smbus routines from acpi.c into pm_smbus.c and
    use it.
    The split out smbus emulation will be used later.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>
    Cc: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index b62117c..05c04e5 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -195,6 +195,7 @@ obj-i386-y += cirrus_vga.o apic.o ioapic.o piix_pci.o
 obj-i386-y += vmmouse.o vmport.o hpet.o
 obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
 obj-i386-y += debugcon.o multiboot.o
+obj-i386-y += pm_smbus.o
 
 # shared objects
 obj-ppc-y = ppc.o
@@ -220,6 +221,7 @@ obj-mips-y += dma.o vga.o i8259.o
 obj-mips-y += g364fb.o jazz_led.o
 obj-mips-y += gt64xxx.o pckbd.o mc146818rtc.o
 obj-mips-y += piix4.o cirrus_vga.o
+obj-mips-y += pm_smbus.o
 
 obj-microblaze-y = petalogix_s3adsp1800_mmu.o
 
diff --git a/hw/acpi.c b/hw/acpi.c
index e3b63b7..ad8f4c7 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -17,6 +17,7 @@
  */
 #include "hw.h"
 #include "pc.h"
+#include "pm_smbus.h"
 #include "pci.h"
 #include "qemu-timer.h"
 #include "sysemu.h"
@@ -39,15 +40,9 @@ typedef struct PIIX4PMState {
     uint8_t apms;
     QEMUTimer *tmr_timer;
     int64_t tmr_overflow_time;
-    i2c_bus *smbus;
-    uint8_t smb_stat;
-    uint8_t smb_ctl;
-    uint8_t smb_cmd;
-    uint8_t smb_addr;
-    uint8_t smb_data0;
-    uint8_t smb_data1;
-    uint8_t smb_data[32];
-    uint8_t smb_index;
+
+    PMSMBus smb;
+
     qemu_irq irq;
     qemu_irq cmos_s3;
     qemu_irq smi_irq;
@@ -68,14 +63,6 @@ typedef struct PIIX4PMState {
 #define ACPI_ENABLE 0xf1
 #define ACPI_DISABLE 0xf0
 
-#define SMBHSTSTS 0x00
-#define SMBHSTCNT 0x02
-#define SMBHSTCMD 0x03
-#define SMBHSTADD 0x04
-#define SMBHSTDAT0 0x05
-#define SMBHSTDAT1 0x06
-#define SMBBLKDAT 0x07
-
 static PIIX4PMState *pm_state;
 
 static uint32_t get_pmtmr(PIIX4PMState *s)
@@ -282,141 +269,6 @@ static void acpi_dbg_writel(void *opaque, uint32_t addr, uint32_t val)
 #endif
 }
 
-static void smb_transaction(PIIX4PMState *s)
-{
-    uint8_t prot = (s->smb_ctl >> 2) & 0x07;
-    uint8_t read = s->smb_addr & 0x01;
-    uint8_t cmd = s->smb_cmd;
-    uint8_t addr = s->smb_addr >> 1;
-    i2c_bus *bus = s->smbus;
-
-#ifdef DEBUG
-    printf("SMBus trans addr=0x%02x prot=0x%02x\n", addr, prot);
-#endif
-    switch(prot) {
-    case 0x0:
-        smbus_quick_command(bus, addr, read);
-        break;
-    case 0x1:
-        if (read) {
-            s->smb_data0 = smbus_receive_byte(bus, addr);
-        } else {
-            smbus_send_byte(bus, addr, cmd);
-        }
-        break;
-    case 0x2:
-        if (read) {
-            s->smb_data0 = smbus_read_byte(bus, addr, cmd);
-        } else {
-            smbus_write_byte(bus, addr, cmd, s->smb_data0);
-        }
-        break;
-    case 0x3:
-        if (read) {
-            uint16_t val;
-            val = smbus_read_word(bus, addr, cmd);
-            s->smb_data0 = val;
-            s->smb_data1 = val >> 8;
-        } else {
-            smbus_write_word(bus, addr, cmd, (s->smb_data1 << 8) | s->smb_data0);
-        }
-        break;
-    case 0x5:
-        if (read) {
-            s->smb_data0 = smbus_read_block(bus, addr, cmd, s->smb_data);
-        } else {
-            smbus_write_block(bus, addr, cmd, s->smb_data, s->smb_data0);
-        }
-        break;
-    default:
-        goto error;
-    }
-    return;
-
-  error:
-    s->smb_stat |= 0x04;
-}
-
-static void smb_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
-{
-    PIIX4PMState *s = opaque;
-    addr &= 0x3f;
-#ifdef DEBUG
-    printf("SMB writeb port=0x%04x val=0x%02x\n", addr, val);
-#endif
-    switch(addr) {
-    case SMBHSTSTS:
-        s->smb_stat = 0;
-        s->smb_index = 0;
-        break;
-    case SMBHSTCNT:
-        s->smb_ctl = val;
-        if (val & 0x40)
-            smb_transaction(s);
-        break;
-    case SMBHSTCMD:
-        s->smb_cmd = val;
-        break;
-    case SMBHSTADD:
-        s->smb_addr = val;
-        break;
-    case SMBHSTDAT0:
-        s->smb_data0 = val;
-        break;
-    case SMBHSTDAT1:
-        s->smb_data1 = val;
-        break;
-    case SMBBLKDAT:
-        s->smb_data[s->smb_index++] = val;
-        if (s->smb_index > 31)
-            s->smb_index = 0;
-        break;
-    default:
-        break;
-    }
-}
-
-static uint32_t smb_ioport_readb(void *opaque, uint32_t addr)
-{
-    PIIX4PMState *s = opaque;
-    uint32_t val;
-
-    addr &= 0x3f;
-    switch(addr) {
-    case SMBHSTSTS:
-        val = s->smb_stat;
-        break;
-    case SMBHSTCNT:
-        s->smb_index = 0;
-        val = s->smb_ctl & 0x1f;
-        break;
-    case SMBHSTCMD:
-        val = s->smb_cmd;
-        break;
-    case SMBHSTADD:
-        val = s->smb_addr;
-        break;
-    case SMBHSTDAT0:
-        val = s->smb_data0;
-        break;
-    case SMBHSTDAT1:
-        val = s->smb_data1;
-        break;
-    case SMBBLKDAT:
-        val = s->smb_data[s->smb_index++];
-        if (s->smb_index > 31)
-            s->smb_index = 0;
-        break;
-    default:
-        val = 0;
-        break;
-    }
-#ifdef DEBUG
-    printf("SMB readb port=0x%04x val=0x%02x\n", addr, val);
-#endif
-    return val;
-}
-
 static void pm_io_space_update(PIIX4PMState *s)
 {
     uint32_t pm_io_base;
@@ -545,8 +397,8 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
     pci_conf[0x90] = smb_io_base | 1;
     pci_conf[0x91] = smb_io_base >> 8;
     pci_conf[0xd2] = 0x09;
-    register_ioport_write(smb_io_base, 64, 1, smb_ioport_writeb, s);
-    register_ioport_read(smb_io_base, 64, 1, smb_ioport_readb, s);
+    register_ioport_write(smb_io_base, 64, 1, smb_ioport_writeb, &s->smb);
+    register_ioport_read(smb_io_base, 64, 1, smb_ioport_readb, &s->smb);
 
     s->tmr_timer = qemu_new_timer(vm_clock, pm_tmr_timer, s);
 
@@ -554,13 +406,13 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
 
     vmstate_register(0, &vmstate_acpi, s);
 
-    s->smbus = i2c_init_bus(NULL, "i2c");
+    pm_smbus_init(NULL, &s->smb);
     s->irq = sci_irq;
     s->cmos_s3 = cmos_s3;
     s->smi_irq = smi_irq;
     qemu_register_reset(piix4_reset, s);
 
-    return s->smbus;
+    return s->smb.smbus;
 }
 
 #define GPE_BASE 0xafe0
diff --git a/hw/pm_smbus.c b/hw/pm_smbus.c
new file mode 100644
index 0000000..6ef6b9e
--- /dev/null
+++ b/hw/pm_smbus.c
@@ -0,0 +1,178 @@
+/*
+ * PC SMBus implementation
+ * splitted from acpi.c
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+#include "hw.h"
+#include "pc.h"
+#include "pm_smbus.h"
+#include "pci.h"
+#include "qemu-timer.h"
+#include "sysemu.h"
+#include "i2c.h"
+#include "smbus.h"
+#include "kvm.h"
+
+/* no save/load? */
+
+#define SMBHSTSTS       0x00
+#define SMBHSTCNT       0x02
+#define SMBHSTCMD       0x03
+#define SMBHSTADD       0x04
+#define SMBHSTDAT0      0x05
+#define SMBHSTDAT1      0x06
+#define SMBBLKDAT       0x07
+
+static void smb_transaction(PMSMBus *s)
+{
+    uint8_t prot = (s->smb_ctl >> 2) & 0x07;
+    uint8_t read = s->smb_addr & 0x01;
+    uint8_t cmd = s->smb_cmd;
+    uint8_t addr = s->smb_addr >> 1;
+    i2c_bus *bus = s->smbus;
+
+#ifdef DEBUG
+    printf("SMBus trans addr=0x%02x prot=0x%02x\n", addr, prot);
+#endif
+    switch(prot) {
+    case 0x0:
+        smbus_quick_command(bus, addr, read);
+        break;
+    case 0x1:
+        if (read) {
+            s->smb_data0 = smbus_receive_byte(bus, addr);
+        } else {
+            smbus_send_byte(bus, addr, cmd);
+        }
+        break;
+    case 0x2:
+        if (read) {
+            s->smb_data0 = smbus_read_byte(bus, addr, cmd);
+        } else {
+            smbus_write_byte(bus, addr, cmd, s->smb_data0);
+        }
+        break;
+    case 0x3:
+        if (read) {
+            uint16_t val;
+            val = smbus_read_word(bus, addr, cmd);
+            s->smb_data0 = val;
+            s->smb_data1 = val >> 8;
+        } else {
+            smbus_write_word(bus, addr, cmd, (s->smb_data1 << 8) | s->smb_data0);
+        }
+        break;
+    case 0x5:
+        if (read) {
+            s->smb_data0 = smbus_read_block(bus, addr, cmd, s->smb_data);
+        } else {
+            smbus_write_block(bus, addr, cmd, s->smb_data, s->smb_data0);
+        }
+        break;
+    default:
+        goto error;
+    }
+    return;
+
+  error:
+    s->smb_stat |= 0x04;
+}
+
+void smb_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+    PMSMBus *s = opaque;
+    addr &= 0x3f;
+#ifdef DEBUG
+    printf("SMB writeb port=0x%04x val=0x%02x\n", addr, val);
+#endif
+    switch(addr) {
+    case SMBHSTSTS:
+        s->smb_stat = 0;
+        s->smb_index = 0;
+        break;
+    case SMBHSTCNT:
+        s->smb_ctl = val;
+        if (val & 0x40)
+            smb_transaction(s);
+        break;
+    case SMBHSTCMD:
+        s->smb_cmd = val;
+        break;
+    case SMBHSTADD:
+        s->smb_addr = val;
+        break;
+    case SMBHSTDAT0:
+        s->smb_data0 = val;
+        break;
+    case SMBHSTDAT1:
+        s->smb_data1 = val;
+        break;
+    case SMBBLKDAT:
+        s->smb_data[s->smb_index++] = val;
+        if (s->smb_index > 31)
+            s->smb_index = 0;
+        break;
+    default:
+        break;
+    }
+}
+
+uint32_t smb_ioport_readb(void *opaque, uint32_t addr)
+{
+    PMSMBus *s = opaque;
+    uint32_t val;
+
+    addr &= 0x3f;
+    switch(addr) {
+    case SMBHSTSTS:
+        val = s->smb_stat;
+        break;
+    case SMBHSTCNT:
+        s->smb_index = 0;
+        val = s->smb_ctl & 0x1f;
+        break;
+    case SMBHSTCMD:
+        val = s->smb_cmd;
+        break;
+    case SMBHSTADD:
+        val = s->smb_addr;
+        break;
+    case SMBHSTDAT0:
+        val = s->smb_data0;
+        break;
+    case SMBHSTDAT1:
+        val = s->smb_data1;
+        break;
+    case SMBBLKDAT:
+        val = s->smb_data[s->smb_index++];
+        if (s->smb_index > 31)
+            s->smb_index = 0;
+        break;
+    default:
+        val = 0;
+        break;
+    }
+#ifdef DEBUG
+    printf("SMB readb port=0x%04x val=0x%02x\n", addr, val);
+#endif
+    return val;
+}
+
+void pm_smbus_init(DeviceState *parent, PMSMBus *smb)
+{
+    smb->smbus = i2c_init_bus(parent, "i2c");
+}
diff --git a/hw/pm_smbus.h b/hw/pm_smbus.h
new file mode 100644
index 0000000..4750a40
--- /dev/null
+++ b/hw/pm_smbus.h
@@ -0,0 +1,21 @@
+#ifndef PM_SMBUS_H
+#define PM_SMBUS_H
+
+typedef struct PMSMBus {
+    i2c_bus *smbus;
+
+    uint8_t smb_stat;
+    uint8_t smb_ctl;
+    uint8_t smb_cmd;
+    uint8_t smb_addr;
+    uint8_t smb_data0;
+    uint8_t smb_data1;
+    uint8_t smb_data[32];
+    uint8_t smb_index;
+} PMSMBus;
+
+void pm_smbus_init(DeviceState *parent, PMSMBus *smb);
+void smb_ioport_writeb(void *opaque, uint32_t addr, uint32_t val);
+uint32_t smb_ioport_readb(void *opaque, uint32_t addr);
+
+#endif /* !PM_SMBUS_H */
commit dc6839100ee42544bffec26bc6a58187c90eeb44
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Sat May 15 13:32:43 2010 +0200

    mc146818rtc: Register vmstate via qdev
    
    After defining the required alias ID, we can push vmstate registration
    of mc146818rtc to qdev.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 89a423e..905e670 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -609,7 +609,7 @@ static int rtc_initfn(ISADevice *dev)
     register_ioport_write(base, 2, 1, cmos_ioport_write, s);
     register_ioport_read(base, 2, 1, cmos_ioport_read, s);
 
-    vmstate_register(base, &vmstate_rtc, s);
+    qdev_set_legacy_instance_id(&dev->qdev, base, 2);
     qemu_register_reset(rtc_reset, s);
     return 0;
 }
@@ -628,6 +628,7 @@ static ISADeviceInfo mc146818rtc_info = {
     .qdev.name     = "mc146818rtc",
     .qdev.size     = sizeof(RTCState),
     .qdev.no_user  = 1,
+    .qdev.vmsd     = &vmstate_rtc,
     .init          = rtc_initfn,
     .qdev.props    = (Property[]) {
         DEFINE_PROP_INT32("base_year", RTCState, base_year, 1980),
commit a64405d1b5d4badbdf4575ba9bfe2b686145b1c9
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Sat May 15 13:32:42 2010 +0200

    fdc: Register vmstate via qdev
    
    Establish vmstate containers for ISA and sysbus variant, define the
    iobase as instance ID alias, and let qdev do the vmstate registration
    work.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/fdc.c b/hw/fdc.c
index c4ca9e9..6306496 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -1918,7 +1918,7 @@ FDCtrl *sun4m_fdctrl_init(qemu_irq irq, target_phys_addr_t io_base,
     return fdctrl;
 }
 
-static int fdctrl_init_common(FDCtrl *fdctrl, target_phys_addr_t io_base)
+static int fdctrl_init_common(FDCtrl *fdctrl)
 {
     int i, j;
     static int command_tables_inited = 0;
@@ -1949,7 +1949,6 @@ static int fdctrl_init_common(FDCtrl *fdctrl, target_phys_addr_t io_base)
         DMA_register_channel(fdctrl->dma_chann, &fdctrl_transfer_handler, fdctrl);
     fdctrl_connect_drives(fdctrl);
 
-    vmstate_register(io_base, &vmstate_fdc, fdctrl);
     return 0;
 }
 
@@ -1973,7 +1972,8 @@ static int isabus_fdc_init1(ISADevice *dev)
     isa_init_irq(&isa->busdev, &fdctrl->irq, isairq);
     fdctrl->dma_chann = dma_chann;
 
-    ret = fdctrl_init_common(fdctrl, iobase);
+    qdev_set_legacy_instance_id(&dev->qdev, iobase, 2);
+    ret = fdctrl_init_common(fdctrl);
 
     return ret;
 }
@@ -1991,7 +1991,8 @@ static int sysbus_fdc_init1(SysBusDevice *dev)
     qdev_init_gpio_in(&dev->qdev, fdctrl_handle_tc, 1);
     fdctrl->dma_chann = -1;
 
-    ret = fdctrl_init_common(fdctrl, io);
+    qdev_set_legacy_instance_id(&dev->qdev, io, 2);
+    ret = fdctrl_init_common(fdctrl);
 
     return ret;
 }
@@ -2008,14 +2009,26 @@ static int sun4m_fdc_init1(SysBusDevice *dev)
     qdev_init_gpio_in(&dev->qdev, fdctrl_handle_tc, 1);
 
     fdctrl->sun4m = 1;
-    return fdctrl_init_common(fdctrl, io);
+    qdev_set_legacy_instance_id(&dev->qdev, io, 2);
+    return fdctrl_init_common(fdctrl);
 }
 
+static const VMStateDescription vmstate_isa_fdc ={
+    .name = "fdc",
+    .version_id = 2,
+    .minimum_version_id = 2,
+    .fields = (VMStateField []) {
+        VMSTATE_STRUCT(state, FDCtrlISABus, 0, vmstate_fdc, FDCtrl),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static ISADeviceInfo isa_fdc_info = {
     .init = isabus_fdc_init1,
     .qdev.name  = "isa-fdc",
     .qdev.size  = sizeof(FDCtrlISABus),
     .qdev.no_user = 1,
+    .qdev.vmsd  = &vmstate_isa_fdc,
     .qdev.reset = fdctrl_external_reset_isa,
     .qdev.props = (Property[]) {
         DEFINE_PROP_DRIVE("driveA", FDCtrlISABus, state.drives[0].dinfo),
@@ -2024,10 +2037,21 @@ static ISADeviceInfo isa_fdc_info = {
     },
 };
 
+static const VMStateDescription vmstate_sysbus_fdc ={
+    .name = "fdc",
+    .version_id = 2,
+    .minimum_version_id = 2,
+    .fields = (VMStateField []) {
+        VMSTATE_STRUCT(state, FDCtrlSysBus, 0, vmstate_fdc, FDCtrl),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static SysBusDeviceInfo sysbus_fdc_info = {
     .init = sysbus_fdc_init1,
     .qdev.name  = "sysbus-fdc",
     .qdev.size  = sizeof(FDCtrlSysBus),
+    .qdev.vmsd  = &vmstate_sysbus_fdc,
     .qdev.reset = fdctrl_external_reset_sysbus,
     .qdev.props = (Property[]) {
         DEFINE_PROP_DRIVE("driveA", FDCtrlSysBus, state.drives[0].dinfo),
@@ -2040,6 +2064,7 @@ static SysBusDeviceInfo sun4m_fdc_info = {
     .init = sun4m_fdc_init1,
     .qdev.name  = "SUNW,fdtwo",
     .qdev.size  = sizeof(FDCtrlSysBus),
+    .qdev.vmsd  = &vmstate_sysbus_fdc,
     .qdev.reset = fdctrl_external_reset_sysbus,
     .qdev.props = (Property[]) {
         DEFINE_PROP_DRIVE("drive", FDCtrlSysBus, state.drives[0].dinfo),
commit 1cc9f5143936d381366bdd55a9b28d4dfb891e08
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Sat May 15 13:32:41 2010 +0200

    serial: Register vmstate via qdev
    
    At least for isa-serial, we can already let qdev do the vmstate
    registration for us. It just takes wrapping vmstate for the
    encapsulating ISASerialState and defining the proper instance ID
    aliases.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/serial.c b/hw/serial.c
index 90213c4..9102edb 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -771,7 +771,7 @@ static int serial_isa_initfn(ISADevice *dev)
     s->baudbase = 115200;
     isa_init_irq(dev, &s->irq, isa->isairq);
     serial_init_core(s);
-    vmstate_register(isa->iobase, &vmstate_serial, s);
+    qdev_set_legacy_instance_id(&dev->qdev, isa->iobase, 3);
 
     register_ioport_write(isa->iobase, 8, 1, serial_ioport_write, s);
     register_ioport_read(isa->iobase, 8, 1, serial_ioport_read, s);
@@ -790,6 +790,16 @@ SerialState *serial_isa_init(int index, CharDriverState *chr)
     return &DO_UPCAST(ISASerialState, dev, dev)->state;
 }
 
+static const VMStateDescription vmstate_isa_serial = {
+    .name = "serial",
+    .version_id = 3,
+    .minimum_version_id = 2,
+    .fields      = (VMStateField []) {
+        VMSTATE_STRUCT(state, ISASerialState, 0, vmstate_serial, SerialState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 SerialState *serial_init(int base, qemu_irq irq, int baudbase,
                          CharDriverState *chr)
 {
@@ -956,6 +966,7 @@ SerialState *serial_mm_init (target_phys_addr_t base, int it_shift,
 static ISADeviceInfo serial_isa_info = {
     .qdev.name  = "isa-serial",
     .qdev.size  = sizeof(ISASerialState),
+    .qdev.vmsd  = &vmstate_isa_serial,
     .init       = serial_isa_initfn,
     .qdev.props = (Property[]) {
         DEFINE_PROP_UINT32("index", ISASerialState, index,   -1),
commit 4d2ffa08b601bdd40d9ccf225480c0a7e90ca078
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Sat May 15 13:32:40 2010 +0200

    vmstate: Add support for alias ID
    
    Some legacy users (mostly PC devices) of vmstate_register manage
    instance IDs on their own, and that unfortunately in a way that is
    incompatible with automatically generated ones. This so far prevents
    switching those users to vmstates that are registered by qdev.
    
    To establish a migration path, this patch introduces the concept of
    alias IDs. They can be passed to an extended vmstate registration
    service, and qdev provides a set service to be used during device init.
    find_se will consider the alias in addition to the default ID. We can
    then start generating the default ID automatically and writing it on
    vmsave, thus converting that format without breaking support for upward
    migration.
    
    The user is required specify the highest vmstate version for which the
    alias is required. Once this version falls behind the minimum required
    for a specific vmstate, an assertion triggers to motivate cleaning up
    the obsolete alias.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/hw.h b/hw/hw.h
index 2d39724..fc2d184 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -758,5 +758,9 @@ extern void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
                                void *opaque);
 extern int vmstate_register(int instance_id, const VMStateDescription *vmsd,
                             void *base);
+extern int vmstate_register_with_alias_id(int instance_id,
+                                          const VMStateDescription *vmsd,
+                                          void *base, int alias_id,
+                                          int required_for_version);
 void vmstate_unregister(const VMStateDescription *vmsd, void *opaque);
 #endif
diff --git a/hw/qdev.c b/hw/qdev.c
index d3bf0fa..af17486 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -93,6 +93,7 @@ static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info)
         assert(bus->allow_hotplug);
         dev->hotplugged = 1;
     }
+    dev->instance_id_alias = -1;
     dev->state = DEV_STATE_CREATED;
     return dev;
 }
@@ -278,12 +279,23 @@ int qdev_init(DeviceState *dev)
         return rc;
     }
     qemu_register_reset(qdev_reset, dev);
-    if (dev->info->vmsd)
-        vmstate_register(-1, dev->info->vmsd, dev);
+    if (dev->info->vmsd) {
+        vmstate_register_with_alias_id(-1, dev->info->vmsd, dev,
+                                       dev->instance_id_alias,
+                                       dev->alias_required_for_version);
+    }
     dev->state = DEV_STATE_INITIALIZED;
     return 0;
 }
 
+void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
+                                 int required_for_version)
+{
+    assert(dev->state == DEV_STATE_CREATED);
+    dev->instance_id_alias = alias_id;
+    dev->alias_required_for_version = required_for_version;
+}
+
 int qdev_unplug(DeviceState *dev)
 {
     if (!dev->parent_bus->allow_hotplug) {
diff --git a/hw/qdev.h b/hw/qdev.h
index d8fbc73..a44060e 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -44,6 +44,8 @@ struct DeviceState {
     QLIST_HEAD(, BusState) child_bus;
     int num_child_bus;
     QLIST_ENTRY(DeviceState) sibling;
+    int instance_id_alias;
+    int alias_required_for_version;
 };
 
 typedef void (*bus_dev_printfn)(Monitor *mon, DeviceState *dev, int indent);
@@ -112,6 +114,8 @@ int qdev_device_help(QemuOpts *opts);
 DeviceState *qdev_device_add(QemuOpts *opts);
 int qdev_init(DeviceState *dev) QEMU_WARN_UNUSED_RESULT;
 void qdev_init_nofail(DeviceState *dev);
+void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
+                                 int required_for_version);
 int qdev_unplug(DeviceState *dev);
 void qdev_free(DeviceState *dev);
 int qdev_simple_unplug_cb(DeviceState *dev);
diff --git a/savevm.c b/savevm.c
index 74e553c..dc20390 100644
--- a/savevm.c
+++ b/savevm.c
@@ -991,6 +991,7 @@ typedef struct SaveStateEntry {
     QTAILQ_ENTRY(SaveStateEntry) entry;
     char idstr[256];
     int instance_id;
+    int alias_id;
     int version_id;
     int section_id;
     SaveSetParamsHandler *set_params;
@@ -1079,11 +1080,16 @@ void unregister_savevm(const char *idstr, void *opaque)
     }
 }
 
-int vmstate_register(int instance_id, const VMStateDescription *vmsd,
-                     void *opaque)
+int vmstate_register_with_alias_id(int instance_id,
+                                   const VMStateDescription *vmsd,
+                                   void *opaque, int alias_id,
+                                   int required_for_version)
 {
     SaveStateEntry *se;
 
+    /* If this triggers, alias support can be dropped for the vmsd. */
+    assert(alias_id == -1 || required_for_version >= vmsd->minimum_version_id);
+
     se = qemu_mallocz(sizeof(SaveStateEntry));
     pstrcpy(se->idstr, sizeof(se->idstr), vmsd->name);
     se->version_id = vmsd->version_id;
@@ -1093,6 +1099,7 @@ int vmstate_register(int instance_id, const VMStateDescription *vmsd,
     se->load_state = NULL;
     se->opaque = opaque;
     se->vmsd = vmsd;
+    se->alias_id = alias_id;
 
     if (instance_id == -1) {
         se->instance_id = calculate_new_instance_id(vmsd->name);
@@ -1104,6 +1111,12 @@ int vmstate_register(int instance_id, const VMStateDescription *vmsd,
     return 0;
 }
 
+int vmstate_register(int instance_id, const VMStateDescription *vmsd,
+                     void *opaque)
+{
+    return vmstate_register_with_alias_id(instance_id, vmsd, opaque, -1, 0);
+}
+
 void vmstate_unregister(const VMStateDescription *vmsd, void *opaque)
 {
     SaveStateEntry *se, *new_se;
@@ -1433,7 +1446,8 @@ static SaveStateEntry *find_se(const char *idstr, int instance_id)
 
     QTAILQ_FOREACH(se, &savevm_handlers, entry) {
         if (!strcmp(se->idstr, idstr) &&
-            instance_id == se->instance_id)
+            (instance_id == se->instance_id ||
+             instance_id == se->alias_id))
             return se;
     }
     return NULL;
commit ec86f3e1af558a9a6f8476b9c1903cb6f152b771
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Sat May 15 13:32:39 2010 +0200

    vmstate: Drop unused post_save handler
    
    No device makes use of it anymore.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/hw.h b/hw/hw.h
index 328b704..2d39724 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -321,7 +321,6 @@ struct VMStateDescription {
     int (*pre_load)(void *opaque);
     int (*post_load)(void *opaque, int version_id);
     void (*pre_save)(void *opaque);
-    void (*post_save)(void *opaque);
     VMStateField *fields;
 };
 
diff --git a/savevm.c b/savevm.c
index 31a419c..74e553c 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1231,9 +1231,6 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
         }
         field++;
     }
-    if (vmsd->post_save) {
-        vmsd->post_save(opaque);
-    }
 }
 
 static int vmstate_load(QEMUFile *f, SaveStateEntry *se, int version_id)
commit 604be20023dc1e03f14f76f76be8023e6abfe14a
Author: Shin-ichiro KAWASAKI <kawasaki at juno.dti.ne.jp>
Date:   Sat May 15 21:25:39 2010 +0900

    sh: sm501: add 2D engine support
    
    In linux kernel v2.6.33, sm501 frame buffer driver modified to support
    2D graphics engine on sm501 chip.  One example is "fill rectangle" operation.
    But current qemu's sm501 emulation doesn't support it.  This results in
    graphics console disturbance.
    
    This patch introduces sm501 2D graphics engine emulation and solve this problem.
    
        Add SM501 2D hardware engine support.
    
         - Add 2D engine register set read/write handlers.
         - Support 'fill rectangle'. Other operations are left for future work.
         - Update SM501 support status comment.
    
    Signed-off-by: Shin-ichiro KAWASAKI <kawasaki at juno.dti.ne.jp>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/sm501.c b/hw/sm501.c
index 9310014..b5ec2da 100644
--- a/hw/sm501.c
+++ b/hw/sm501.c
@@ -31,16 +31,16 @@
 #include "qdev-addr.h"
 
 /*
- * Status: 2008/11/02
+ * Status: 2010/05/07
  *   - Minimum implementation for Linux console : mmio regs and CRT layer.
- *   - Always updates full screen.
+ *   - 2D grapihcs acceleration partially supported : only fill rectangle.
  *
  * TODO:
  *   - Panel support
- *   - Hardware cursor support
  *   - Touch panel support
  *   - USB support
  *   - UART support
+ *   - More 2D graphics engine support
  *   - Performance tuning
  */
 
@@ -510,6 +510,18 @@ typedef struct SM501State {
     uint32_t dc_crt_hwc_color_1_2;
     uint32_t dc_crt_hwc_color_3;
 
+    uint32_t twoD_destination;
+    uint32_t twoD_dimension;
+    uint32_t twoD_control;
+    uint32_t twoD_pitch;
+    uint32_t twoD_foreground;
+    uint32_t twoD_stretch;
+    uint32_t twoD_color_compare_mask;
+    uint32_t twoD_mask;
+    uint32_t twoD_window_width;
+    uint32_t twoD_source_base;
+    uint32_t twoD_destination_base;
+
 } SM501State;
 
 static uint32_t get_local_mem_size_index(uint32_t size)
@@ -619,6 +631,69 @@ static int within_hwc_y_range(SM501State *state, int y, int crt)
     return (hwc_y <= y && y < hwc_y + SM501_HWC_HEIGHT);
 }
 
+static void sm501_2d_operation(SM501State * s)
+{
+    /* obtain operation parameters */
+    int operation = (s->twoD_control >> 16) & 0x1f;
+    int dst_x = (s->twoD_destination >> 16) & 0x01FFF;
+    int dst_y = s->twoD_destination & 0xFFFF;
+    int operation_width = (s->twoD_dimension >> 16) & 0x1FFF;
+    int operation_height = s->twoD_dimension & 0xFFFF;
+    uint32_t color = s->twoD_foreground;
+    int format_flags = (s->twoD_stretch >> 20) & 0x3;
+    int addressing = (s->twoD_stretch >> 16) & 0xF;
+
+    /* get frame buffer info */
+#if 0 /* for future use */
+    uint8_t * src = s->local_mem + (s->twoD_source_base & 0x03FFFFFF);
+#endif
+    uint8_t * dst = s->local_mem + (s->twoD_destination_base & 0x03FFFFFF);
+    int dst_width = (s->dc_crt_h_total & 0x00000FFF) + 1;
+
+    if (addressing != 0x0) {
+        printf("%s: only XY addressing is supported.\n", __func__);
+        abort();
+    }
+
+    if ((s->twoD_source_base & 0x08000000) ||
+        (s->twoD_destination_base & 0x08000000)) {
+        printf("%s: only local memory is supported.\n", __func__);
+        abort();
+    }
+
+    switch (operation) {
+    case 0x01: /* fill rectangle */
+
+#define FILL_RECT(_bpp, _pixel_type) {                                      \
+        int y, x;                                                           \
+        for (y = 0; y < operation_height; y++) {                            \
+            for (x = 0; x < operation_width; x++) {                         \
+                int index = ((dst_y + y) * dst_width + dst_x + x) * _bpp;   \
+                *(_pixel_type*)&dst[index] = (_pixel_type)color;            \
+            }                                                               \
+        }                                                                   \
+    }
+
+        switch (format_flags) {
+        case 0:
+            FILL_RECT(1, uint8_t);
+            break;
+        case 1:
+            FILL_RECT(2, uint16_t);
+            break;
+        case 2:
+            FILL_RECT(4, uint32_t);
+            break;
+        }
+        break;
+
+    default:
+        printf("non-implemented SM501 2D operation. %d\n", operation);
+        abort();
+        break;
+    }
+}
+
 static uint32_t sm501_system_config_read(void *opaque, target_phys_addr_t addr)
 {
     SM501State * s = (SM501State *)opaque;
@@ -969,6 +1044,92 @@ static CPUWriteMemoryFunc * const sm501_disp_ctrl_writefn[] = {
     &sm501_disp_ctrl_write,
 };
 
+static uint32_t sm501_2d_engine_read(void *opaque, target_phys_addr_t addr)
+{
+    SM501State * s = (SM501State *)opaque;
+    uint32_t ret = 0;
+    SM501_DPRINTF("sm501 2d engine regs : read addr=%x\n", (int)addr);
+
+    switch(addr) {
+    case SM501_2D_SOURCE_BASE:
+        ret = s->twoD_source_base;
+        break;
+    default:
+        printf("sm501 disp ctrl : not implemented register read."
+               " addr=%x\n", (int)addr);
+        abort();
+    }
+
+    return ret;
+}
+
+static void sm501_2d_engine_write(void *opaque,
+                                  target_phys_addr_t addr, uint32_t value)
+{
+    SM501State * s = (SM501State *)opaque;
+    SM501_DPRINTF("sm501 2d engine regs : write addr=%x, val=%x\n",
+                  addr, value);
+
+    switch(addr) {
+    case SM501_2D_DESTINATION:
+        s->twoD_destination = value;
+        break;
+    case SM501_2D_DIMENSION:
+        s->twoD_dimension = value;
+        break;
+    case SM501_2D_CONTROL:
+        s->twoD_control = value;
+
+        /* do 2d operation if start flag is set. */
+        if (value & 0x80000000) {
+            sm501_2d_operation(s);
+            s->twoD_control &= ~0x80000000; /* start flag down */
+        }
+
+        break;
+    case SM501_2D_PITCH:
+        s->twoD_pitch = value;
+        break;
+    case SM501_2D_FOREGROUND:
+        s->twoD_foreground = value;
+        break;
+    case SM501_2D_STRETCH:
+        s->twoD_stretch = value;
+        break;
+    case SM501_2D_COLOR_COMPARE_MASK:
+        s->twoD_color_compare_mask = value;
+        break;
+    case SM501_2D_MASK:
+        s->twoD_mask = value;
+        break;
+    case SM501_2D_WINDOW_WIDTH:
+        s->twoD_window_width = value;
+        break;
+    case SM501_2D_SOURCE_BASE:
+        s->twoD_source_base = value;
+        break;
+    case SM501_2D_DESTINATION_BASE:
+        s->twoD_destination_base = value;
+        break;
+    default:
+        printf("sm501 2d engine : not implemented register write."
+               " addr=%x, val=%x\n", (int)addr, value);
+        abort();
+    }
+}
+
+static CPUReadMemoryFunc * const sm501_2d_engine_readfn[] = {
+    NULL,
+    NULL,
+    &sm501_2d_engine_read,
+};
+
+static CPUWriteMemoryFunc * const sm501_2d_engine_writefn[] = {
+    NULL,
+    NULL,
+    &sm501_2d_engine_write,
+};
+
 /* draw line functions for all console modes */
 
 #include "pixel_ops.h"
@@ -1195,6 +1356,7 @@ void sm501_init(uint32_t base, uint32_t local_mem_bytes, qemu_irq irq,
     DeviceState *dev;
     int sm501_system_config_index;
     int sm501_disp_ctrl_index;
+    int sm501_2d_engine_index;
 
     /* allocate management data region */
     s = (SM501State *)qemu_mallocz(sizeof(SM501State));
@@ -1223,6 +1385,10 @@ void sm501_init(uint32_t base, uint32_t local_mem_bytes, qemu_irq irq,
 						   sm501_disp_ctrl_writefn, s);
     cpu_register_physical_memory(base + MMIO_BASE_OFFSET + SM501_DC,
                                  0x1000, sm501_disp_ctrl_index);
+    sm501_2d_engine_index = cpu_register_io_memory(sm501_2d_engine_readfn,
+                                                   sm501_2d_engine_writefn, s);
+    cpu_register_physical_memory(base + MMIO_BASE_OFFSET + SM501_2D_ENGINE,
+                                 0x54, sm501_2d_engine_index);
 
     /* bridge to usb host emulation module */
     dev = qdev_create(NULL, "sysbus-ohci");
commit e5d3b98d5372c318e13a2f128f2198926c019990
Author: Andrzej Zaborowski <balrog at zabor.org>
Date:   Sat May 15 14:31:27 2010 +0200

    tmp105: update the register in post_load where it needs updating.
    
    This was the only user of .post_save as noticed by Jan Kiszka and
    seems to have been added there wrongly during conversion to
    VMStateDescription.
    
    Signed-off-by: Andrzej Zaborowski <balrogg at gmail.com>

diff --git a/hw/tmp105.c b/hw/tmp105.c
index 8343aff..f7e6f2b 100644
--- a/hw/tmp105.c
+++ b/hw/tmp105.c
@@ -173,16 +173,12 @@ static void tmp105_event(i2c_slave *i2c, enum i2c_event event)
     s->len = 0;
 }
 
-static void tmp105_post_save(void *opaque)
-{
-    TMP105State *s = opaque;
-    s->faults = tmp105_faultq[(s->config >> 3) & 3];		/* F */
-}
-
 static int tmp105_post_load(void *opaque, int version_id)
 {
     TMP105State *s = opaque;
 
+    s->faults = tmp105_faultq[(s->config >> 3) & 3];		/* F */
+
     tmp105_interrupt_update(s);
     return 0;
 }
@@ -192,7 +188,6 @@ static const VMStateDescription vmstate_tmp105 = {
     .version_id = 0,
     .minimum_version_id = 0,
     .minimum_version_id_old = 0,
-    .post_save = tmp105_post_save,
     .post_load = tmp105_post_load,
     .fields      = (VMStateField []) {
         VMSTATE_UINT8(len, TMP105State),
commit 26a823305d7fdf369453a8caf5efdd467acddc8c
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Fri May 14 19:32:21 2010 +0000

    cpus: add one 'const'
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cpus.c b/cpus.c
index 826886c..8341f6c 100644
--- a/cpus.c
+++ b/cpus.c
@@ -147,7 +147,7 @@ static int io_thread_fd = -1;
 static void qemu_event_increment(void)
 {
     /* Write 8 bytes to be compatible with eventfd.  */
-    static uint64_t val = 1;
+    static const uint64_t val = 1;
     ssize_t ret;
 
     if (io_thread_fd == -1)
commit af2960f942577a0d48f7368ca90fbaa783e77ac3
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Fri May 14 19:32:18 2010 +0000

    e1000: make some tables 'const'
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/e1000.c b/hw/e1000.c
index 34cc451..96d045d 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -544,8 +544,8 @@ start_xmit(E1000State *s)
 static int
 receive_filter(E1000State *s, const uint8_t *buf, int size)
 {
-    static uint8_t bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-    static int mta_shift[] = {4, 3, 2, 0};
+    static const uint8_t bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+    static const int mta_shift[] = {4, 3, 2, 0};
     uint32_t f, rctl = s->mac_reg[RCTL], ra[2], *rp;
 
     if (is_vlan_packet(s, buf) && vlan_rx_filter_enabled(s)) {
commit 117e1e8244f5943ca84c37d2a0ff4711cd795852
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Fri May 14 19:32:14 2010 +0000

    ide: make a table 'const'
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/ide/core.c b/hw/ide/core.c
index 0757528..b0165bc 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -36,7 +36,7 @@
 
 #define IDE_PAGE_SIZE 4096
 
-static int smart_attributes[][5] = {
+static const int smart_attributes[][5] = {
     /* id,  flags, val, wrst, thrsh */
     { 0x01, 0x03, 0x64, 0x64, 0x06}, /* raw read */
     { 0x03, 0x03, 0x64, 0x64, 0x46}, /* spin up */
commit 68f04a3c629c911a2ecf3d18d925f5ab28211fec
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Fri May 14 19:32:11 2010 +0000

    vga: make some tables 'const'
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/vga.c b/hw/vga.c
index db72115..87a1bb0 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -1171,7 +1171,7 @@ static inline int get_depth_index(DisplayState *s)
     }
 }
 
-static vga_draw_glyph8_func *vga_draw_glyph8_table[NB_DEPTHS] = {
+static vga_draw_glyph8_func * const vga_draw_glyph8_table[NB_DEPTHS] = {
     vga_draw_glyph8_8,
     vga_draw_glyph8_16,
     vga_draw_glyph8_16,
@@ -1181,7 +1181,7 @@ static vga_draw_glyph8_func *vga_draw_glyph8_table[NB_DEPTHS] = {
     vga_draw_glyph8_16,
 };
 
-static vga_draw_glyph8_func *vga_draw_glyph16_table[NB_DEPTHS] = {
+static vga_draw_glyph8_func * const vga_draw_glyph16_table[NB_DEPTHS] = {
     vga_draw_glyph16_8,
     vga_draw_glyph16_16,
     vga_draw_glyph16_16,
@@ -1191,7 +1191,7 @@ static vga_draw_glyph8_func *vga_draw_glyph16_table[NB_DEPTHS] = {
     vga_draw_glyph16_16,
 };
 
-static vga_draw_glyph9_func *vga_draw_glyph9_table[NB_DEPTHS] = {
+static vga_draw_glyph9_func * const vga_draw_glyph9_table[NB_DEPTHS] = {
     vga_draw_glyph9_8,
     vga_draw_glyph9_16,
     vga_draw_glyph9_16,
@@ -1251,7 +1251,7 @@ static void vga_get_text_resolution(VGACommonState *s, int *pwidth, int *pheight
 
 typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
 
-static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS] = {
+static rgb_to_pixel_dup_func * const rgb_to_pixel_dup_table[NB_DEPTHS] = {
     rgb_to_pixel8_dup,
     rgb_to_pixel15_dup,
     rgb_to_pixel16_dup,
@@ -1447,7 +1447,7 @@ enum {
     VGA_DRAW_LINE_NB,
 };
 
-static vga_draw_line_func *vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
+static vga_draw_line_func * const vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
     vga_draw_line2_8,
     vga_draw_line2_16,
     vga_draw_line2_16,
commit d08555c17ac9b3c51e9a2bc7d2b12891241c29ae
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Fri May 14 19:31:53 2010 +0000

    Compile virtio-9p-debug and virtio-9p-local once
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.objs b/Makefile.objs
index ecdd53e..110f8fd 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -226,6 +226,8 @@ sound-obj-$(CONFIG_CS4231A) += cs4231a.o
 adlib.o fmopl.o: QEMU_CFLAGS += -DBUILD_Y8950=0
 hw-obj-$(CONFIG_SOUND) += $(sound-obj-y)
 
+hw-obj-$(CONFIG_LINUX) += virtio-9p-debug.o virtio-9p-local.o
+
 ######################################################################
 # libdis
 # NOTE: the disassembler code is only needed for debugging
diff --git a/Makefile.target b/Makefile.target
index c092900..b62117c 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -168,7 +168,7 @@ obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o
 obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
 obj-y += vhost_net.o
 obj-$(CONFIG_VHOST_NET) += vhost.o
-obj-$(CONFIG_LINUX) += virtio-9p.o virtio-9p-debug.o virtio-9p-local.o
+obj-$(CONFIG_LINUX) += virtio-9p.o
 obj-y += rwhandler.o
 obj-$(CONFIG_KVM) += kvm.o kvm-all.o
 obj-$(CONFIG_NO_KVM) += kvm-stub.o
commit 7ac9f9be20b95e3963f0404fa6c5c5c9654106de
Merge: 14ac15d... c1667e4...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri May 14 10:56:56 2010 -0500

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

commit 14ac15d3ac8e0ef1c91204e2ac772b6412a6b99e
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue May 11 07:56:30 2010 -0500

    Update SeaBIOS
    
     - 7d09d0e Fix virtio compile errors on various gcc versions.
     - 89acfa3 Support for booting from virtio disks
     - 6d66316 smbios: avoid counting io hole as ram
     - e5cd945 Fix error causing USB HID "boot" protocol to not be enabled.
     - 0e88576 Add support for USB mice.
     - dd5a8a6 When USB keyboard active, don't send keyboard commands to ps2 port.
     - 5718d56 Document usb-hid.c functions.
     - e438b0c Further parallelize init when using CONFIG_THREAD_OPTIONROMS.
     - f59b5ac Handle unknown function addresses in tools/checkstack.py.
     - 9ba1dea Simplify build by manually resolving external symbols in layoutrom.py.
     - 698d3f9 USB EHCI should yield() whil waiting for controller to ack reset.
     - f9a774c Add __attribute__((__malloc__)) declaration to internal malloc funcs.
     - b7045ce Minor - remove redundant check from ata_try_dma.
     - 67f6d37 Fix possible unitialized variable issue in usb msc.
     - a7eb8fc Some improvements to optionrom preemption support.
     - d28b0fe Refactor USB hub code.
     - ba28541 Prep version for next release.
     - 12bffd5 Update version to 0.6.0.
     - 87ab2fb Improve USB EHCI timing.
     - d705e5a Disable inlining on old compilers.
     - bca0736 Force use of indirect function calls in inline assembler.
     - d7eb27e Don't move EBDA while an optionrom is running (CONFIG_THREAD_OPTIONROMS).
     - 7415270 Call to int1552 (from int1346) should set regs->dl.
     - 9dc243e Adjust debug levels of device discovery.
     - d9c9361 Default CONFIG_COREBOOT_FLASH on; make depend on CONFIG_COREBOOT.
     - c35e1e5 Restore segment limits in handle_1589 code.
     - 11cc662 Extend time for rtc to be ready.
     - 4ed378a Backup and restore registers when calling out to user funcs.
     - 68c5139 Enable irqs in kbd/clock calls that caller might "spin" on.
     - f628244 Process event on ps2 keyboard irq even if event already read.
     - a5d8458 Revert "Unify ps2 port data processing."
     - b9ed5e2 Handle variable length return of ps2 port GETID command.
     - 67a9eec Prevent ps2 irqs from messing up ps2 init.
     - 6704cf9 Revert "Rework disabling of ps2 port irqs."
     - 808939c Fix smp cpu detect on gcc 4.5.
     - a979c1c Improvements to tools/checkstack.py.
     - 190cc62 Add USB EHCI controller support.
     - 0770d67 Some USB UHCI and OHCI fixes and cleanups.
     - bfe7ca7 Minor - USB OHCI interrupt queue should be one larger.
     - 09e2f7c Reduce size of USB 'struct uhci_td'.
     - 406fad6 Dynamically allocate USB controller structures.
     - 4547eb9 Replace USB encoded 'u32 endp' scheme with explicit struct fields.
     - 8ebcac0 Further parallelize USB init by launching a thread per usb port.
     - e908665 Introduce simple "mutex" locking code.
     - 3b79f8b Only compile usb-hub.c and paravirt.c with 32bit code.
     - 357bdfa Prefer passing a USB "pipe" structure over a USB endp encoding.
     - 7fb8ba8 Add a generic "internal error" warning function.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/pc-bios/bios.bin b/pc-bios/bios.bin
index 7a8f0d0..f27ea89 100644
Binary files a/pc-bios/bios.bin and b/pc-bios/bios.bin differ
diff --git a/roms/seabios b/roms/seabios
index 8f469b9..7d09d0e 160000
--- a/roms/seabios
+++ b/roms/seabios
@@ -1 +1 @@
-Subproject commit 8f469b9676127ba6bb52609d89ec774e61db0ee1
+Subproject commit 7d09d0e3ba11310e973d4302c7fcc3fc2184e04c
commit 5acd0646b6033d40ef5d0ae06338cc354108f640
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Wed May 12 19:27:23 2010 +0000

    pckbd: don't use any static state
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/pckbd.c b/hw/pckbd.c
index 7998aa6..e83b8a6 100644
--- a/hw/pckbd.c
+++ b/hw/pckbd.c
@@ -126,8 +126,6 @@ typedef struct KBDState {
     target_phys_addr_t mask;
 } KBDState;
 
-static KBDState kbd_state;
-
 /* update irq and KBD_STAT_[MOUSE_]OBF */
 /* XXX: not generating the irqs if KBD_MODE_DISABLE_KBD is set may be
    incorrect, but it avoids having to simulate exact delays */
@@ -390,7 +388,7 @@ void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq,
                    target_phys_addr_t base, ram_addr_t size,
                    target_phys_addr_t mask)
 {
-    KBDState *s = &kbd_state;
+    KBDState *s = qemu_mallocz(sizeof(KBDState));
     int s_io_memory;
 
     s->irq_kbd = kbd_irq;
commit 9c0afd0e1df092e0d8a3cefdcb81e664cf18d97c
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Wed May 12 19:27:23 2010 +0000

    apb: don't use any static state
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index 095f3b7..65d8ba6 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -73,10 +73,9 @@ typedef struct APBState {
     uint32_t obio_irq_map[32];
     qemu_irq pci_irqs[32];
     uint32_t reset_control;
+    unsigned int nr_resets;
 } APBState;
 
-static unsigned int nr_resets;
-
 static void apb_config_writel (void *opaque, target_phys_addr_t addr,
                                uint32_t val)
 {
@@ -108,7 +107,7 @@ static void apb_config_writel (void *opaque, target_phys_addr_t addr,
             s->reset_control &= ~(val & RESET_WCMASK);
             s->reset_control |= val & RESET_WMASK;
             if (val & SOFT_POR) {
-                nr_resets = 0;
+                s->nr_resets = 0;
                 qemu_system_reset_request();
             } else if (val & SOFT_XIR) {
                 qemu_system_reset_request();
@@ -374,7 +373,7 @@ static void pci_pbm_reset(DeviceState *d)
         s->pci_irq_map[i] &= PBM_PCI_IMR_MASK;
     }
 
-    if (nr_resets++ == 0) {
+    if (s->nr_resets++ == 0) {
         /* Power on reset */
         s->reset_control = POR;
     }
commit 113c61069cb46f871f9c976f6b99097ec3a3cb8f
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Wed May 12 20:34:39 2010 +0200

    target-sparc: Fix wrong printf argument
    
    cpu_get_ccr() returns a target_ulong, so a type cast is needed to avoid
    wrong output on big endian hosts. We could also use TARGET_FMT_lx,
    but that would print 8 instead of 2 digits.
    
    Cc: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index 4642122..582de10 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -1490,7 +1490,7 @@ void cpu_dump_state(CPUState *env, FILE *f,
     }
 #ifdef TARGET_SPARC64
     cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
-                cpu_get_ccr(env));
+                (unsigned)cpu_get_ccr(env));
     cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
     cpu_fprintf(f, " xcc: ");
     cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
commit a72b517756cdced088f311367d5bfc0c352623fb
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Wed May 12 18:57:14 2010 +0000

    Update OpenBIOS images to r771
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/pc-bios/README b/pc-bios/README
index 437ef1c..fc940a7 100644
--- a/pc-bios/README
+++ b/pc-bios/README
@@ -14,9 +14,8 @@
 - OpenBIOS (http://www.openbios.org/) is a free (GPL v2) portable
   firmware implementation. The goal is to implement a 100% IEEE
   1275-1994 (referred to as Open Firmware) compliant firmware.
-  The included image for PowerPC (for 32 and 64 bit PPC CPUs) is
-  built from OpenBIOS SVN revision 721, the Sparc32 and Sparc64 ones
-  are built from OpenBIOS SVN revision 683.
+  The included image for PowerPC (for 32 and 64 bit PPC CPUs), Sparc32
+  and Sparc64 are built from OpenBIOS SVN revision 771.
 
 - The PXE roms come from Rom-o-Matic gPXE 0.9.9 with BANNER_TIMEOUT=0
 
diff --git a/pc-bios/openbios-ppc b/pc-bios/openbios-ppc
index 340fc69..34e188e 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 4f2f45f..4c2a9f7 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 632f938..fdb739b 100644
Binary files a/pc-bios/openbios-sparc64 and b/pc-bios/openbios-sparc64 differ
commit 57c3229ba1c5cecae277301b8b16577fbf2de98b
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Sun May 9 14:35:43 2010 +0300

    virtio-net: return with value in void function
    
    virtio-net has return with value in a void function.
    No idea why does it compile with gcc,
    but this isn't standard C.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index d602c56..cb664e6 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -227,7 +227,7 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features)
     if (!tap_get_vhost_net(n->nic->nc.peer)) {
         return;
     }
-    return vhost_net_ack_features(tap_get_vhost_net(n->nic->nc.peer), features);
+    vhost_net_ack_features(tap_get_vhost_net(n->nic->nc.peer), features);
 }
 
 static int virtio_net_handle_rx_mode(VirtIONet *n, uint8_t cmd,
commit fae054b070143a60ce40671470292efc2dc58a49
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Sun May 9 19:42:09 2010 +0300

    virtio: invoke set_features on load
    
    After migration, vhost was not getting features
    acked because set_features callback was never invoked.
    The fix is just to invoke that callback.
    
    Reported-by: David L Stevens <dlstevens at us.ibm.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    Tested-by: David L Stevens <dlstevens at us.ibm.com>

diff --git a/hw/virtio.c b/hw/virtio.c
index e7657ae..4475bb3 100644
--- a/hw/virtio.c
+++ b/hw/virtio.c
@@ -677,6 +677,8 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
                 features, supported_features);
         return -1;
     }
+    if (vdev->set_features)
+        vdev->set_features(vdev, features);
     vdev->guest_features = features;
     vdev->config_len = qemu_get_be32(f);
     qemu_get_buffer(f, vdev->config, vdev->config_len);
commit c3f8f61157625d0bb5bfc135047573de48fdc675
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Sun May 9 19:15:16 2010 +0300

    pci: irq_state vmstate breakage
    
    Code for saving irq_state got vm_state
    macros wrong, passing in the wrong parameter.
    As a result, we both saved a wrong value
    and restored it to a wrong offset.
    
    This leads to device and bus irq counts getting
    out of sync, which in turn leads to interrupts getting lost or
    never cleared, such as
    https://bugzilla.redhat.com/show_bug.cgi?id=588133
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    Acked-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/pci.c b/hw/pci.c
index 3ca5f09..1e143d9 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -322,7 +322,7 @@ static VMStateInfo vmstate_info_pci_config = {
 
 static int get_pci_irq_state(QEMUFile *f, void *pv, size_t size)
 {
-    PCIDevice *s = container_of(pv, PCIDevice, config);
+    PCIDevice *s = container_of(pv, PCIDevice, irq_state);
     uint32_t irq_state[PCI_NUM_PINS];
     int i;
     for (i = 0; i < PCI_NUM_PINS; ++i) {
@@ -344,7 +344,7 @@ static int get_pci_irq_state(QEMUFile *f, void *pv, size_t size)
 static void put_pci_irq_state(QEMUFile *f, void *pv, size_t size)
 {
     int i;
-    PCIDevice *s = container_of(pv, PCIDevice, config);
+    PCIDevice *s = container_of(pv, PCIDevice, irq_state);
 
     for (i = 0; i < PCI_NUM_PINS; ++i) {
         qemu_put_be32(f, pci_irq_state(s, i));
commit 925fe64ae7b487fdb7bd56fcab63e2f87653c226
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Tue May 11 06:44:21 2010 -0400

    pci: cleanly backout of pci_qdev_init()
    
    If the init function of a device fails, as might happen with device
    assignment, we never undo the work done by do_pci_register_device().
    This not only causes a bit of a memory leak, but also leaves a bogus
    pointer in the bus devices array that can cause a segfault or
    garbage data from 'info pci'.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci.c b/hw/pci.c
index f167436..3ca5f09 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -625,6 +625,13 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
     return pci_dev;
 }
 
+static void do_pci_unregister_device(PCIDevice *pci_dev)
+{
+    qemu_free_irqs(pci_dev->irq);
+    pci_dev->bus->devices[pci_dev->devfn] = NULL;
+    pci_config_free(pci_dev);
+}
+
 PCIDevice *pci_register_device(PCIBus *bus, const char *name,
                                int instance_size, int devfn,
                                PCIConfigReadFunc *config_read,
@@ -680,10 +687,7 @@ static int pci_unregister_device(DeviceState *dev)
         return ret;
 
     pci_unregister_io_regions(pci_dev);
-
-    qemu_free_irqs(pci_dev->irq);
-    pci_dev->bus->devices[pci_dev->devfn] = NULL;
-    pci_config_free(pci_dev);
+    do_pci_unregister_device(pci_dev);
     return 0;
 }
 
@@ -1652,8 +1656,10 @@ static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
     if (pci_dev == NULL)
         return -1;
     rc = info->init(pci_dev);
-    if (rc != 0)
+    if (rc != 0) {
+        do_pci_unregister_device(pci_dev);
         return rc;
+    }
 
     /* rom loading */
     if (pci_dev->romfile == NULL && info->romfile != NULL)
commit c1667e409764bb43a8196e40d01c409326d54a96
Author: Gleb Natapov <gleb at redhat.com>
Date:   Tue May 11 09:41:25 2010 +0300

    kvm: fix 80000001.EDX supported bit filtering
    
    On AMD some bits from 1.EDX are reported in 80000001.EDX. The mask used
    to copy bits from 1.EDX to 80000001.EDX is incorrect resulting in
    unsupported features passed into a guest.
    
    Signed-off-by: Gleb Natapov <gleb at redhat.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 676aa60..d6b12ed 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -111,7 +111,7 @@ uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function, int reg)
                      * so add missing bits according to the AMD spec:
                      */
                     cpuid_1_edx = kvm_arch_get_supported_cpuid(env, 1, R_EDX);
-                    ret |= cpuid_1_edx & 0xdfeff7ff;
+                    ret |= cpuid_1_edx & 0x183f7ff;
                     break;
                 }
                 break;
commit 4513d9232badcc5039d69dae946054ba2682c258
Author: Gleb Natapov <gleb at redhat.com>
Date:   Mon May 10 11:21:34 2010 +0300

    Do not stop VM if emulation failed in userspace.
    
    Continue vcpu execution in case emulation failure happened while vcpu
    was in userspace. In this case #UD will be injected into the guest
    allowing guest OS to kill offending process and continue.
    
    Signed-off-by: Gleb Natapov <gleb at redhat.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index d06980c..c238f54 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -764,6 +764,8 @@ static void kvm_handle_internal_error(CPUState *env, struct kvm_run *run)
     cpu_dump_state(env, stderr, fprintf, 0);
     if (run->internal.suberror == KVM_INTERNAL_ERROR_EMULATION) {
         fprintf(stderr, "emulation failure\n");
+        if (!kvm_arch_stop_on_emulation_error(env))
+		return;
     }
     /* FIXME: Should trigger a qmp message to let management know
      * something went wrong.
diff --git a/kvm.h b/kvm.h
index 5071a31..a28e7aa 100644
--- a/kvm.h
+++ b/kvm.h
@@ -140,6 +140,8 @@ void kvm_arch_remove_all_hw_breakpoints(void);
 
 void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg);
 
+bool kvm_arch_stop_on_emulation_error(CPUState *env);
+
 int kvm_check_extension(KVMState *s, unsigned int extension);
 
 uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function,
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index bd7a190..676aa60 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1289,3 +1289,10 @@ void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg)
     }
 }
 #endif /* KVM_CAP_SET_GUEST_DEBUG */
+
+bool kvm_arch_stop_on_emulation_error(CPUState *env)
+{
+      return !(env->cr[0] & CR0_PE_MASK) ||
+              ((env->segs[R_CS].selector  & 3) != 3);
+}
+
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 91c0963..2625cb8 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -326,3 +326,8 @@ uint32_t kvmppc_get_tbfreq(void)
     retval = atoi(ns);
     return retval;
 }
+
+bool kvm_arch_stop_on_emulation_error(CPUState *env)
+{
+    return true;
+}
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index a2c00ac..a2d7741 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -485,3 +485,8 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
 
     return ret;
 }
+
+bool kvm_arch_stop_on_emulation_error(CPUState *env)
+{
+    return true;
+}
commit 0af691d779965663abdd7bc708c2ad7bce2f6da0
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Tue May 4 09:45:27 2010 -0300

    kvm: enable smp > 1
    
    Process INIT/SIPI requests and enable -smp > 1.
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index e766202..d06980c 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -593,11 +593,6 @@ int kvm_init(int smp_cpus)
     int ret;
     int i;
 
-    if (smp_cpus > 1) {
-        fprintf(stderr, "No SMP KVM support, use '-smp 1'\n");
-        return -EINVAL;
-    }
-
     s = qemu_mallocz(sizeof(KVMState));
 
 #ifdef KVM_CAP_SET_GUEST_DEBUG
@@ -840,6 +835,11 @@ int kvm_cpu_exec(CPUState *env)
         }
 #endif
 
+        if (kvm_arch_process_irqchip_events(env)) {
+            ret = 0;
+            break;
+        }
+
         if (env->kvm_vcpu_dirty) {
             kvm_arch_put_registers(env, KVM_PUT_RUNTIME_STATE);
             env->kvm_vcpu_dirty = 0;
diff --git a/kvm.h b/kvm.h
index 70bfbf8..5071a31 100644
--- a/kvm.h
+++ b/kvm.h
@@ -90,6 +90,8 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run);
 
 int kvm_arch_pre_run(CPUState *env, struct kvm_run *run);
 
+int kvm_arch_process_irqchip_events(CPUState *env);
+
 int kvm_arch_get_registers(CPUState *env);
 
 /* state subset only touched by the VCPU itself during runtime */
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index c9ec72e..bd7a190 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1073,6 +1073,22 @@ int kvm_arch_post_run(CPUState *env, struct kvm_run *run)
     return 0;
 }
 
+int kvm_arch_process_irqchip_events(CPUState *env)
+{
+    if (env->interrupt_request & CPU_INTERRUPT_INIT) {
+        kvm_cpu_synchronize_state(env);
+        do_cpu_init(env);
+        env->exception_index = EXCP_HALTED;
+    }
+
+    if (env->interrupt_request & CPU_INTERRUPT_SIPI) {
+        kvm_cpu_synchronize_state(env);
+        do_cpu_sipi(env);
+    }
+
+    return env->halted;
+}
+
 static int kvm_handle_halt(CPUState *env)
 {
     if (!((env->interrupt_request & CPU_INTERRUPT_HARD) &&
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index aa3d432..91c0963 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -224,6 +224,11 @@ int kvm_arch_post_run(CPUState *env, struct kvm_run *run)
     return 0;
 }
 
+int kvm_arch_process_irqchip_events(CPUState *env)
+{
+    return 0;
+}
+
 static int kvmppc_handle_halt(CPUState *env)
 {
     if (!(env->interrupt_request & CPU_INTERRUPT_HARD) && (msr_ee)) {
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 72e77b0..a2c00ac 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -175,6 +175,11 @@ int kvm_arch_post_run(CPUState *env, struct kvm_run *run)
     return 0;
 }
 
+int kvm_arch_process_irqchip_events(CPUState *env)
+{
+    return 0;
+}
+
 static void kvm_s390_interrupt_internal(CPUState *env, int type, uint32_t parm,
                                         uint64_t parm64, int vm)
 {
commit dbaa07c404d05676df8a081e60b6e66344eafc51
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue May 4 09:45:26 2010 -0300

    kvm: validate context for kvm cpu get/put operations
    
    Validate that KVM vcpu state is only read/written from cpu thread itself
    or that cpu is stopped.
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index f73b47b..c9ec72e 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -949,6 +949,8 @@ int kvm_arch_put_registers(CPUState *env, int level)
 {
     int ret;
 
+    assert(cpu_is_stopped(env) || qemu_cpu_self(env));
+
     ret = kvm_getput_regs(env, 1);
     if (ret < 0)
         return ret;
@@ -991,6 +993,8 @@ int kvm_arch_get_registers(CPUState *env)
 {
     int ret;
 
+    assert(cpu_is_stopped(env) || qemu_cpu_self(env));
+
     ret = kvm_getput_regs(env, 0);
     if (ret < 0)
         return ret;
commit ced6c05143b49a910342862ed9c14204e1177ee4
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Tue May 4 09:45:25 2010 -0300

    move stop/stopped CPU_COMMON fields after area zeroed by reset
    
    cpu_reset zeroes CPUState upto breakpoints member. Contents of
    stop/stopped should not be zeroed on cpu_reset.
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/cpu-defs.h b/cpu-defs.h
index c764d67..8d4bf86 100644
--- a/cpu-defs.h
+++ b/cpu-defs.h
@@ -159,8 +159,6 @@ typedef struct CPUWatchpoint {
     target_ulong mem_io_vaddr; /* target virtual addr at which the      \
                                      memory was accessed */             \
     uint32_t halted; /* Nonzero if the CPU is in suspend state */       \
-    uint32_t stop;   /* Stop request */                                 \
-    uint32_t stopped; /* Artificially stopped */                        \
     uint32_t interrupt_request;                                         \
     volatile sig_atomic_t exit_request;                                 \
     CPU_COMMON_TLB                                                      \
@@ -203,6 +201,8 @@ typedef struct CPUWatchpoint {
     void *opaque;                                                       \
                                                                         \
     uint32_t created;                                                   \
+    uint32_t stop;   /* Stop request */                                 \
+    uint32_t stopped; /* Artificially stopped */                        \
     struct QemuThread *thread;                                          \
     struct QemuCond *halt_cond;                                         \
     struct qemu_work_item *queued_work_first, *queued_work_last;        \
commit 3ae9501c5bfe874017a385ca437583f5cf66a40a
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Tue May 4 09:45:24 2010 -0300

    add cpu_is_stopped helper
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/cpu-all.h b/cpu-all.h
index 9efb8a9..47a5722 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -821,6 +821,7 @@ void cpu_watchpoint_remove_all(CPUState *env, int mask);
 
 void cpu_single_step(CPUState *env, int enabled);
 void cpu_reset(CPUState *s);
+int cpu_is_stopped(CPUState *env);
 void run_on_cpu(CPUState *env, void (*func)(void *data), void *data);
 
 #define CPU_LOG_TB_OUT_ASM (1 << 0)
diff --git a/cpus.c b/cpus.c
index af87007..826886c 100644
--- a/cpus.c
+++ b/cpus.c
@@ -91,6 +91,11 @@ void cpu_synchronize_all_post_init(void)
     }
 }
 
+int cpu_is_stopped(CPUState *env)
+{
+    return !vm_running || env->stopped;
+}
+
 static void do_vm_stop(int reason)
 {
     if (vm_running) {
commit 2705d56a6a7e9c7833e04d33aedbc01d2280a280
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue May 4 09:45:23 2010 -0300

    kvm: synchronize state from cpu context
    
    It is not safe to retrieve the KVM internal state of a given cpu
    while its potentially modifying it.
    
    Queue the request to run on cpu context, similarly to qemu-kvm.
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index fbd084c..e766202 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -796,14 +796,22 @@ void kvm_flush_coalesced_mmio_buffer(void)
 #endif
 }
 
-void kvm_cpu_synchronize_state(CPUState *env)
+static void do_kvm_cpu_synchronize_state(void *_env)
 {
+    CPUState *env = _env;
+
     if (!env->kvm_vcpu_dirty) {
         kvm_arch_get_registers(env);
         env->kvm_vcpu_dirty = 1;
     }
 }
 
+void kvm_cpu_synchronize_state(CPUState *env)
+{
+    if (!env->kvm_vcpu_dirty)
+        run_on_cpu(env, do_kvm_cpu_synchronize_state, env);
+}
+
 void kvm_cpu_synchronize_post_reset(CPUState *env)
 {
     kvm_arch_put_registers(env, KVM_PUT_RESET_STATE);
commit e82bcec25f19846bfb899d55c9fb5915516b378a
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Tue May 4 09:45:22 2010 -0300

    port qemu-kvm's on_vcpu code
    
    run_on_cpu allows to execute work on a given CPUState context.
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/cpu-all.h b/cpu-all.h
index 52a1817..9efb8a9 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -821,6 +821,7 @@ void cpu_watchpoint_remove_all(CPUState *env, int mask);
 
 void cpu_single_step(CPUState *env, int enabled);
 void cpu_reset(CPUState *s);
+void run_on_cpu(CPUState *env, void (*func)(void *data), void *data);
 
 #define CPU_LOG_TB_OUT_ASM (1 << 0)
 #define CPU_LOG_TB_IN_ASM  (1 << 1)
diff --git a/cpu-defs.h b/cpu-defs.h
index 0140596..c764d67 100644
--- a/cpu-defs.h
+++ b/cpu-defs.h
@@ -132,6 +132,7 @@ typedef struct icount_decr_u16 {
 
 struct kvm_run;
 struct KVMState;
+struct qemu_work_item;
 
 typedef struct CPUBreakpoint {
     target_ulong pc;
@@ -204,6 +205,7 @@ typedef struct CPUWatchpoint {
     uint32_t created;                                                   \
     struct QemuThread *thread;                                          \
     struct QemuCond *halt_cond;                                         \
+    struct qemu_work_item *queued_work_first, *queued_work_last;        \
     const char *cpu_model_str;                                          \
     struct KVMState *kvm_state;                                         \
     struct kvm_run *kvm_run;                                            \
diff --git a/cpus.c b/cpus.c
index 5afdb4a..af87007 100644
--- a/cpus.c
+++ b/cpus.c
@@ -115,6 +115,8 @@ static int cpu_has_work(CPUState *env)
 {
     if (env->stop)
         return 1;
+    if (env->queued_work_first)
+        return 1;
     if (env->stopped || !vm_running)
         return 0;
     if (!env->halted)
@@ -252,6 +254,11 @@ int qemu_cpu_self(void *env)
     return 1;
 }
 
+void run_on_cpu(CPUState *env, void (*func)(void *data), void *data)
+{
+    func(data);
+}
+
 void resume_all_vcpus(void)
 {
 }
@@ -304,6 +311,7 @@ static QemuCond qemu_cpu_cond;
 /* system init */
 static QemuCond qemu_system_cond;
 static QemuCond qemu_pause_cond;
+static QemuCond qemu_work_cond;
 
 static void tcg_block_io_signals(void);
 static void kvm_block_io_signals(CPUState *env);
@@ -334,6 +342,50 @@ void qemu_main_loop_start(void)
     qemu_cond_broadcast(&qemu_system_cond);
 }
 
+void run_on_cpu(CPUState *env, void (*func)(void *data), void *data)
+{
+    struct qemu_work_item wi;
+
+    if (qemu_cpu_self(env)) {
+        func(data);
+        return;
+    }
+
+    wi.func = func;
+    wi.data = data;
+    if (!env->queued_work_first)
+        env->queued_work_first = &wi;
+    else
+        env->queued_work_last->next = &wi;
+    env->queued_work_last = &wi;
+    wi.next = NULL;
+    wi.done = false;
+
+    qemu_cpu_kick(env);
+    while (!wi.done) {
+        CPUState *self_env = cpu_single_env;
+
+        qemu_cond_wait(&qemu_work_cond, &qemu_global_mutex);
+        cpu_single_env = self_env;
+    }
+}
+
+static void flush_queued_work(CPUState *env)
+{
+    struct qemu_work_item *wi;
+
+    if (!env->queued_work_first)
+        return;
+
+    while ((wi = env->queued_work_first)) {
+        env->queued_work_first = wi->next;
+        wi->func(wi->data);
+        wi->done = true;
+    }
+    env->queued_work_last = NULL;
+    qemu_cond_broadcast(&qemu_work_cond);
+}
+
 static void qemu_wait_io_event_common(CPUState *env)
 {
     if (env->stop) {
@@ -341,6 +393,7 @@ static void qemu_wait_io_event_common(CPUState *env)
         env->stopped = 1;
         qemu_cond_signal(&qemu_pause_cond);
     }
+    flush_queued_work(env);
 }
 
 static void qemu_wait_io_event(CPUState *env)
diff --git a/qemu-common.h b/qemu-common.h
index 4ba0cda..a4888e5 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -249,6 +249,14 @@ void qemu_notify_event(void);
 void qemu_cpu_kick(void *env);
 int qemu_cpu_self(void *env);
 
+/* work queue */
+struct qemu_work_item {
+    struct qemu_work_item *next;
+    void (*func)(void *data);
+    void *data;
+    int done;
+};
+
 #ifdef CONFIG_USER_ONLY
 #define qemu_init_vcpu(env) do { } while (0)
 #else
commit 1fbb22e5f8be9f7793251e5258b23936643f677c
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Tue May 4 09:45:21 2010 -0300

    standardize on qemu_cpu_kick for signalling cpu thread(s)
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/cpus.c b/cpus.c
index 53226b3..5afdb4a 100644
--- a/cpus.c
+++ b/cpus.c
@@ -454,8 +454,7 @@ void qemu_cpu_kick(void *_env)
 {
     CPUState *env = _env;
     qemu_cond_broadcast(env->halt_cond);
-    if (kvm_enabled())
-        qemu_thread_signal(env->thread, SIG_IPI);
+    qemu_thread_signal(env->thread, SIG_IPI);
 }
 
 int qemu_cpu_self(void *_env)
@@ -583,7 +582,6 @@ void pause_all_vcpus(void)
 
     while (penv) {
         penv->stop = 1;
-        qemu_thread_signal(penv->thread, SIG_IPI);
         qemu_cpu_kick(penv);
         penv = (CPUState *)penv->next_cpu;
     }
@@ -592,7 +590,7 @@ void pause_all_vcpus(void)
         qemu_cond_timedwait(&qemu_pause_cond, &qemu_global_mutex, 100);
         penv = first_cpu;
         while (penv) {
-            qemu_thread_signal(penv->thread, SIG_IPI);
+            qemu_cpu_kick(penv);
             penv = (CPUState *)penv->next_cpu;
         }
     }
@@ -605,7 +603,6 @@ void resume_all_vcpus(void)
     while (penv) {
         penv->stop = 0;
         penv->stopped = 0;
-        qemu_thread_signal(penv->thread, SIG_IPI);
         qemu_cpu_kick(penv);
         penv = (CPUState *)penv->next_cpu;
     }
commit 1a28cac3161f8a85ee0256776068eaed2da025e5
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Tue May 4 09:45:20 2010 -0300

    make SIG_IPI to tcg vcpu thread reliable
    
    Store tcg loop exit request on a global variable, and transfer it to
    per-CPUState exit_request after assignment of cpu_single_env.
    
    This makes exit request signal from robust. Drop the timedlock hack.
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/cpu-exec.c b/cpu-exec.c
index dc81e79..c776605 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -213,6 +213,8 @@ static void cpu_handle_debug_exception(CPUState *env)
 
 /* main execution loop */
 
+volatile sig_atomic_t exit_request;
+
 int cpu_exec(CPUState *env1)
 {
     volatile host_reg_t saved_env_reg;
@@ -234,6 +236,11 @@ int cpu_exec(CPUState *env1)
     asm("");
     env = env1;
 
+    if (exit_request) {
+        env->exit_request = 1;
+        exit_request = 0;
+    }
+
 #if defined(TARGET_I386)
     if (!kvm_enabled()) {
         /* put eflags in CPU temporary format */
diff --git a/cpus.c b/cpus.c
index 29462e5..53226b3 100644
--- a/cpus.c
+++ b/cpus.c
@@ -472,6 +472,7 @@ static void cpu_signal(int sig)
 {
     if (cpu_single_env)
         cpu_exit(cpu_single_env);
+    exit_request = 1;
 }
 
 static void tcg_block_io_signals(void)
@@ -542,26 +543,20 @@ static void unblock_io_signals(void)
     pthread_sigmask(SIG_BLOCK, &set, NULL);
 }
 
-static void qemu_signal_lock(unsigned int msecs)
-{
-    qemu_mutex_lock(&qemu_fair_mutex);
-
-    while (qemu_mutex_trylock(&qemu_global_mutex)) {
-        qemu_thread_signal(tcg_cpu_thread, SIG_IPI);
-        if (!qemu_mutex_timedlock(&qemu_global_mutex, msecs))
-            break;
-    }
-    qemu_mutex_unlock(&qemu_fair_mutex);
-}
-
 void qemu_mutex_lock_iothread(void)
 {
     if (kvm_enabled()) {
         qemu_mutex_lock(&qemu_fair_mutex);
         qemu_mutex_lock(&qemu_global_mutex);
         qemu_mutex_unlock(&qemu_fair_mutex);
-    } else
-        qemu_signal_lock(100);
+    } else {
+        qemu_mutex_lock(&qemu_fair_mutex);
+        if (qemu_mutex_trylock(&qemu_global_mutex)) {
+            qemu_thread_signal(tcg_cpu_thread, SIG_IPI);
+            qemu_mutex_lock(&qemu_global_mutex);
+        }
+        qemu_mutex_unlock(&qemu_fair_mutex);
+    }
 }
 
 void qemu_mutex_unlock_iothread(void)
diff --git a/exec-all.h b/exec-all.h
index 1016de2..4565dd0 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -351,4 +351,7 @@ CPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler);
 /* vl.c */
 extern int singlestep;
 
+/* cpu-exec.c */
+extern volatile sig_atomic_t exit_request;
+
 #endif
commit 273faf1b6dbdedd0fe9fc519ec73380eced667c2
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Tue May 4 09:45:19 2010 -0300

    kvm: set cpu_single_env around KVM_RUN ioctl
    
    Zero cpu_single_env before leaving global lock protection, and
    restore on return.
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index 6962b2b..fbd084c 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -838,9 +838,11 @@ int kvm_cpu_exec(CPUState *env)
         }
 
         kvm_arch_pre_run(env, run);
+        cpu_single_env = NULL;
         qemu_mutex_unlock_iothread();
         ret = kvm_vcpu_ioctl(env, KVM_RUN, 0);
         qemu_mutex_lock_iothread();
+        cpu_single_env = env;
         kvm_arch_post_run(env, run);
 
         if (ret == -EINTR || ret == -EAGAIN) {
commit 618a568da4eda5c2e41fc4e58059546806afff6b
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Mon May 3 18:12:23 2010 -0300

    Fix -mem-path with hugetlbfs
    
    Fallback to qemu_vmalloc in case file_ram_alloc fails.
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/exec.c b/exec.c
index 3416aed..56b5561 100644
--- a/exec.c
+++ b/exec.c
@@ -2775,8 +2775,12 @@ ram_addr_t qemu_ram_alloc(ram_addr_t size)
     if (mem_path) {
 #if defined (__linux__) && !defined(TARGET_S390X)
         new_block->host = file_ram_alloc(size, mem_path);
-        if (!new_block->host)
-            exit(1);
+        if (!new_block->host) {
+            new_block->host = qemu_vmalloc(size);
+#ifdef MADV_MERGEABLE
+            madvise(new_block->host, size, MADV_MERGEABLE);
+#endif
+        }
 #else
         fprintf(stderr, "-mem-path option unsupported\n");
         exit(1);
commit 54d7cf136f040713095cbc064f62d753bff6f9d2
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue May 4 13:20:33 2010 +0200

    doc: Clean up monitor command function index
    
    Remove bogus entries "count", "format" and "size".  Accidentally added
    in commit 70fcbbe7.
    
    Add missing entry "qmp_capabilities".  Was forgotten in commit
    4a7e1190.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index 220ed9c..a8f194c 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -374,16 +374,13 @@ data. Its syntax is: @option{/@{count@}@{format@}@{size@}}
 
 @table @var
 @item count
- at findex count
 is the number of items to be dumped.
 
 @item format
- at findex format
 can be x (hex), d (signed decimal), u (unsigned decimal), o (octal),
 c (char) or i (asm instruction).
 
 @item size
- at findex size
 can be b (8 bits), h (16 bits), w (32 bits) or g (64 bits). On x86,
 @code{h} or @code{w} can be specified with the @code{i} format to
 respectively select 16 or 32 bit code instruction size.
@@ -1181,6 +1178,7 @@ ETEXI
 
 STEXI
 @item qmp_capabilities
+ at findex qmp_capabilities
 Enable the specified QMP capabilities
 ETEXI
 
commit c427ea9cd110818bb4f6906b6d36d9a4d93f6fd7
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue May 4 13:20:32 2010 +0200

    doc: Heading for monitor command cpu got lost, restore it
    
    Broken in commit 2313086a.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index bf47ae0..220ed9c 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -611,6 +611,8 @@ ETEXI
     },
 
 STEXI
+ at item cpu @var{index}
+ at findex cpu
 Set the default CPU.
 ETEXI
 
commit 0e4aec988c813227dccff705c2cd10b0f954bf23
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue May 4 13:20:31 2010 +0200

    doc: Fix acl monitor command documentation
    
    Commit 15dfcd45 added acl_add and acl_reset, but fat-fingered their
    documentation to read acl_allow and acl_remove.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index 21aeb6b..bf47ae0 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -1063,8 +1063,8 @@ ETEXI
     },
 
 STEXI
- at item acl_allow @var{aclname} @var{match} @code{allow|deny} [@var{index}]
- at findex acl_allow
+ at item acl_add @var{aclname} @var{match} @code{allow|deny} [@var{index}]
+ at findex acl_add
 Add a match rule to the access control list, allowing or denying access.
 The match will normally be an exact username or x509 distinguished name,
 but can optionally include wildcard globs. eg @code{*@@EXAMPLE.COM} to
@@ -1096,7 +1096,8 @@ ETEXI
     },
 
 STEXI
- at item acl_remove @var{aclname}
+ at item acl_reset @var{aclname}
+ at findex acl_reset
 Remove all matches from the access control list, and set the default
 policy back to @code{deny}.
 ETEXI
commit 21413d683b1fa264d82b6a3408ec8f2b5ce29d27
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue May 4 13:20:30 2010 +0200

    doc: Fix host forwarding monitor command documentation
    
    Commit f3546deb replaced host_net_redir by hostfwd_add,
    hostfwd_remove, but neglected to update documentation.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index 5ea5748..21aeb6b 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -953,7 +953,14 @@ ETEXI
         .help       = "redirect TCP or UDP connections from host to guest (requires -net user)",
         .mhandler.cmd = net_slirp_hostfwd_add,
     },
+#endif
+STEXI
+ at item hostfwd_add
+ at findex hostfwd_add
+Redirect TCP or UDP connections from host to guest (requires -net user).
+ETEXI
 
+#ifdef CONFIG_SLIRP
     {
         .name       = "hostfwd_remove",
         .args_type  = "arg1:s,arg2:s?,arg3:s?",
@@ -964,9 +971,9 @@ ETEXI
 
 #endif
 STEXI
- at item host_net_redir
- at findex host_net_redir
-Redirect TCP or UDP connections from host to guest (requires -net user).
+ at item hostfwd_remove
+ at findex hostfwd_remove
+Remove host-to-guest TCP or UDP redirection.
 ETEXI
 
     {
commit 64d564094cac5f72eeaeb950c442b773a00d3586
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue May 4 14:21:03 2010 +0200

    lsi: Handle removal of selected devices
    
    We must not store references to selected devices as they may be
    hot-removed. Instead, look up the device based on its tag right before
    using it. If the device disappeared, throw an interrupt and disconnect.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index f088d06..9d3c44d 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -175,7 +175,6 @@ do { fprintf(stderr, "lsi_scsi: error: " fmt , ## __VA_ARGS__);} while (0)
 
 typedef struct lsi_request {
     uint32_t tag;
-    SCSIDevice *dev;
     uint32_t dma_len;
     uint8_t *dma_buf;
     uint32_t pending;
@@ -202,7 +201,6 @@ typedef struct {
      * 3 if a DMA operation is in progress.  */
     int waiting;
     SCSIBus bus;
-    SCSIDevice *select_dev;
     int current_lun;
     /* The tag is a combination of the device ID and the SCSI tag.  */
     uint32_t select_tag;
@@ -518,11 +516,25 @@ static void lsi_resume_script(LSIState *s)
     }
 }
 
+static void lsi_disconnect(LSIState *s)
+{
+    s->scntl1 &= ~LSI_SCNTL1_CON;
+    s->sstat1 &= ~PHASE_MASK;
+}
+
+static void lsi_bad_selection(LSIState *s, uint32_t id)
+{
+    DPRINTF("Selected absent target %d\n", id);
+    lsi_script_scsi_interrupt(s, 0, LSI_SIST1_STO);
+    lsi_disconnect(s);
+}
+
 /* Initiate a SCSI layer data transfer.  */
 static void lsi_do_dma(LSIState *s, int out)
 {
-    uint32_t count;
+    uint32_t count, id;
     target_phys_addr_t addr;
+    SCSIDevice *dev;
 
     assert(s->current);
     if (!s->current->dma_len) {
@@ -531,6 +543,13 @@ static void lsi_do_dma(LSIState *s, int out)
         return;
     }
 
+    id = s->current->tag >> 8;
+    dev = s->bus.devs[id];
+    if (!dev) {
+        lsi_bad_selection(s, id);
+        return;
+    }
+
     count = s->dbc;
     if (count > s->current->dma_len)
         count = s->current->dma_len;
@@ -550,8 +569,7 @@ static void lsi_do_dma(LSIState *s, int out)
     s->dbc -= count;
 
     if (s->current->dma_buf == NULL) {
-        s->current->dma_buf = s->current->dev->info->get_buf(s->current->dev,
-                                                             s->current->tag);
+        s->current->dma_buf = dev->info->get_buf(dev, s->current->tag);
     }
 
     /* ??? Set SFBR to first data byte.  */
@@ -565,10 +583,10 @@ static void lsi_do_dma(LSIState *s, int out)
         s->current->dma_buf = NULL;
         if (out) {
             /* Write the data.  */
-            s->current->dev->info->write_data(s->current->dev, s->current->tag);
+            dev->info->write_data(dev, s->current->tag);
         } else {
             /* Request any remaining data.  */
-            s->current->dev->info->read_data(s->current->dev, s->current->tag);
+            dev->info->read_data(dev, s->current->tag);
         }
     } else {
         s->current->dma_buf += count;
@@ -715,7 +733,9 @@ static void lsi_command_complete(SCSIBus *bus, int reason, uint32_t tag,
 
 static void lsi_do_command(LSIState *s)
 {
+    SCSIDevice *dev;
     uint8_t buf[16];
+    uint32_t id;
     int n;
 
     DPRINTF("Send command len=%d\n", s->dbc);
@@ -725,19 +745,24 @@ static void lsi_do_command(LSIState *s)
     s->sfbr = buf[0];
     s->command_complete = 0;
 
+    id = s->select_tag >> 8;
+    dev = s->bus.devs[id];
+    if (!dev) {
+        lsi_bad_selection(s, id);
+        return;
+    }
+
     assert(s->current == NULL);
     s->current = qemu_mallocz(sizeof(lsi_request));
     s->current->tag = s->select_tag;
-    s->current->dev = s->select_dev;
 
-    n = s->current->dev->info->send_command(s->current->dev, s->current->tag, buf,
-                                            s->current_lun);
+    n = dev->info->send_command(dev, s->current->tag, buf, s->current_lun);
     if (n > 0) {
         lsi_set_phase(s, PHASE_DI);
-        s->current->dev->info->read_data(s->current->dev, s->current->tag);
+        dev->info->read_data(dev, s->current->tag);
     } else if (n < 0) {
         lsi_set_phase(s, PHASE_DO);
-        s->current->dev->info->write_data(s->current->dev, s->current->tag);
+        dev->info->write_data(dev, s->current->tag);
     }
 
     if (!s->command_complete) {
@@ -771,12 +796,6 @@ static void lsi_do_status(LSIState *s)
     lsi_add_msg_byte(s, 0); /* COMMAND COMPLETE */
 }
 
-static void lsi_disconnect(LSIState *s)
-{
-    s->scntl1 &= ~LSI_SCNTL1_CON;
-    s->sstat1 &= ~PHASE_MASK;
-}
-
 static void lsi_do_msgin(LSIState *s)
 {
     int len;
@@ -1092,9 +1111,7 @@ again:
                 s->sstat0 |= LSI_SSTAT0_WOA;
                 s->scntl1 &= ~LSI_SCNTL1_IARB;
                 if (id >= LSI_MAX_DEVS || !s->bus.devs[id]) {
-                    DPRINTF("Selected absent target %d\n", id);
-                    lsi_script_scsi_interrupt(s, 0, LSI_SIST1_STO);
-                    lsi_disconnect(s);
+                    lsi_bad_selection(s, id);
                     break;
                 }
                 DPRINTF("Selected target %d%s\n",
@@ -1102,7 +1119,6 @@ again:
                 /* ??? Linux drivers compain when this is set.  Maybe
                    it only applies in low-level mode (unimplemented).
                 lsi_script_scsi_interrupt(s, LSI_SIST0_CMP, 0); */
-                s->select_dev = s->bus.devs[id];
                 s->select_tag = id << 8;
                 s->scntl1 |= LSI_SCNTL1_CON;
                 if (insn & (1 << 3)) {
commit 12aa6dd61cb29bc2f1dc38d26bc61bdd7b6e9163
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue May 4 14:21:02 2010 +0200

    lsi: Adjust some register reset values
    
    According to the LSI spec, the reset value of dcmd, dstat, and ctest2
    were wrong, and sdid as well as ssid require zero initialization. There
    are surely more discrepancies, this is just another increment.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 61de23e..f088d06 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -298,8 +298,8 @@ static void lsi_soft_reset(LSIState *s)
     memset(s->scratch, 0, sizeof(s->scratch));
     s->istat0 = 0;
     s->istat1 = 0;
-    s->dcmd = 0;
-    s->dstat = 0;
+    s->dcmd = 0x40;
+    s->dstat = LSI_DSTAT_DFE;
     s->dien = 0;
     s->sist0 = 0;
     s->sist1 = 0;
@@ -308,7 +308,7 @@ static void lsi_soft_reset(LSIState *s)
     s->mbox0 = 0;
     s->mbox1 = 0;
     s->dfifo = 0;
-    s->ctest2 = 0;
+    s->ctest2 = LSI_CTEST2_DACK;
     s->ctest3 = 0;
     s->ctest4 = 0;
     s->ctest5 = 0;
@@ -327,6 +327,8 @@ static void lsi_soft_reset(LSIState *s)
     s->scid = 7;
     s->sxfer = 0;
     s->socl = 0;
+    s->sdid = 0;
+    s->ssid = 0;
     s->stest1 = 0;
     s->stest2 = 0;
     s->stest3 = 0;
commit d43ba0af97646e36b6309292d30ee13b0948b1f8
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue May 4 14:21:01 2010 +0200

    lsi: Purge message queue on reset
    
    Declare the input message queue empty and initialize the related state
    machine properly on controller reset. This fixes unrecoverable errors
    when the controller was reset during ongoing requests.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 85eea15..61de23e 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -288,6 +288,8 @@ static void lsi_soft_reset(LSIState *s)
     DPRINTF("Reset\n");
     s->carry = 0;
 
+    s->msg_action = 0;
+    s->msg_len = 0;
     s->waiting = 0;
     s->dsa = 0;
     s->dnad = 0;
commit 3e94cb020444ed201cfe6210f0de9953143dc74b
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue May 4 14:21:00 2010 +0200

    scsi-disk: Clear aiocb on read completion
    
    Once the I/O completion callback returned, aiocb will be released by the
    controller. So we have to clear the reference not only in
    scsi_write_complete, but also in scsi_read_complete. Otherwise we risk
    inconsistencies when a reset hits us before the related request is
    released.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index b8d805f..4d20919 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -125,6 +125,8 @@ static void scsi_read_complete(void * opaque, int ret)
 {
     SCSIDiskReq *r = (SCSIDiskReq *)opaque;
 
+    r->req.aiocb = NULL;
+
     if (ret) {
         DPRINTF("IO error\n");
         r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, 0);
commit e9447f35718439c1affdee3ef69b2fee50c8106c
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue May 4 14:20:59 2010 +0200

    SCSI: Add disk reset handler
    
    Ensure that pending requests of an SCSI disk are purged on system reset
    and also restore max_lba. The latter is no only present in the reset
    handler as that one is called after init as well.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 77cb1da..b8d805f 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -1010,22 +1010,45 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
     }
 }
 
-static void scsi_destroy(SCSIDevice *dev)
+static void scsi_disk_purge_requests(SCSIDiskState *s)
 {
-    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
     SCSIDiskReq *r;
 
     while (!QTAILQ_EMPTY(&s->qdev.requests)) {
         r = DO_UPCAST(SCSIDiskReq, req, QTAILQ_FIRST(&s->qdev.requests));
+        if (r->req.aiocb) {
+            bdrv_aio_cancel(r->req.aiocb);
+        }
         scsi_remove_request(r);
     }
+}
+
+static void scsi_disk_reset(DeviceState *dev)
+{
+    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev.qdev, dev);
+    uint64_t nb_sectors;
+
+    scsi_disk_purge_requests(s);
+
+    bdrv_get_geometry(s->bs, &nb_sectors);
+    nb_sectors /= s->cluster_size;
+    if (nb_sectors) {
+        nb_sectors--;
+    }
+    s->max_lba = nb_sectors;
+}
+
+static void scsi_destroy(SCSIDevice *dev)
+{
+    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
+
+    scsi_disk_purge_requests(s);
     drive_uninit(s->qdev.conf.dinfo);
 }
 
 static int scsi_disk_initfn(SCSIDevice *dev)
 {
     SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
-    uint64_t nb_sectors;
 
     if (!s->qdev.conf.dinfo || !s->qdev.conf.dinfo->bdrv) {
         error_report("scsi-disk: drive property not set");
@@ -1046,11 +1069,6 @@ static int scsi_disk_initfn(SCSIDevice *dev)
     s->cluster_size = s->qdev.blocksize / 512;
 
     s->qdev.type = TYPE_DISK;
-    bdrv_get_geometry(s->bs, &nb_sectors);
-    nb_sectors /= s->cluster_size;
-    if (nb_sectors)
-        nb_sectors--;
-    s->max_lba = nb_sectors;
     qemu_add_vm_change_state_handler(scsi_dma_restart_cb, s);
     return 0;
 }
@@ -1059,6 +1077,7 @@ static SCSIDeviceInfo scsi_disk_info = {
     .qdev.name    = "scsi-disk",
     .qdev.desc    = "virtual scsi disk or cdrom",
     .qdev.size    = sizeof(SCSIDiskState),
+    .qdev.reset   = scsi_disk_reset,
     .init         = scsi_disk_initfn,
     .destroy      = scsi_destroy,
     .send_command = scsi_send_command,
commit 4c64d5b52ed5287bb31489bba39cf41628230bce
Author: Amit Shah <amit.shah at redhat.com>
Date:   Tue May 4 16:39:07 2010 +0530

    iov: Move from hw/ to topdir
    
    The iov functions can be useful to other code as well.
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    CC: Christoph Hellwig <hch at lst.de>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/iov.c b/hw/iov.c
deleted file mode 100644
index 588cd04..0000000
--- a/hw/iov.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Helpers for getting linearized buffers from iov / filling buffers into iovs
- *
- * Copyright IBM, Corp. 2007, 2008
- * Copyright (C) 2010 Red Hat, Inc.
- *
- * Author(s):
- *  Anthony Liguori <aliguori at us.ibm.com>
- *  Amit Shah <amit.shah at redhat.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2.  See
- * the COPYING file in the top-level directory.
- */
-
-#include "iov.h"
-
-size_t iov_from_buf(struct iovec *iov, unsigned int iovcnt,
-                    const void *buf, size_t size)
-{
-    size_t offset;
-    unsigned int i;
-
-    offset = 0;
-    for (i = 0; offset < size && i < iovcnt; i++) {
-        size_t len;
-
-        len = MIN(iov[i].iov_len, size - offset);
-
-        memcpy(iov[i].iov_base, buf + offset, len);
-        offset += len;
-    }
-    return offset;
-}
-
-size_t iov_to_buf(const struct iovec *iov, const unsigned int iovcnt,
-                  void *buf, size_t offset, size_t size)
-{
-    uint8_t *ptr;
-    size_t iov_off, buf_off;
-    unsigned int i;
-
-    ptr = buf;
-    iov_off = 0;
-    buf_off = 0;
-    for (i = 0; i < iovcnt && size; i++) {
-        if (offset < (iov_off + iov[i].iov_len)) {
-            size_t len = MIN((iov_off + iov[i].iov_len) - offset , size);
-
-            memcpy(ptr + buf_off, iov[i].iov_base + (offset - iov_off), len);
-
-            buf_off += len;
-            offset += len;
-            size -= len;
-        }
-        iov_off += iov[i].iov_len;
-    }
-    return buf_off;
-}
-
-size_t iov_size(const struct iovec *iov, const unsigned int iovcnt)
-{
-    size_t len;
-    unsigned int i;
-
-    len = 0;
-    for (i = 0; i < iovcnt; i++) {
-        len += iov[i].iov_len;
-    }
-    return len;
-}
diff --git a/hw/iov.h b/hw/iov.h
deleted file mode 100644
index 60a8547..0000000
--- a/hw/iov.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Helpers for getting linearized buffers from iov / filling buffers into iovs
- *
- * Copyright (C) 2010 Red Hat, Inc.
- *
- * Author(s):
- *  Amit Shah <amit.shah at redhat.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2.  See
- * the COPYING file in the top-level directory.
- */
-
-#include "qemu-common.h"
-
-size_t iov_from_buf(struct iovec *iov, unsigned int iovcnt,
-                    const void *buf, size_t size);
-size_t iov_to_buf(const struct iovec *iov, const unsigned int iovcnt,
-                  void *buf, size_t offset, size_t size);
-size_t iov_size(const struct iovec *iov, const unsigned int iovcnt);
diff --git a/iov.c b/iov.c
new file mode 100644
index 0000000..588cd04
--- /dev/null
+++ b/iov.c
@@ -0,0 +1,70 @@
+/*
+ * Helpers for getting linearized buffers from iov / filling buffers into iovs
+ *
+ * Copyright IBM, Corp. 2007, 2008
+ * Copyright (C) 2010 Red Hat, Inc.
+ *
+ * Author(s):
+ *  Anthony Liguori <aliguori at us.ibm.com>
+ *  Amit Shah <amit.shah at redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#include "iov.h"
+
+size_t iov_from_buf(struct iovec *iov, unsigned int iovcnt,
+                    const void *buf, size_t size)
+{
+    size_t offset;
+    unsigned int i;
+
+    offset = 0;
+    for (i = 0; offset < size && i < iovcnt; i++) {
+        size_t len;
+
+        len = MIN(iov[i].iov_len, size - offset);
+
+        memcpy(iov[i].iov_base, buf + offset, len);
+        offset += len;
+    }
+    return offset;
+}
+
+size_t iov_to_buf(const struct iovec *iov, const unsigned int iovcnt,
+                  void *buf, size_t offset, size_t size)
+{
+    uint8_t *ptr;
+    size_t iov_off, buf_off;
+    unsigned int i;
+
+    ptr = buf;
+    iov_off = 0;
+    buf_off = 0;
+    for (i = 0; i < iovcnt && size; i++) {
+        if (offset < (iov_off + iov[i].iov_len)) {
+            size_t len = MIN((iov_off + iov[i].iov_len) - offset , size);
+
+            memcpy(ptr + buf_off, iov[i].iov_base + (offset - iov_off), len);
+
+            buf_off += len;
+            offset += len;
+            size -= len;
+        }
+        iov_off += iov[i].iov_len;
+    }
+    return buf_off;
+}
+
+size_t iov_size(const struct iovec *iov, const unsigned int iovcnt)
+{
+    size_t len;
+    unsigned int i;
+
+    len = 0;
+    for (i = 0; i < iovcnt; i++) {
+        len += iov[i].iov_len;
+    }
+    return len;
+}
diff --git a/iov.h b/iov.h
new file mode 100644
index 0000000..60a8547
--- /dev/null
+++ b/iov.h
@@ -0,0 +1,19 @@
+/*
+ * Helpers for getting linearized buffers from iov / filling buffers into iovs
+ *
+ * Copyright (C) 2010 Red Hat, Inc.
+ *
+ * Author(s):
+ *  Amit Shah <amit.shah at redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#include "qemu-common.h"
+
+size_t iov_from_buf(struct iovec *iov, unsigned int iovcnt,
+                    const void *buf, size_t size);
+size_t iov_to_buf(const struct iovec *iov, const unsigned int iovcnt,
+                  void *buf, size_t offset, size_t size);
+size_t iov_size(const struct iovec *iov, const unsigned int iovcnt);
commit 14eb8b6829ad9dee7035de729e083844a425f274
Author: Corentin Chary <corentincj at iksaif.net>
Date:   Tue May 4 14:01:58 2010 +0200

    vnc: set the right prefered encoding
    
    message is a hint by the client as to its preference (the first
    encoding specified being most preferred)"
    
    Signed-off-by: Corentin Chary <corentincj at iksaif.net>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vnc.c b/vnc.c
index b1a3fdb..1f7ad73 100644
--- a/vnc.c
+++ b/vnc.c
@@ -1594,7 +1594,7 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
 
     vnc_zlib_init(vs);
     vs->features = 0;
-    vs->vnc_encoding = 0;
+    vs->vnc_encoding = -1;
     vs->tight_compression = 9;
     vs->tight_quality = 9;
     vs->absolute = -1;
@@ -1603,18 +1603,24 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
         enc = encodings[i];
         switch (enc) {
         case VNC_ENCODING_RAW:
-            vs->vnc_encoding = enc;
+            if (vs->vnc_encoding != -1) {
+                vs->vnc_encoding = enc;
+            }
             break;
         case VNC_ENCODING_COPYRECT:
             vs->features |= VNC_FEATURE_COPYRECT_MASK;
             break;
         case VNC_ENCODING_HEXTILE:
             vs->features |= VNC_FEATURE_HEXTILE_MASK;
-            vs->vnc_encoding = enc;
+            if (vs->vnc_encoding != -1) {
+                vs->vnc_encoding = enc;
+            }
             break;
         case VNC_ENCODING_ZLIB:
             vs->features |= VNC_FEATURE_ZLIB_MASK;
-            vs->vnc_encoding = enc;
+            if (vs->vnc_encoding != -1) {
+                vs->vnc_encoding = enc;
+            }
             break;
         case VNC_ENCODING_DESKTOPRESIZE:
             vs->features |= VNC_FEATURE_RESIZE_MASK;
commit 5a834bb47c373e887de5210b7ceae96e1ef413f7
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun May 9 20:19:04 2010 +0000

    sparc: Fix lazy flag calculation on interrupts, refactor
    
    Recalculate Sparc64 CPU flags on interrupts, otherwise some earlier
    flags could be stored to pstate.
    
    Refactor PSR/CCR/CWP handling: concentrate the actual
    functions to op_helper.c.
    
    Thanks to Igor Kovalenko for reporting.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/gdbstub.c b/gdbstub.c
index 93c4850..474ed8a 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -804,7 +804,7 @@ static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
     /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
     switch (n) {
     case 64: GET_REGA(env->y);
-    case 65: GET_REGA(GET_PSR(env));
+    case 65: GET_REGA(cpu_get_psr(env));
     case 66: GET_REGA(env->wim);
     case 67: GET_REGA(env->tbr);
     case 68: GET_REGA(env->pc);
@@ -829,10 +829,10 @@ static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
     switch (n) {
     case 80: GET_REGL(env->pc);
     case 81: GET_REGL(env->npc);
-    case 82: GET_REGL(((uint64_t)GET_CCR(env) << 32) |
-                           ((env->asi & 0xff) << 24) |
-                           ((env->pstate & 0xfff) << 8) |
-                           GET_CWP64(env));
+    case 82: GET_REGL((cpu_get_ccr(env) << 32) |
+                      ((env->asi & 0xff) << 24) |
+                      ((env->pstate & 0xfff) << 8) |
+                      cpu_get_cwp64(env));
     case 83: GET_REGL(env->fsr);
     case 84: GET_REGL(env->fprs);
     case 85: GET_REGL(env->y);
@@ -868,7 +868,7 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
         /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
         switch (n) {
         case 64: env->y = tmp; break;
-        case 65: PUT_PSR(env, tmp); break;
+        case 65: cpu_put_psr(env, tmp); break;
         case 66: env->wim = tmp; break;
         case 67: env->tbr = tmp; break;
         case 68: env->pc = tmp; break;
@@ -892,10 +892,10 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
         case 80: env->pc = tmp; break;
         case 81: env->npc = tmp; break;
         case 82:
-	    PUT_CCR(env, tmp >> 32);
+            cpu_put_ccr(env, tmp >> 32);
 	    env->asi = (tmp >> 24) & 0xff;
 	    env->pstate = (tmp >> 8) & 0xfff;
-	    PUT_CWP64(env, tmp & 0xff);
+            cpu_put_cwp64(env, tmp & 0xff);
 	    break;
         case 83: env->fsr = tmp; break;
         case 84: env->fprs = tmp; break;
diff --git a/linux-user/signal.c b/linux-user/signal.c
index a72c15c..e5a187e 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -2111,8 +2111,8 @@ void sparc64_set_context(CPUSPARCState *env)
     err |= __get_user(env->y, &((*grp)[MC_Y]));
     err |= __get_user(tstate, &((*grp)[MC_TSTATE]));
     env->asi = (tstate >> 24) & 0xff;
-    PUT_CCR(env, tstate >> 32);
-    PUT_CWP64(env, tstate & 0x1f);
+    cpu_put_ccr(env, tstate >> 32);
+    cpu_put_cwp64(env, tstate & 0x1f);
     err |= __get_user(env->gregs[1], (&(*grp)[MC_G1]));
     err |= __get_user(env->gregs[2], (&(*grp)[MC_G2]));
     err |= __get_user(env->gregs[3], (&(*grp)[MC_G3]));
diff --git a/monitor.c b/monitor.c
index 46d0b47..a1ebc5d 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2856,7 +2856,8 @@ static target_long monitor_get_tbl (const struct MonitorDef *md, int val)
 static target_long monitor_get_psr (const struct MonitorDef *md, int val)
 {
     CPUState *env = mon_get_cpu();
-    return GET_PSR(env);
+
+    return cpu_get_psr(env);
 }
 #endif
 
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index b679333..22f3ad0 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -434,6 +434,7 @@ typedef struct CPUSPARCState {
     sparc_def_t *def;
 } CPUSPARCState;
 
+#ifndef NO_CPU_IO_DEFS
 /* helper.c */
 CPUSPARCState *cpu_sparc_init(const char *cpu_model);
 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu);
@@ -453,62 +454,18 @@ void gen_intermediate_code_init(CPUSPARCState *env);
 /* cpu-exec.c */
 int cpu_sparc_exec(CPUSPARCState *s);
 
-#if !defined (TARGET_SPARC64)
-#define GET_PSR(env) (env->version | (env->psr & PSR_ICC) |             \
-                      (env->psref? PSR_EF : 0) |                        \
-                      (env->psrpil << 8) |                              \
-                      (env->psrs? PSR_S : 0) |                          \
-                      (env->psrps? PSR_PS : 0) |                        \
-                      (env->psret? PSR_ET : 0) | env->cwp)
-#else
-#define GET_PSR(env) (env->version | (env->psr & PSR_ICC) |             \
-                      (env->psref? PSR_EF : 0) |                        \
-                      (env->psrpil << 8) |                              \
-                      (env->psrs? PSR_S : 0) |                          \
-                      (env->psrps? PSR_PS : 0) |                        \
-                      env->cwp)
-#endif
-
-#ifndef NO_CPU_IO_DEFS
-
-static inline int cpu_cwp_inc(CPUSPARCState *env1, int cwp)
-{
-    if (unlikely(cwp >= env1->nwindows))
-        cwp -= env1->nwindows;
-    return cwp;
-}
-
-static inline int cpu_cwp_dec(CPUSPARCState *env1, int cwp)
-{
-    if (unlikely(cwp < 0))
-        cwp += env1->nwindows;
-    return cwp;
-}
+/* op_helper.c */
+target_ulong cpu_get_psr(CPUState *env1);
+void cpu_put_psr(CPUState *env1, target_ulong val);
+#ifdef TARGET_SPARC64
+target_ulong cpu_get_ccr(CPUState *env1);
+void cpu_put_ccr(CPUState *env1, target_ulong val);
+target_ulong cpu_get_cwp64(CPUState *env1);
+void cpu_put_cwp64(CPUState *env1, int cwp);
 #endif
-
-static inline void memcpy32(target_ulong *dst, const target_ulong *src)
-{
-    dst[0] = src[0];
-    dst[1] = src[1];
-    dst[2] = src[2];
-    dst[3] = src[3];
-    dst[4] = src[4];
-    dst[5] = src[5];
-    dst[6] = src[6];
-    dst[7] = src[7];
-}
-
-static inline void cpu_set_cwp(CPUSPARCState *env1, int new_cwp)
-{
-    /* put the modified wrap registers at their proper location */
-    if (env1->cwp == env1->nwindows - 1)
-        memcpy32(env1->regbase, env1->regbase + env1->nwindows * 16);
-    env1->cwp = new_cwp;
-    /* put the wrap registers at their temporary location */
-    if (new_cwp == env1->nwindows - 1)
-        memcpy32(env1->regbase + env1->nwindows * 16, env1->regbase);
-    env1->regwptr = env1->regbase + (new_cwp * 16);
-}
+int cpu_cwp_inc(CPUState *env1, int cwp);
+int cpu_cwp_dec(CPUState *env1, int cwp);
+void cpu_set_cwp(CPUState *env1, int new_cwp);
 
 /* sun4m.c, sun4u.c */
 void cpu_check_irqs(CPUSPARCState *env);
@@ -530,41 +487,6 @@ static inline int tlb_compare_context(const SparcTLBEntry *tlb,
 }
 
 #endif
-
-static inline void PUT_PSR(CPUSPARCState *env1, target_ulong val)
-{
-    env1->psr = val & PSR_ICC;
-    env1->psref = (val & PSR_EF)? 1 : 0;
-    env1->psrpil = (val & PSR_PIL) >> 8;
-#if ((!defined (TARGET_SPARC64)) && !defined(CONFIG_USER_ONLY))
-    cpu_check_irqs(env1);
-#endif
-    env1->psrs = (val & PSR_S)? 1 : 0;
-    env1->psrps = (val & PSR_PS)? 1 : 0;
-#if !defined (TARGET_SPARC64)
-    env1->psret = (val & PSR_ET)? 1 : 0;
-#endif
-    cpu_set_cwp(env1, val & PSR_CWP);
-    env1->cc_op = CC_OP_FLAGS;
-}
-
-#ifdef TARGET_SPARC64
-#define GET_CCR(env) (((env->xcc >> 20) << 4) | ((env->psr & PSR_ICC) >> 20))
-#define PUT_CCR(env, val) do { int _tmp = val;                          \
-        env->xcc = (_tmp >> 4) << 20;                                   \
-        env->psr = (_tmp & 0xf) << 20;                                  \
-        CC_OP = CC_OP_FLAGS;                                            \
-    } while (0)
-#define GET_CWP64(env) (env->nwindows - 1 - (env)->cwp)
-
-#ifndef NO_CPU_IO_DEFS
-static inline void PUT_CWP64(CPUSPARCState *env1, int cwp)
-{
-    if (unlikely(cwp >= env1->nwindows || cwp < 0))
-        cwp %= env1->nwindows;
-    cpu_set_cwp(env1, env1->nwindows - 1 - cwp);
-}
-#endif
 #endif
 
 /* cpu-exec.c */
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index 0ba7c9f..4642122 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -1490,10 +1490,10 @@ void cpu_dump_state(CPUState *env, FILE *f,
     }
 #ifdef TARGET_SPARC64
     cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
-                GET_CCR(env));
-    cpu_print_cc(f, cpu_fprintf, GET_CCR(env) << PSR_CARRY_SHIFT);
+                cpu_get_ccr(env));
+    cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
     cpu_fprintf(f, " xcc: ");
-    cpu_print_cc(f, cpu_fprintf, GET_CCR(env) << (PSR_CARRY_SHIFT - 4));
+    cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
     cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
                 env->psrpil);
     cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
@@ -1503,8 +1503,8 @@ void cpu_dump_state(CPUState *env, FILE *f,
     cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
                 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
 #else
-    cpu_fprintf(f, "psr: %08x (icc: ", GET_PSR(env));
-    cpu_print_cc(f, cpu_fprintf, GET_PSR(env));
+    cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
+    cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
     cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs? 'S' : '-',
                 env->psrps? 'P' : '-', env->psret? 'E' : '-',
                 env->wim);
diff --git a/target-sparc/machine.c b/target-sparc/machine.c
index 4b87ec6..752e431 100644
--- a/target-sparc/machine.c
+++ b/target-sparc/machine.c
@@ -33,7 +33,7 @@ void cpu_save(QEMUFile *f, void *opaque)
     qemu_put_betls(f, &env->pc);
     qemu_put_betls(f, &env->npc);
     qemu_put_betls(f, &env->y);
-    tmp = GET_PSR(env);
+    tmp = cpu_get_psr(env);
     qemu_put_be32(f, tmp);
     qemu_put_betls(f, &env->fsr);
     qemu_put_betls(f, &env->tbr);
@@ -130,7 +130,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     tmp = qemu_get_be32(f);
     env->cwp = 0; /* needed to ensure that the wrapping registers are
                      correctly updated */
-    PUT_PSR(env, tmp);
+    cpu_put_psr(env, tmp);
     qemu_get_betls(f, &env->fsr);
     qemu_get_betls(f, &env->tbr);
     tmp = qemu_get_be32(f);
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index b6b08d3..fcfd3f3 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -253,11 +253,6 @@ void HELPER(raise_exception)(int tt)
     raise_exception(tt);
 }
 
-static inline void set_cwp(int new_cwp)
-{
-    cpu_set_cwp(env, new_cwp);
-}
-
 void helper_check_align(target_ulong addr, uint32_t align)
 {
     if (addr & align) {
@@ -1295,6 +1290,142 @@ uint32_t helper_compute_C_icc(void)
     return ret;
 }
 
+static inline void memcpy32(target_ulong *dst, const target_ulong *src)
+{
+    dst[0] = src[0];
+    dst[1] = src[1];
+    dst[2] = src[2];
+    dst[3] = src[3];
+    dst[4] = src[4];
+    dst[5] = src[5];
+    dst[6] = src[6];
+    dst[7] = src[7];
+}
+
+static void set_cwp(int new_cwp)
+{
+    /* put the modified wrap registers at their proper location */
+    if (env->cwp == env->nwindows - 1) {
+        memcpy32(env->regbase, env->regbase + env->nwindows * 16);
+    }
+    env->cwp = new_cwp;
+
+    /* put the wrap registers at their temporary location */
+    if (new_cwp == env->nwindows - 1) {
+        memcpy32(env->regbase + env->nwindows * 16, env->regbase);
+    }
+    env->regwptr = env->regbase + (new_cwp * 16);
+}
+
+void cpu_set_cwp(CPUState *env1, int new_cwp)
+{
+    CPUState *saved_env;
+
+    saved_env = env;
+    env = env1;
+    set_cwp(new_cwp);
+    env = saved_env;
+}
+
+static target_ulong get_psr(void)
+{
+    helper_compute_psr();
+
+#if !defined (TARGET_SPARC64)
+    return env->version | (env->psr & PSR_ICC) |
+        (env->psref? PSR_EF : 0) |
+        (env->psrpil << 8) |
+        (env->psrs? PSR_S : 0) |
+        (env->psrps? PSR_PS : 0) |
+        (env->psret? PSR_ET : 0) | env->cwp;
+#else
+    return env->version | (env->psr & PSR_ICC) |
+        (env->psref? PSR_EF : 0) |
+        (env->psrpil << 8) |
+        (env->psrs? PSR_S : 0) |
+        (env->psrps? PSR_PS : 0) | env->cwp;
+#endif
+}
+
+target_ulong cpu_get_psr(CPUState *env1)
+{
+    CPUState *saved_env;
+    target_ulong ret;
+
+    saved_env = env;
+    env = env1;
+    ret = get_psr();
+    env = saved_env;
+    return ret;
+}
+
+static void put_psr(target_ulong val)
+{
+    env->psr = val & PSR_ICC;
+    env->psref = (val & PSR_EF)? 1 : 0;
+    env->psrpil = (val & PSR_PIL) >> 8;
+#if ((!defined (TARGET_SPARC64)) && !defined(CONFIG_USER_ONLY))
+    cpu_check_irqs(env);
+#endif
+    env->psrs = (val & PSR_S)? 1 : 0;
+    env->psrps = (val & PSR_PS)? 1 : 0;
+#if !defined (TARGET_SPARC64)
+    env->psret = (val & PSR_ET)? 1 : 0;
+#endif
+    set_cwp(val & PSR_CWP);
+    env->cc_op = CC_OP_FLAGS;
+}
+
+void cpu_put_psr(CPUState *env1, target_ulong val)
+{
+    CPUState *saved_env;
+
+    saved_env = env;
+    env = env1;
+    put_psr(val);
+    env = saved_env;
+}
+
+static int cwp_inc(int cwp)
+{
+    if (unlikely(cwp >= env->nwindows)) {
+        cwp -= env->nwindows;
+    }
+    return cwp;
+}
+
+int cpu_cwp_inc(CPUState *env1, int cwp)
+{
+    CPUState *saved_env;
+    target_ulong ret;
+
+    saved_env = env;
+    env = env1;
+    ret = cwp_inc(cwp);
+    env = saved_env;
+    return ret;
+}
+
+static int cwp_dec(int cwp)
+{
+    if (unlikely(cwp < 0)) {
+        cwp += env->nwindows;
+    }
+    return cwp;
+}
+
+int cpu_cwp_dec(CPUState *env1, int cwp)
+{
+    CPUState *saved_env;
+    target_ulong ret;
+
+    saved_env = env;
+    env = env1;
+    ret = cwp_dec(cwp);
+    env = saved_env;
+    return ret;
+}
+
 #ifdef TARGET_SPARC64
 GEN_FCMPS(fcmps_fcc1, float32, 22, 0);
 GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
@@ -3016,7 +3147,7 @@ void helper_rett(void)
         raise_exception(TT_ILL_INSN);
 
     env->psret = 1;
-    cwp = cpu_cwp_inc(env, env->cwp + 1) ;
+    cwp = cwp_inc(env->cwp + 1) ;
     if (env->wim & (1 << cwp)) {
         raise_exception(TT_WIN_UNF);
     }
@@ -3236,7 +3367,7 @@ void helper_save(void)
 {
     uint32_t cwp;
 
-    cwp = cpu_cwp_dec(env, env->cwp - 1);
+    cwp = cwp_dec(env->cwp - 1);
     if (env->wim & (1 << cwp)) {
         raise_exception(TT_WIN_OVF);
     }
@@ -3247,7 +3378,7 @@ void helper_restore(void)
 {
     uint32_t cwp;
 
-    cwp = cpu_cwp_inc(env, env->cwp + 1);
+    cwp = cwp_inc(env->cwp + 1);
     if (env->wim & (1 << cwp)) {
         raise_exception(TT_WIN_UNF);
     }
@@ -3256,15 +3387,16 @@ void helper_restore(void)
 
 void helper_wrpsr(target_ulong new_psr)
 {
-    if ((new_psr & PSR_CWP) >= env->nwindows)
+    if ((new_psr & PSR_CWP) >= env->nwindows) {
         raise_exception(TT_ILL_INSN);
-    else
-        PUT_PSR(env, new_psr);
+    } else {
+        cpu_put_psr(env, new_psr);
+    }
 }
 
 target_ulong helper_rdpsr(void)
 {
-    return GET_PSR(env);
+    return get_psr();
 }
 
 #else
@@ -3274,7 +3406,7 @@ void helper_save(void)
 {
     uint32_t cwp;
 
-    cwp = cpu_cwp_dec(env, env->cwp - 1);
+    cwp = cwp_dec(env->cwp - 1);
     if (env->cansave == 0) {
         raise_exception(TT_SPILL | (env->otherwin != 0 ?
                                     (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
@@ -3295,7 +3427,7 @@ void helper_restore(void)
 {
     uint32_t cwp;
 
-    cwp = cpu_cwp_inc(env, env->cwp + 1);
+    cwp = cwp_inc(env->cwp + 1);
     if (env->canrestore == 0) {
         raise_exception(TT_FILL | (env->otherwin != 0 ?
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
@@ -3336,26 +3468,101 @@ void helper_restored(void)
         env->otherwin--;
 }
 
+static target_ulong get_ccr(void)
+{
+    target_ulong psr;
+
+    psr = get_psr();
+
+    return ((env->xcc >> 20) << 4) | ((psr & PSR_ICC) >> 20);
+}
+
+target_ulong cpu_get_ccr(CPUState *env1)
+{
+    CPUState *saved_env;
+    target_ulong ret;
+
+    saved_env = env;
+    env = env1;
+    ret = get_ccr();
+    env = saved_env;
+    return ret;
+}
+
+static void put_ccr(target_ulong val)
+{
+    target_ulong tmp = val;
+
+    env->xcc = (tmp >> 4) << 20;
+    env->psr = (tmp & 0xf) << 20;
+    CC_OP = CC_OP_FLAGS;
+}
+
+void cpu_put_ccr(CPUState *env1, target_ulong val)
+{
+    CPUState *saved_env;
+
+    saved_env = env;
+    env = env1;
+    put_ccr(val);
+    env = saved_env;
+}
+
+static target_ulong get_cwp64(void)
+{
+    return env->nwindows - 1 - env->cwp;
+}
+
+target_ulong cpu_get_cwp64(CPUState *env1)
+{
+    CPUState *saved_env;
+    target_ulong ret;
+
+    saved_env = env;
+    env = env1;
+    ret = get_cwp64();
+    env = saved_env;
+    return ret;
+}
+
+static void put_cwp64(int cwp)
+{
+    if (unlikely(cwp >= env->nwindows || cwp < 0)) {
+        cwp %= env->nwindows;
+    }
+    set_cwp(env->nwindows - 1 - cwp);
+}
+
+void cpu_put_cwp64(CPUState *env1, int cwp)
+{
+    CPUState *saved_env;
+
+    saved_env = env;
+    env = env1;
+    put_cwp64(cwp);
+    env = saved_env;
+}
+
 target_ulong helper_rdccr(void)
 {
-    return GET_CCR(env);
+    return get_ccr();
 }
 
 void helper_wrccr(target_ulong new_ccr)
 {
-    PUT_CCR(env, new_ccr);
+    put_ccr(new_ccr);
 }
 
 // CWP handling is reversed in V9, but we still use the V8 register
 // order.
 target_ulong helper_rdcwp(void)
 {
-    return GET_CWP64(env);
+    return get_cwp64();
 }
 
 void helper_wrcwp(target_ulong new_cwp)
 {
-    PUT_CWP64(env, new_cwp);
+    put_cwp64(new_cwp);
 }
 
 // This function uses non-native bit order
@@ -3475,10 +3682,10 @@ void helper_done(void)
 
     env->pc = tsptr->tnpc;
     env->npc = tsptr->tnpc + 4;
-    PUT_CCR(env, tsptr->tstate >> 32);
+    put_ccr(tsptr->tstate >> 32);
     env->asi = (tsptr->tstate >> 24) & 0xff;
     change_pstate((tsptr->tstate >> 8) & 0xf3f);
-    PUT_CWP64(env, tsptr->tstate & 0xff);
+    put_cwp64(tsptr->tstate & 0xff);
     env->tl--;
 
     DPRINTF_PSTATE("... helper_done tl=%d\n", env->tl);
@@ -3496,10 +3703,10 @@ void helper_retry(void)
 
     env->pc = tsptr->tpc;
     env->npc = tsptr->tnpc;
-    PUT_CCR(env, tsptr->tstate >> 32);
+    put_ccr(tsptr->tstate >> 32);
     env->asi = (tsptr->tstate >> 24) & 0xff;
     change_pstate((tsptr->tstate >> 8) & 0xf3f);
-    PUT_CWP64(env, tsptr->tstate & 0xff);
+    put_cwp64(tsptr->tstate & 0xff);
     env->tl--;
 
     DPRINTF_PSTATE("... helper_retry tl=%d\n", env->tl);
@@ -3650,9 +3857,9 @@ void do_interrupt(CPUState *env)
     }
     tsptr = cpu_tsptr(env);
 
-    tsptr->tstate = ((uint64_t)GET_CCR(env) << 32) |
+    tsptr->tstate = (get_ccr() << 32) |
         ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
-        GET_CWP64(env);
+        get_cwp64();
     tsptr->tpc = env->pc;
     tsptr->tnpc = env->npc;
     tsptr->tt = intno;
@@ -3673,12 +3880,13 @@ void do_interrupt(CPUState *env)
         break;
     }
 
-    if (intno == TT_CLRWIN)
-        cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1));
-    else if ((intno & 0x1c0) == TT_SPILL)
-        cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
-    else if ((intno & 0x1c0) == TT_FILL)
-        cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1));
+    if (intno == TT_CLRWIN) {
+        set_cwp(cwp_dec(env->cwp - 1));
+    } else if ((intno & 0x1c0) == TT_SPILL) {
+        set_cwp(cwp_dec(env->cwp - env->cansave - 2));
+    } else if ((intno & 0x1c0) == TT_FILL) {
+        set_cwp(cwp_inc(env->cwp + 1));
+    }
     env->tbr &= ~0x7fffULL;
     env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
     env->pc = env->tbr;
@@ -3769,8 +3977,8 @@ void do_interrupt(CPUState *env)
     }
 #endif
     env->psret = 0;
-    cwp = cpu_cwp_dec(env, env->cwp - 1);
-    cpu_set_cwp(env, cwp);
+    cwp = cwp_dec(env->cwp - 1);
+    set_cwp(cwp);
     env->regwptr[9] = env->pc;
     env->regwptr[10] = env->npc;
     env->psrps = env->psrs;
commit 275ea26546466446cf2ed83a93aa50e94538c203
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun May 9 15:40:24 2010 +0000

    sparc: lazy C flag calculation
    
    Calculate only the carry flag for ADDX/SUBX instead of full
    set of flags.
    
    Thanks to Igor Kovalenko for spotting a bug with an earlier
    version.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index be2a116..ea7c71b 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -334,9 +334,9 @@ static inline void gen_op_add_cc(TCGv dst, TCGv src1, TCGv src2)
 
 static inline void gen_op_addxi_cc(TCGv dst, TCGv src1, target_long src2)
 {
+    gen_helper_compute_C_icc(cpu_tmp0);
     tcg_gen_mov_tl(cpu_cc_src, src1);
     tcg_gen_movi_tl(cpu_cc_src2, src2);
-    gen_mov_reg_C(cpu_tmp0, cpu_psr);
     tcg_gen_add_tl(cpu_cc_dst, cpu_cc_src, cpu_tmp0);
     tcg_gen_addi_tl(cpu_cc_dst, cpu_cc_dst, src2);
     tcg_gen_mov_tl(dst, cpu_cc_dst);
@@ -344,9 +344,9 @@ static inline void gen_op_addxi_cc(TCGv dst, TCGv src1, target_long src2)
 
 static inline void gen_op_addx_cc(TCGv dst, TCGv src1, TCGv src2)
 {
+    gen_helper_compute_C_icc(cpu_tmp0);
     tcg_gen_mov_tl(cpu_cc_src, src1);
     tcg_gen_mov_tl(cpu_cc_src2, src2);
-    gen_mov_reg_C(cpu_tmp0, cpu_psr);
     tcg_gen_add_tl(cpu_cc_dst, cpu_cc_src, cpu_tmp0);
     tcg_gen_add_tl(cpu_cc_dst, cpu_cc_dst, cpu_cc_src2);
     tcg_gen_mov_tl(dst, cpu_cc_dst);
@@ -417,9 +417,9 @@ static inline void gen_op_sub_cc(TCGv dst, TCGv src1, TCGv src2)
 
 static inline void gen_op_subxi_cc(TCGv dst, TCGv src1, target_long src2)
 {
+    gen_helper_compute_C_icc(cpu_tmp0);
     tcg_gen_mov_tl(cpu_cc_src, src1);
     tcg_gen_movi_tl(cpu_cc_src2, src2);
-    gen_mov_reg_C(cpu_tmp0, cpu_psr);
     tcg_gen_sub_tl(cpu_cc_dst, cpu_cc_src, cpu_tmp0);
     tcg_gen_subi_tl(cpu_cc_dst, cpu_cc_dst, src2);
     tcg_gen_mov_tl(dst, cpu_cc_dst);
@@ -427,9 +427,9 @@ static inline void gen_op_subxi_cc(TCGv dst, TCGv src1, target_long src2)
 
 static inline void gen_op_subx_cc(TCGv dst, TCGv src1, TCGv src2)
 {
+    gen_helper_compute_C_icc(cpu_tmp0);
     tcg_gen_mov_tl(cpu_cc_src, src1);
     tcg_gen_mov_tl(cpu_cc_src2, src2);
-    gen_mov_reg_C(cpu_tmp0, cpu_psr);
     tcg_gen_sub_tl(cpu_cc_dst, cpu_cc_src, cpu_tmp0);
     tcg_gen_sub_tl(cpu_cc_dst, cpu_cc_dst, cpu_cc_src2);
     tcg_gen_mov_tl(dst, cpu_cc_dst);
@@ -2953,25 +2953,21 @@ static void disas_sparc_insn(DisasContext * dc)
                         if (IS_IMM) {
                             simm = GET_FIELDs(insn, 19, 31);
                             if (xop & 0x10) {
-                                gen_helper_compute_psr();
                                 gen_op_addxi_cc(cpu_dst, cpu_src1, simm);
                                 tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADDX);
                                 dc->cc_op = CC_OP_ADDX;
                             } else {
-                                gen_helper_compute_psr();
-                                gen_mov_reg_C(cpu_tmp0, cpu_psr);
+                                gen_helper_compute_C_icc(cpu_tmp0);
                                 tcg_gen_addi_tl(cpu_tmp0, cpu_tmp0, simm);
                                 tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_tmp0);
                             }
                         } else {
                             if (xop & 0x10) {
-                                gen_helper_compute_psr();
                                 gen_op_addx_cc(cpu_dst, cpu_src1, cpu_src2);
                                 tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADDX);
                                 dc->cc_op = CC_OP_ADDX;
                             } else {
-                                gen_helper_compute_psr();
-                                gen_mov_reg_C(cpu_tmp0, cpu_psr);
+                                gen_helper_compute_C_icc(cpu_tmp0);
                                 tcg_gen_add_tl(cpu_tmp0, cpu_src2, cpu_tmp0);
                                 tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_tmp0);
                             }
@@ -3009,25 +3005,21 @@ static void disas_sparc_insn(DisasContext * dc)
                         if (IS_IMM) {
                             simm = GET_FIELDs(insn, 19, 31);
                             if (xop & 0x10) {
-                                gen_helper_compute_psr();
                                 gen_op_subxi_cc(cpu_dst, cpu_src1, simm);
                                 tcg_gen_movi_i32(cpu_cc_op, CC_OP_SUBX);
                                 dc->cc_op = CC_OP_SUBX;
                             } else {
-                                gen_helper_compute_psr();
-                                gen_mov_reg_C(cpu_tmp0, cpu_psr);
+                                gen_helper_compute_C_icc(cpu_tmp0);
                                 tcg_gen_addi_tl(cpu_tmp0, cpu_tmp0, simm);
                                 tcg_gen_sub_tl(cpu_dst, cpu_src1, cpu_tmp0);
                             }
                         } else {
                             if (xop & 0x10) {
-                                gen_helper_compute_psr();
                                 gen_op_subx_cc(cpu_dst, cpu_src1, cpu_src2);
                                 tcg_gen_movi_i32(cpu_cc_op, CC_OP_SUBX);
                                 dc->cc_op = CC_OP_SUBX;
                             } else {
-                                gen_helper_compute_psr();
-                                gen_mov_reg_C(cpu_tmp0, cpu_psr);
+                                gen_helper_compute_C_icc(cpu_tmp0);
                                 tcg_gen_add_tl(cpu_tmp0, cpu_src2, cpu_tmp0);
                                 tcg_gen_sub_tl(cpu_dst, cpu_src1, cpu_tmp0);
                             }
commit 72139e83a98eba2bfed2dbc2db2818fb19e47ca0
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Fri May 7 23:20:56 2010 +0200

    mips-dis: Add missing static attributes
    
    mips_abi_choices and mips_arch_choices are only used locally.
    
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/mips-dis.c b/mips-dis.c
index 169169c..ae64543 100644
--- a/mips-dis.c
+++ b/mips-dis.c
@@ -3035,7 +3035,7 @@ struct mips_abi_choice
   const char * const *fpr_names;
 };
 
-struct mips_abi_choice mips_abi_choices[] =
+static struct mips_abi_choice mips_abi_choices[] =
 {
   { "numeric", mips_gpr_names_numeric, mips_fpr_names_numeric },
   { "32", mips_gpr_names_oldabi, mips_fpr_names_32 },
@@ -3086,7 +3086,7 @@ struct mips_arch_choice
 
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
 
-const struct mips_arch_choice mips_arch_choices[] =
+static const struct mips_arch_choice mips_arch_choices[] =
 {
   { "numeric",	0, 0, 0, 0,
     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
commit a5ad59166aa7b8a3159ad057b77c8df6d84a9fa0
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Fri May 7 19:47:31 2010 +0200

    tcg: Add missing 'static' attribute
    
    tcg_out_reloc is only used locally (in */target.c which is
    included in tcg.c).
    
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/tcg/tcg.c b/tcg/tcg.c
index beceff0..a99ecb9 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -100,8 +100,8 @@ static inline void tcg_out32(TCGContext *s, uint32_t v)
 
 /* label relocation processing */
 
-void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type, 
-                   int label_index, long addend)
+static void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type,
+                          int label_index, long addend)
 {
     TCGLabel *l;
     TCGRelocation *r;
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 166c889..44856e1 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -477,9 +477,6 @@ TCGv_i64 tcg_const_i64(int64_t val);
 TCGv_i32 tcg_const_local_i32(int32_t val);
 TCGv_i64 tcg_const_local_i64(int64_t val);
 
-void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type, 
-                   int label_index, long addend);
-
 extern uint8_t code_gen_prologue[];
 #if defined(_ARCH_PPC) && !defined(_ARCH_PPC64)
 #define tcg_qemu_tb_exec(tb_ptr) \
commit 92b30744d7da8facd8f2206731bae87eebb06164
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri May 7 12:43:46 2010 +0200

    qcow2: Remove static forward declaration
    
    OpenBSDs gcc is said to generate warnings for this declaration, so don't
    reference bdrv_qcow2 directly, but look it up using bdrv_find_format.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/block/qcow2.c b/block/qcow2.c
index 3dbe4b8..ebad4e1 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -52,8 +52,6 @@ typedef struct {
 #define  QCOW_EXT_MAGIC_END 0
 #define  QCOW_EXT_MAGIC_BACKING_FORMAT 0xE2792ACA
 
-static BlockDriver bdrv_qcow2;
-
 static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
 {
     const QCowHeader *cow_header = (const void *)buf;
@@ -1018,8 +1016,9 @@ exit:
     /* Preallocate metadata */
     if (ret == 0 && prealloc) {
         BlockDriverState *bs;
+        BlockDriver *drv = bdrv_find_format("qcow2");
         bs = bdrv_new("");
-        bdrv_open(bs, filename, BDRV_O_CACHE_WB | BDRV_O_RDWR, &bdrv_qcow2);
+        bdrv_open(bs, filename, BDRV_O_CACHE_WB | BDRV_O_RDWR, drv);
         preallocate(bs);
         bdrv_close(bs);
     }
commit de5f3f40afb6e6491cc650d803254adc79da60e7
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri May 7 12:43:45 2010 +0200

    Revert "Fix OpenBSD build"
    
    This reverts commit 20d97356c9df6d68fbd37d6334fdb7063f24eab6.
    The BlockDriver definition should stay at the end of source files.
    
    Conflicts:
    
    	block/qcow2.c
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/block/qcow2.c b/block/qcow2.c
index 21ed6f8..3dbe4b8 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -52,7 +52,7 @@ typedef struct {
 #define  QCOW_EXT_MAGIC_END 0
 #define  QCOW_EXT_MAGIC_BACKING_FORMAT 0xE2792ACA
 
-static int qcow_create(const char *filename, QEMUOptionParameter *options);
+static BlockDriver bdrv_qcow2;
 
 static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
 {
@@ -830,6 +830,250 @@ static int preallocate(BlockDriverState *bs)
     return 0;
 }
 
+static int qcow_create2(const char *filename, int64_t total_size,
+                        const char *backing_file, const char *backing_format,
+                        int flags, size_t cluster_size, int prealloc)
+{
+
+    int fd, header_size, backing_filename_len, l1_size, i, shift, l2_bits;
+    int ref_clusters, reftable_clusters, backing_format_len = 0;
+    int rounded_ext_bf_len = 0;
+    QCowHeader header;
+    uint64_t tmp, offset;
+    uint64_t old_ref_clusters;
+    QCowCreateState s1, *s = &s1;
+    QCowExtension ext_bf = {0, 0};
+    int ret;
+
+    memset(s, 0, sizeof(*s));
+
+    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
+    if (fd < 0)
+        return -errno;
+    memset(&header, 0, sizeof(header));
+    header.magic = cpu_to_be32(QCOW_MAGIC);
+    header.version = cpu_to_be32(QCOW_VERSION);
+    header.size = cpu_to_be64(total_size * 512);
+    header_size = sizeof(header);
+    backing_filename_len = 0;
+    if (backing_file) {
+        if (backing_format) {
+            ext_bf.magic = QCOW_EXT_MAGIC_BACKING_FORMAT;
+            backing_format_len = strlen(backing_format);
+            ext_bf.len = backing_format_len;
+            rounded_ext_bf_len = (sizeof(ext_bf) + ext_bf.len + 7) & ~7;
+            header_size += rounded_ext_bf_len;
+        }
+        header.backing_file_offset = cpu_to_be64(header_size);
+        backing_filename_len = strlen(backing_file);
+        header.backing_file_size = cpu_to_be32(backing_filename_len);
+        header_size += backing_filename_len;
+    }
+
+    /* Cluster size */
+    s->cluster_bits = get_bits_from_size(cluster_size);
+    if (s->cluster_bits < MIN_CLUSTER_BITS ||
+        s->cluster_bits > MAX_CLUSTER_BITS)
+    {
+        fprintf(stderr, "Cluster size must be a power of two between "
+            "%d and %dk\n",
+            1 << MIN_CLUSTER_BITS,
+            1 << (MAX_CLUSTER_BITS - 10));
+        return -EINVAL;
+    }
+    s->cluster_size = 1 << s->cluster_bits;
+
+    header.cluster_bits = cpu_to_be32(s->cluster_bits);
+    header_size = (header_size + 7) & ~7;
+    if (flags & BLOCK_FLAG_ENCRYPT) {
+        header.crypt_method = cpu_to_be32(QCOW_CRYPT_AES);
+    } else {
+        header.crypt_method = cpu_to_be32(QCOW_CRYPT_NONE);
+    }
+    l2_bits = s->cluster_bits - 3;
+    shift = s->cluster_bits + l2_bits;
+    l1_size = (((total_size * 512) + (1LL << shift) - 1) >> shift);
+    offset = align_offset(header_size, s->cluster_size);
+    s->l1_table_offset = offset;
+    header.l1_table_offset = cpu_to_be64(s->l1_table_offset);
+    header.l1_size = cpu_to_be32(l1_size);
+    offset += align_offset(l1_size * sizeof(uint64_t), s->cluster_size);
+
+    /* count how many refcount blocks needed */
+
+#define NUM_CLUSTERS(bytes) \
+    (((bytes) + (s->cluster_size) - 1) / (s->cluster_size))
+
+    ref_clusters = NUM_CLUSTERS(NUM_CLUSTERS(offset) * sizeof(uint16_t));
+
+    do {
+        uint64_t image_clusters;
+        old_ref_clusters = ref_clusters;
+
+        /* Number of clusters used for the refcount table */
+        reftable_clusters = NUM_CLUSTERS(ref_clusters * sizeof(uint64_t));
+
+        /* Number of clusters that the whole image will have */
+        image_clusters = NUM_CLUSTERS(offset) + ref_clusters
+            + reftable_clusters;
+
+        /* Number of refcount blocks needed for the image */
+        ref_clusters = NUM_CLUSTERS(image_clusters * sizeof(uint16_t));
+
+    } while (ref_clusters != old_ref_clusters);
+
+    s->refcount_table = qemu_mallocz(reftable_clusters * s->cluster_size);
+
+    s->refcount_table_offset = offset;
+    header.refcount_table_offset = cpu_to_be64(offset);
+    header.refcount_table_clusters = cpu_to_be32(reftable_clusters);
+    offset += (reftable_clusters * s->cluster_size);
+    s->refcount_block_offset = offset;
+
+    for (i=0; i < ref_clusters; i++) {
+        s->refcount_table[i] = cpu_to_be64(offset);
+        offset += s->cluster_size;
+    }
+
+    s->refcount_block = qemu_mallocz(ref_clusters * s->cluster_size);
+
+    /* update refcounts */
+    qcow2_create_refcount_update(s, 0, header_size);
+    qcow2_create_refcount_update(s, s->l1_table_offset,
+        l1_size * sizeof(uint64_t));
+    qcow2_create_refcount_update(s, s->refcount_table_offset,
+        reftable_clusters * s->cluster_size);
+    qcow2_create_refcount_update(s, s->refcount_block_offset,
+        ref_clusters * s->cluster_size);
+
+    /* write all the data */
+    ret = qemu_write_full(fd, &header, sizeof(header));
+    if (ret != sizeof(header)) {
+        ret = -errno;
+        goto exit;
+    }
+    if (backing_file) {
+        if (backing_format_len) {
+            char zero[16];
+            int padding = rounded_ext_bf_len - (ext_bf.len + sizeof(ext_bf));
+
+            memset(zero, 0, sizeof(zero));
+            cpu_to_be32s(&ext_bf.magic);
+            cpu_to_be32s(&ext_bf.len);
+            ret = qemu_write_full(fd, &ext_bf, sizeof(ext_bf));
+            if (ret != sizeof(ext_bf)) {
+                ret = -errno;
+                goto exit;
+            }
+            ret = qemu_write_full(fd, backing_format, backing_format_len);
+            if (ret != backing_format_len) {
+                ret = -errno;
+                goto exit;
+            }
+            if (padding > 0) {
+                ret = qemu_write_full(fd, zero, padding);
+                if (ret != padding) {
+                    ret = -errno;
+                    goto exit;
+                }
+            }
+        }
+        ret = qemu_write_full(fd, backing_file, backing_filename_len);
+        if (ret != backing_filename_len) {
+            ret = -errno;
+            goto exit;
+        }
+    }
+    lseek(fd, s->l1_table_offset, SEEK_SET);
+    tmp = 0;
+    for(i = 0;i < l1_size; i++) {
+        ret = qemu_write_full(fd, &tmp, sizeof(tmp));
+        if (ret != sizeof(tmp)) {
+            ret = -errno;
+            goto exit;
+        }
+    }
+    lseek(fd, s->refcount_table_offset, SEEK_SET);
+    ret = qemu_write_full(fd, s->refcount_table,
+        reftable_clusters * s->cluster_size);
+    if (ret != reftable_clusters * s->cluster_size) {
+        ret = -errno;
+        goto exit;
+    }
+
+    lseek(fd, s->refcount_block_offset, SEEK_SET);
+    ret = qemu_write_full(fd, s->refcount_block,
+		    ref_clusters * s->cluster_size);
+    if (ret != ref_clusters * s->cluster_size) {
+        ret = -errno;
+        goto exit;
+    }
+
+    ret = 0;
+exit:
+    qemu_free(s->refcount_table);
+    qemu_free(s->refcount_block);
+    close(fd);
+
+    /* Preallocate metadata */
+    if (ret == 0 && prealloc) {
+        BlockDriverState *bs;
+        bs = bdrv_new("");
+        bdrv_open(bs, filename, BDRV_O_CACHE_WB | BDRV_O_RDWR, &bdrv_qcow2);
+        preallocate(bs);
+        bdrv_close(bs);
+    }
+
+    return ret;
+}
+
+static int qcow_create(const char *filename, QEMUOptionParameter *options)
+{
+    const char *backing_file = NULL;
+    const char *backing_fmt = NULL;
+    uint64_t sectors = 0;
+    int flags = 0;
+    size_t cluster_size = 65536;
+    int prealloc = 0;
+
+    /* Read out options */
+    while (options && options->name) {
+        if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
+            sectors = options->value.n / 512;
+        } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
+            backing_file = options->value.s;
+        } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FMT)) {
+            backing_fmt = options->value.s;
+        } else if (!strcmp(options->name, BLOCK_OPT_ENCRYPT)) {
+            flags |= options->value.n ? BLOCK_FLAG_ENCRYPT : 0;
+        } else if (!strcmp(options->name, BLOCK_OPT_CLUSTER_SIZE)) {
+            if (options->value.n) {
+                cluster_size = options->value.n;
+            }
+        } else if (!strcmp(options->name, BLOCK_OPT_PREALLOC)) {
+            if (!options->value.s || !strcmp(options->value.s, "off")) {
+                prealloc = 0;
+            } else if (!strcmp(options->value.s, "metadata")) {
+                prealloc = 1;
+            } else {
+                fprintf(stderr, "Invalid preallocation mode: '%s'\n",
+                    options->value.s);
+                return -EINVAL;
+            }
+        }
+        options++;
+    }
+
+    if (backing_file && prealloc) {
+        fprintf(stderr, "Backing file and preallocation cannot be used at "
+            "the same time\n");
+        return -EINVAL;
+    }
+
+    return qcow_create2(filename, sectors, backing_file, backing_fmt, flags,
+        cluster_size, prealloc);
+}
+
 static int qcow_make_empty(BlockDriverState *bs)
 {
 #if 0
@@ -1105,250 +1349,6 @@ static BlockDriver bdrv_qcow2 = {
     .bdrv_check = qcow_check,
 };
 
-static int qcow_create2(const char *filename, int64_t total_size,
-                        const char *backing_file, const char *backing_format,
-                        int flags, size_t cluster_size, int prealloc)
-{
-
-    int fd, header_size, backing_filename_len, l1_size, i, shift, l2_bits;
-    int ref_clusters, reftable_clusters, backing_format_len = 0;
-    int rounded_ext_bf_len = 0;
-    QCowHeader header;
-    uint64_t tmp, offset;
-    uint64_t old_ref_clusters;
-    QCowCreateState s1, *s = &s1;
-    QCowExtension ext_bf = {0, 0};
-    int ret;
-
-    memset(s, 0, sizeof(*s));
-
-    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
-    if (fd < 0)
-        return -errno;
-    memset(&header, 0, sizeof(header));
-    header.magic = cpu_to_be32(QCOW_MAGIC);
-    header.version = cpu_to_be32(QCOW_VERSION);
-    header.size = cpu_to_be64(total_size * 512);
-    header_size = sizeof(header);
-    backing_filename_len = 0;
-    if (backing_file) {
-        if (backing_format) {
-            ext_bf.magic = QCOW_EXT_MAGIC_BACKING_FORMAT;
-            backing_format_len = strlen(backing_format);
-            ext_bf.len = backing_format_len;
-            rounded_ext_bf_len = (sizeof(ext_bf) + ext_bf.len + 7) & ~7;
-            header_size += rounded_ext_bf_len;
-        }
-        header.backing_file_offset = cpu_to_be64(header_size);
-        backing_filename_len = strlen(backing_file);
-        header.backing_file_size = cpu_to_be32(backing_filename_len);
-        header_size += backing_filename_len;
-    }
-
-    /* Cluster size */
-    s->cluster_bits = get_bits_from_size(cluster_size);
-    if (s->cluster_bits < MIN_CLUSTER_BITS ||
-        s->cluster_bits > MAX_CLUSTER_BITS)
-    {
-        fprintf(stderr, "Cluster size must be a power of two between "
-            "%d and %dk\n",
-            1 << MIN_CLUSTER_BITS,
-            1 << (MAX_CLUSTER_BITS - 10));
-        return -EINVAL;
-    }
-    s->cluster_size = 1 << s->cluster_bits;
-
-    header.cluster_bits = cpu_to_be32(s->cluster_bits);
-    header_size = (header_size + 7) & ~7;
-    if (flags & BLOCK_FLAG_ENCRYPT) {
-        header.crypt_method = cpu_to_be32(QCOW_CRYPT_AES);
-    } else {
-        header.crypt_method = cpu_to_be32(QCOW_CRYPT_NONE);
-    }
-    l2_bits = s->cluster_bits - 3;
-    shift = s->cluster_bits + l2_bits;
-    l1_size = (((total_size * 512) + (1LL << shift) - 1) >> shift);
-    offset = align_offset(header_size, s->cluster_size);
-    s->l1_table_offset = offset;
-    header.l1_table_offset = cpu_to_be64(s->l1_table_offset);
-    header.l1_size = cpu_to_be32(l1_size);
-    offset += align_offset(l1_size * sizeof(uint64_t), s->cluster_size);
-
-    /* count how many refcount blocks needed */
-
-#define NUM_CLUSTERS(bytes) \
-    (((bytes) + (s->cluster_size) - 1) / (s->cluster_size))
-
-    ref_clusters = NUM_CLUSTERS(NUM_CLUSTERS(offset) * sizeof(uint16_t));
-
-    do {
-        uint64_t image_clusters;
-        old_ref_clusters = ref_clusters;
-
-        /* Number of clusters used for the refcount table */
-        reftable_clusters = NUM_CLUSTERS(ref_clusters * sizeof(uint64_t));
-
-        /* Number of clusters that the whole image will have */
-        image_clusters = NUM_CLUSTERS(offset) + ref_clusters
-            + reftable_clusters;
-
-        /* Number of refcount blocks needed for the image */
-        ref_clusters = NUM_CLUSTERS(image_clusters * sizeof(uint16_t));
-
-    } while (ref_clusters != old_ref_clusters);
-
-    s->refcount_table = qemu_mallocz(reftable_clusters * s->cluster_size);
-
-    s->refcount_table_offset = offset;
-    header.refcount_table_offset = cpu_to_be64(offset);
-    header.refcount_table_clusters = cpu_to_be32(reftable_clusters);
-    offset += (reftable_clusters * s->cluster_size);
-    s->refcount_block_offset = offset;
-
-    for (i=0; i < ref_clusters; i++) {
-        s->refcount_table[i] = cpu_to_be64(offset);
-        offset += s->cluster_size;
-    }
-
-    s->refcount_block = qemu_mallocz(ref_clusters * s->cluster_size);
-
-    /* update refcounts */
-    qcow2_create_refcount_update(s, 0, header_size);
-    qcow2_create_refcount_update(s, s->l1_table_offset,
-        l1_size * sizeof(uint64_t));
-    qcow2_create_refcount_update(s, s->refcount_table_offset,
-        reftable_clusters * s->cluster_size);
-    qcow2_create_refcount_update(s, s->refcount_block_offset,
-        ref_clusters * s->cluster_size);
-
-    /* write all the data */
-    ret = qemu_write_full(fd, &header, sizeof(header));
-    if (ret != sizeof(header)) {
-        ret = -errno;
-        goto exit;
-    }
-    if (backing_file) {
-        if (backing_format_len) {
-            char zero[16];
-            int padding = rounded_ext_bf_len - (ext_bf.len + sizeof(ext_bf));
-
-            memset(zero, 0, sizeof(zero));
-            cpu_to_be32s(&ext_bf.magic);
-            cpu_to_be32s(&ext_bf.len);
-            ret = qemu_write_full(fd, &ext_bf, sizeof(ext_bf));
-            if (ret != sizeof(ext_bf)) {
-                ret = -errno;
-                goto exit;
-            }
-            ret = qemu_write_full(fd, backing_format, backing_format_len);
-            if (ret != backing_format_len) {
-                ret = -errno;
-                goto exit;
-            }
-            if (padding > 0) {
-                ret = qemu_write_full(fd, zero, padding);
-                if (ret != padding) {
-                    ret = -errno;
-                    goto exit;
-                }
-            }
-        }
-        ret = qemu_write_full(fd, backing_file, backing_filename_len);
-        if (ret != backing_filename_len) {
-            ret = -errno;
-            goto exit;
-        }
-    }
-    lseek(fd, s->l1_table_offset, SEEK_SET);
-    tmp = 0;
-    for(i = 0;i < l1_size; i++) {
-        ret = qemu_write_full(fd, &tmp, sizeof(tmp));
-        if (ret != sizeof(tmp)) {
-            ret = -errno;
-            goto exit;
-        }
-    }
-    lseek(fd, s->refcount_table_offset, SEEK_SET);
-    ret = qemu_write_full(fd, s->refcount_table,
-        reftable_clusters * s->cluster_size);
-    if (ret != reftable_clusters * s->cluster_size) {
-        ret = -errno;
-        goto exit;
-    }
-
-    lseek(fd, s->refcount_block_offset, SEEK_SET);
-    ret = qemu_write_full(fd, s->refcount_block,
-		    ref_clusters * s->cluster_size);
-    if (ret != ref_clusters * s->cluster_size) {
-        ret = -errno;
-        goto exit;
-    }
-
-    ret = 0;
-exit:
-    qemu_free(s->refcount_table);
-    qemu_free(s->refcount_block);
-    close(fd);
-
-    /* Preallocate metadata */
-    if (ret == 0 && prealloc) {
-        BlockDriverState *bs;
-        bs = bdrv_new("");
-        bdrv_open(bs, filename, BDRV_O_CACHE_WB | BDRV_O_RDWR, &bdrv_qcow2);
-        preallocate(bs);
-        bdrv_close(bs);
-    }
-
-    return ret;
-}
-
-static int qcow_create(const char *filename, QEMUOptionParameter *options)
-{
-    const char *backing_file = NULL;
-    const char *backing_fmt = NULL;
-    uint64_t sectors = 0;
-    int flags = 0;
-    size_t cluster_size = 65536;
-    int prealloc = 0;
-
-    /* Read out options */
-    while (options && options->name) {
-        if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
-            sectors = options->value.n / 512;
-        } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
-            backing_file = options->value.s;
-        } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FMT)) {
-            backing_fmt = options->value.s;
-        } else if (!strcmp(options->name, BLOCK_OPT_ENCRYPT)) {
-            flags |= options->value.n ? BLOCK_FLAG_ENCRYPT : 0;
-        } else if (!strcmp(options->name, BLOCK_OPT_CLUSTER_SIZE)) {
-            if (options->value.n) {
-                cluster_size = options->value.n;
-            }
-        } else if (!strcmp(options->name, BLOCK_OPT_PREALLOC)) {
-            if (!options->value.s || !strcmp(options->value.s, "off")) {
-                prealloc = 0;
-            } else if (!strcmp(options->value.s, "metadata")) {
-                prealloc = 1;
-            } else {
-                fprintf(stderr, "Invalid preallocation mode: '%s'\n",
-                    options->value.s);
-                return -EINVAL;
-            }
-        }
-        options++;
-    }
-
-    if (backing_file && prealloc) {
-        fprintf(stderr, "Backing file and preallocation cannot be used at "
-            "the same time\n");
-        return -EINVAL;
-    }
-
-    return qcow_create2(filename, sectors, backing_file, backing_fmt, flags,
-        cluster_size, prealloc);
-}
-
 static void bdrv_qcow2_init(void)
 {
     bdrv_register(&bdrv_qcow2);
commit 3cab721d0e01422337d14250f66b6362eb573aa2
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri May 7 09:52:51 2010 -0700

    Fill in unassigned mem read/write callbacks.
    
    Implement the "functions may be omitted with NULL pointer"
    interface mentioned in the function block comment by transforming
    NULL entries in the read/write arrays into calls to the
    unassigned_mem family of functions.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/exec.c b/exec.c
index e980788..3416aed 100644
--- a/exec.c
+++ b/exec.c
@@ -3262,6 +3262,8 @@ static int cpu_register_io_memory_fixed(int io_index,
                                         CPUWriteMemoryFunc * const *mem_write,
                                         void *opaque)
 {
+    int i;
+
     if (io_index <= 0) {
         io_index = get_free_io_mem_idx();
         if (io_index == -1)
@@ -3272,8 +3274,14 @@ static int cpu_register_io_memory_fixed(int io_index,
             return -1;
     }
 
-    memcpy(io_mem_read[io_index], mem_read, 3 * sizeof(CPUReadMemoryFunc*));
-    memcpy(io_mem_write[io_index], mem_write, 3 * sizeof(CPUWriteMemoryFunc*));
+    for (i = 0; i < 3; ++i) {
+        io_mem_read[io_index][i]
+            = (mem_read[i] ? mem_read[i] : unassigned_mem_read[i]);
+    }
+    for (i = 0; i < 3; ++i) {
+        io_mem_write[io_index][i]
+            = (mem_write[i] ? mem_write[i] : unassigned_mem_write[i]);
+    }
     io_mem_opaque[io_index] = opaque;
 
     return (io_index << IO_MEM_SHIFT);
commit 4cbd40cec0e5b54856bad2ddcc714ca8be350029
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Thu May 6 22:19:20 2010 +0200

    darwin-user: Add missing static attribute
    
    Function usage is only used locally, so add "static".
    
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/darwin-user/main.c b/darwin-user/main.c
index ade7d48..175e12f 100644
--- a/darwin-user/main.c
+++ b/darwin-user/main.c
@@ -704,7 +704,7 @@ void cpu_loop(CPUX86State *env)
 }
 #endif
 
-void usage(void)
+static void usage(void)
 {
     printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003-2004 Fabrice Bellard\n"
            "usage: qemu-" TARGET_ARCH " [-h] [-d opts] [-L path] [-s size] program [arguments...]\n"
commit 051eb6c135d1f297d9b98717e2a5cc56ee76fbf1
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Thu May 6 22:17:54 2010 +0200

    Add missing 'static' attribute
    
    Function usage() is only used locally.
    
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/tests/qruncom.c b/tests/qruncom.c
index a8d0ef6..079f7a2 100644
--- a/tests/qruncom.c
+++ b/tests/qruncom.c
@@ -89,7 +89,7 @@ int errno;
 
 #define COM_BASE_ADDR    0x10100
 
-void usage(void)
+static void usage(void)
 {
     printf("qruncom version 0.1 (c) 2003 Fabrice Bellard\n"
            "usage: qruncom file.com\n"
diff --git a/tests/runcom.c b/tests/runcom.c
index cbbaf31..6380566 100644
--- a/tests/runcom.c
+++ b/tests/runcom.c
@@ -25,7 +25,7 @@ _syscall2(int, vm86, int, func, struct vm86plus_struct *, v86)
 
 #define COM_BASE_ADDR    0x10100
 
-void usage(void)
+static void usage(void)
 {
     printf("runcom version 0.1 (c) 2003 Fabrice Bellard\n"
            "usage: runcom file.com\n"
commit 4450521668471c7685551d8c5bcc582d754e9843
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Fri May 7 16:14:59 2010 +0000

    sparc64: fix build with older gccs
    
    Fix errors missed in 2065061ede22d401aae2ce995c3af54db9d28639:
     CC    sparc64-softmmu/helper.o
    cc1: warnings being treated as errors
    /src/qemu/target-sparc/helper.c: In function 'get_physical_address':
    /src/qemu/target-sparc/helper.c:426: warning: 'context' may be used uninitialized in this function
    /src/qemu/target-sparc/helper.c:426: note: 'context' was declared here
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index cac6cad..0ba7c9f 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -444,6 +444,7 @@ static int get_physical_address_data(CPUState *env,
         context = env->dmmu.mmu_secondary_context & 0x1fff;
         break;
     case MMU_NUCLEUS_IDX:
+    default:
         context = 0;
         break;
     }
commit 2065061ede22d401aae2ce995c3af54db9d28639
Author: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Date:   Mon May 3 11:29:44 2010 +0400

    sparc64: handle asi referencing nucleus and secondary MMU contexts
    
    - increase max supported MMU modes to 6
    - handle nucleus context asi
    - handle secondary context asi
    - handle non-faulting loads from secondary context
    
    Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/softmmu_exec.h b/softmmu_exec.h
index a43e621..28d1d53 100644
--- a/softmmu_exec.h
+++ b/softmmu_exec.h
@@ -100,9 +100,28 @@
 #undef MEMSUFFIX
 #endif /* (NB_MMU_MODES >= 5) */
 
-#if (NB_MMU_MODES > 5)
-#error "NB_MMU_MODES > 5 is not supported for now"
-#endif /* (NB_MMU_MODES > 5) */
+#if (NB_MMU_MODES >= 6)
+
+#define ACCESS_TYPE 5
+#define MEMSUFFIX MMU_MODE5_SUFFIX
+#define DATA_SIZE 1
+#include "softmmu_header.h"
+
+#define DATA_SIZE 2
+#include "softmmu_header.h"
+
+#define DATA_SIZE 4
+#include "softmmu_header.h"
+
+#define DATA_SIZE 8
+#include "softmmu_header.h"
+#undef ACCESS_TYPE
+#undef MEMSUFFIX
+#endif /* (NB_MMU_MODES >= 6) */
+
+#if (NB_MMU_MODES > 6)
+#error "NB_MMU_MODES > 6 is not supported for now"
+#endif /* (NB_MMU_MODES > 6) */
 
 /* these access are slower, they must be as rare as possible */
 #define ACCESS_TYPE (NB_MMU_MODES)
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index b705728..b679333 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -224,7 +224,7 @@ enum {
 #if !defined(TARGET_SPARC64)
 #define NB_MMU_MODES 2
 #else
-#define NB_MMU_MODES 3
+#define NB_MMU_MODES 6
 typedef struct trap_state {
     uint64_t tpc;
     uint64_t tnpc;
@@ -571,6 +571,9 @@ static inline void PUT_CWP64(CPUSPARCState *env1, int cwp)
 #if !defined(CONFIG_USER_ONLY)
 void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
                           int is_asi, int size);
+target_phys_addr_t cpu_get_phys_page_nofault(CPUState *env, target_ulong addr,
+                                           int mmu_idx);
+
 #endif
 int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc);
 
@@ -587,10 +590,18 @@ int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc);
 #define MMU_MODE1_SUFFIX _kernel
 #ifdef TARGET_SPARC64
 #define MMU_MODE2_SUFFIX _hypv
+#define MMU_MODE3_SUFFIX _nucleus
+#define MMU_MODE4_SUFFIX _user_secondary
+#define MMU_MODE5_SUFFIX _kernel_secondary
 #endif
 #define MMU_USER_IDX   0
 #define MMU_KERNEL_IDX 1
 #define MMU_HYPV_IDX   2
+#ifdef TARGET_SPARC64
+#define MMU_NUCLEUS_IDX 3
+#define MMU_USER_SECONDARY_IDX   4
+#define MMU_KERNEL_SECONDARY_IDX 5
+#endif
 
 static inline int cpu_mmu_index(CPUState *env1)
 {
diff --git a/target-sparc/exec.h b/target-sparc/exec.h
index 70df828..1e9de82 100644
--- a/target-sparc/exec.h
+++ b/target-sparc/exec.h
@@ -13,6 +13,10 @@ register struct CPUSPARCState *env asm(AREG0);
 #include "cpu.h"
 #include "exec-all.h"
 
+#if !defined(CONFIG_USER_ONLY)
+#include "softmmu_exec.h"
+#endif /* !defined(CONFIG_USER_ONLY) */
+
 /* op_helper.c */
 void do_interrupt(CPUState *env);
 
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index 4ece01b..cac6cad 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -420,21 +420,32 @@ static inline int ultrasparc_tag_match(SparcTLBEntry *tlb,
 
 static int get_physical_address_data(CPUState *env,
                                      target_phys_addr_t *physical, int *prot,
-                                     target_ulong address, int rw, int is_user)
+                                     target_ulong address, int rw, int mmu_idx)
 {
     unsigned int i;
     uint64_t context;
 
+    int is_user = (mmu_idx == MMU_USER_IDX ||
+                   mmu_idx == MMU_USER_SECONDARY_IDX);
+
     if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
         *physical = ultrasparc_truncate_physical(address);
         *prot = PAGE_READ | PAGE_WRITE;
         return 0;
     }
 
-    if (env->tl == 0) {
+    switch(mmu_idx) {
+    case MMU_USER_IDX:
+    case MMU_KERNEL_IDX:
         context = env->dmmu.mmu_primary_context & 0x1fff;
-    } else {
+        break;
+    case MMU_USER_SECONDARY_IDX:
+    case MMU_KERNEL_SECONDARY_IDX:
+        context = env->dmmu.mmu_secondary_context & 0x1fff;
+        break;
+    case MMU_NUCLEUS_IDX:
         context = 0;
+        break;
     }
 
     for (i = 0; i < 64; i++) {
@@ -482,11 +493,14 @@ static int get_physical_address_data(CPUState *env,
 
 static int get_physical_address_code(CPUState *env,
                                      target_phys_addr_t *physical, int *prot,
-                                     target_ulong address, int is_user)
+                                     target_ulong address, int mmu_idx)
 {
     unsigned int i;
     uint64_t context;
 
+    int is_user = (mmu_idx == MMU_USER_IDX ||
+                   mmu_idx == MMU_USER_SECONDARY_IDX);
+
     if ((env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0) {
         /* IMMU disabled */
         *physical = ultrasparc_truncate_physical(address);
@@ -495,8 +509,10 @@ static int get_physical_address_code(CPUState *env,
     }
 
     if (env->tl == 0) {
+        /* PRIMARY context */
         context = env->dmmu.mmu_primary_context & 0x1fff;
     } else {
+        /* NUCLEUS context */
         context = 0;
     }
 
@@ -535,17 +551,15 @@ static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
                                 target_ulong address, int rw, int mmu_idx,
                                 target_ulong *page_size)
 {
-    int is_user = mmu_idx == MMU_USER_IDX;
-
     /* ??? We treat everything as a small page, then explicitly flush
        everything when an entry is evicted.  */
     *page_size = TARGET_PAGE_SIZE;
     if (rw == 2)
         return get_physical_address_code(env, physical, prot, address,
-                                         is_user);
+                                         mmu_idx);
     else
         return get_physical_address_data(env, physical, prot, address, rw,
-                                         is_user);
+                                         mmu_idx);
 }
 
 /* Perform address translation */
@@ -659,21 +673,27 @@ void dump_mmu(CPUState *env)
 
 
 #if !defined(CONFIG_USER_ONLY)
-target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
+target_phys_addr_t cpu_get_phys_page_nofault(CPUState *env, target_ulong addr,
+                                           int mmu_idx)
 {
     target_phys_addr_t phys_addr;
     target_ulong page_size;
     int prot, access_index;
 
     if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2,
-                             MMU_KERNEL_IDX, &page_size) != 0)
+                             mmu_idx, &page_size) != 0)
         if (get_physical_address(env, &phys_addr, &prot, &access_index, addr,
-                                 0, MMU_KERNEL_IDX, &page_size) != 0)
+                                 0, mmu_idx, &page_size) != 0)
             return -1;
     if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED)
         return -1;
     return phys_addr;
 }
+
+target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
+{
+    return cpu_get_phys_page_nofault(env, addr, MMU_KERNEL_IDX);
+}
 #endif
 
 void cpu_reset(CPUSPARCState *env)
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 245eba7..b6b08d3 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -1,9 +1,6 @@
 #include "exec.h"
 #include "host-utils.h"
 #include "helper.h"
-#if !defined(CONFIG_USER_ONLY)
-#include "softmmu_exec.h"
-#endif /* !defined(CONFIG_USER_ONLY) */
 
 //#define DEBUG_MMU
 //#define DEBUG_MXCC
@@ -2142,17 +2139,29 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
     switch (asi) {
     case 0x82: // Primary no-fault
     case 0x8a: // Primary no-fault LE
-        if (cpu_get_phys_page_debug(env, addr) == -1ULL) {
+    case 0x83: // Secondary no-fault
+    case 0x8b: // Secondary no-fault LE
+        {
+            /* secondary space access has lowest asi bit equal to 1 */
+            int access_mmu_idx = ( asi & 1 ) ? MMU_KERNEL_IDX
+                                             : MMU_KERNEL_SECONDARY_IDX;
+
+            if (cpu_get_phys_page_nofault(env, addr, access_mmu_idx) == -1ULL) {
 #ifdef DEBUG_ASI
-            dump_asi("read ", last_addr, asi, size, ret);
+                dump_asi("read ", last_addr, asi, size, ret);
 #endif
-            return 0;
+                return 0;
+            }
         }
         // Fall through
     case 0x10: // As if user primary
+    case 0x11: // As if user secondary
     case 0x18: // As if user primary LE
+    case 0x19: // As if user secondary LE
     case 0x80: // Primary
+    case 0x81: // Secondary
     case 0x88: // Primary LE
+    case 0x89: // Secondary LE
     case 0xe2: // UA2007 Primary block init
     case 0xe3: // UA2007 Secondary block init
         if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
@@ -2174,37 +2183,75 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
                     break;
                 }
             } else {
+                /* secondary space access has lowest asi bit equal to 1 */
+                if (asi & 1) {
+                    switch(size) {
+                    case 1:
+                        ret = ldub_kernel_secondary(addr);
+                        break;
+                    case 2:
+                        ret = lduw_kernel_secondary(addr);
+                        break;
+                    case 4:
+                        ret = ldl_kernel_secondary(addr);
+                        break;
+                    default:
+                    case 8:
+                        ret = ldq_kernel_secondary(addr);
+                        break;
+                    }
+                } else {
+                    switch(size) {
+                    case 1:
+                        ret = ldub_kernel(addr);
+                        break;
+                    case 2:
+                        ret = lduw_kernel(addr);
+                        break;
+                    case 4:
+                        ret = ldl_kernel(addr);
+                        break;
+                    default:
+                    case 8:
+                        ret = ldq_kernel(addr);
+                        break;
+                    }
+                }
+            }
+        } else {
+            /* secondary space access has lowest asi bit equal to 1 */
+            if (asi & 1) {
                 switch(size) {
                 case 1:
-                    ret = ldub_kernel(addr);
+                    ret = ldub_user_secondary(addr);
                     break;
                 case 2:
-                    ret = lduw_kernel(addr);
+                    ret = lduw_user_secondary(addr);
                     break;
                 case 4:
-                    ret = ldl_kernel(addr);
+                    ret = ldl_user_secondary(addr);
                     break;
                 default:
                 case 8:
-                    ret = ldq_kernel(addr);
+                    ret = ldq_user_secondary(addr);
+                    break;
+                }
+            } else {
+                switch(size) {
+                case 1:
+                    ret = ldub_user(addr);
+                    break;
+                case 2:
+                    ret = lduw_user(addr);
+                    break;
+                case 4:
+                    ret = ldl_user(addr);
+                    break;
+                default:
+                case 8:
+                    ret = ldq_user(addr);
                     break;
                 }
-            }
-        } else {
-            switch(size) {
-            case 1:
-                ret = ldub_user(addr);
-                break;
-            case 2:
-                ret = lduw_user(addr);
-                break;
-            case 4:
-                ret = ldl_user(addr);
-                break;
-            default:
-            case 8:
-                ret = ldq_user(addr);
-                break;
             }
         }
         break;
@@ -2235,22 +2282,27 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
         //  Only ldda allowed
         raise_exception(TT_ILL_INSN);
         return 0;
-    case 0x83: // Secondary no-fault
-    case 0x8b: // Secondary no-fault LE
-        if (cpu_get_phys_page_debug(env, addr) == -1ULL) {
-#ifdef DEBUG_ASI
-            dump_asi("read ", last_addr, asi, size, ret);
-#endif
-            return 0;
-        }
-        // Fall through
     case 0x04: // Nucleus
     case 0x0c: // Nucleus Little Endian (LE)
-    case 0x11: // As if user secondary
-    case 0x19: // As if user secondary LE
+    {
+        switch(size) {
+        case 1:
+            ret = ldub_nucleus(addr);
+            break;
+        case 2:
+            ret = lduw_nucleus(addr);
+            break;
+        case 4:
+            ret = ldl_nucleus(addr);
+            break;
+        default:
+        case 8:
+            ret = ldq_nucleus(addr);
+            break;
+        }
+        break;
+    }
     case 0x4a: // UPA config
-    case 0x81: // Secondary
-    case 0x89: // Secondary LE
         // XXX
         break;
     case 0x45: // LSU
@@ -2464,9 +2516,13 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
 
     switch(asi) {
     case 0x10: // As if user primary
+    case 0x11: // As if user secondary
     case 0x18: // As if user primary LE
+    case 0x19: // As if user secondary LE
     case 0x80: // Primary
+    case 0x81: // Secondary
     case 0x88: // Primary LE
+    case 0x89: // Secondary LE
     case 0xe2: // UA2007 Primary block init
     case 0xe3: // UA2007 Secondary block init
         if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
@@ -2488,37 +2544,75 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
                     break;
                 }
             } else {
+                /* secondary space access has lowest asi bit equal to 1 */
+                if (asi & 1) {
+                    switch(size) {
+                    case 1:
+                        stb_kernel_secondary(addr, val);
+                        break;
+                    case 2:
+                        stw_kernel_secondary(addr, val);
+                        break;
+                    case 4:
+                        stl_kernel_secondary(addr, val);
+                        break;
+                    case 8:
+                    default:
+                        stq_kernel_secondary(addr, val);
+                        break;
+                    }
+                } else {
+                    switch(size) {
+                    case 1:
+                        stb_kernel(addr, val);
+                        break;
+                    case 2:
+                        stw_kernel(addr, val);
+                        break;
+                    case 4:
+                        stl_kernel(addr, val);
+                        break;
+                    case 8:
+                    default:
+                        stq_kernel(addr, val);
+                        break;
+                    }
+                }
+            }
+        } else {
+            /* secondary space access has lowest asi bit equal to 1 */
+            if (asi & 1) {
                 switch(size) {
                 case 1:
-                    stb_kernel(addr, val);
+                    stb_user_secondary(addr, val);
                     break;
                 case 2:
-                    stw_kernel(addr, val);
+                    stw_user_secondary(addr, val);
                     break;
                 case 4:
-                    stl_kernel(addr, val);
+                    stl_user_secondary(addr, val);
                     break;
                 case 8:
                 default:
-                    stq_kernel(addr, val);
+                    stq_user_secondary(addr, val);
+                    break;
+                }
+            } else {
+                switch(size) {
+                case 1:
+                    stb_user(addr, val);
+                    break;
+                case 2:
+                    stw_user(addr, val);
+                    break;
+                case 4:
+                    stl_user(addr, val);
+                    break;
+                case 8:
+                default:
+                    stq_user(addr, val);
                     break;
                 }
-            }
-        } else {
-            switch(size) {
-            case 1:
-                stb_user(addr, val);
-                break;
-            case 2:
-                stw_user(addr, val);
-                break;
-            case 4:
-                stl_user(addr, val);
-                break;
-            case 8:
-            default:
-                stq_user(addr, val);
-                break;
             }
         }
         break;
@@ -2551,11 +2645,26 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
         return;
     case 0x04: // Nucleus
     case 0x0c: // Nucleus Little Endian (LE)
-    case 0x11: // As if user secondary
-    case 0x19: // As if user secondary LE
+    {
+        switch(size) {
+        case 1:
+            stb_nucleus(addr, val);
+            break;
+        case 2:
+            stw_nucleus(addr, val);
+            break;
+        case 4:
+            stl_nucleus(addr, val);
+            break;
+        default:
+        case 8:
+            stq_nucleus(addr, val);
+            break;
+        }
+        break;
+    }
+
     case 0x4a: // UPA config
-    case 0x81: // Secondary
-    case 0x89: // Secondary LE
         // XXX
         return;
     case 0x45: // LSU
commit 299b520cd4092be3c53f8380b81315c33927d9d3
Author: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Date:   Tue May 4 23:15:41 2010 +0400

    sparc64: implement global translation table entries v1
    
    - match global tte against any context
    - show global tte in MMU dump
    
    v0->v1: added default case to switch statement in demap_tlb
    - should fix gcc warning about uninitialized context variable
    
    Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 0e7f390..b705728 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -513,6 +513,24 @@ static inline void cpu_set_cwp(CPUSPARCState *env1, int new_cwp)
 /* sun4m.c, sun4u.c */
 void cpu_check_irqs(CPUSPARCState *env);
 
+#if defined (TARGET_SPARC64)
+
+static inline int compare_masked(uint64_t x, uint64_t y, uint64_t mask)
+{
+    return (x & mask) == (y & mask);
+}
+
+#define MMU_CONTEXT_BITS 13
+#define MMU_CONTEXT_MASK ((1 << MMU_CONTEXT_BITS) - 1)
+
+static inline int tlb_compare_context(const SparcTLBEntry *tlb,
+                                      uint64_t context)
+{
+    return compare_masked(context, tlb->tag, MMU_CONTEXT_MASK);
+}
+
+#endif
+
 static inline void PUT_PSR(CPUSPARCState *env1, target_ulong val)
 {
     env1->psr = val & PSR_ICC;
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index 1f0f7d4..4ece01b 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -381,17 +381,11 @@ static inline target_phys_addr_t ultrasparc_truncate_physical(uint64_t x)
  * UltraSparc IIi I/DMMUs
  */
 
-static inline int compare_masked(uint64_t x, uint64_t y, uint64_t mask)
-{
-    return (x & mask) == (y & mask);
-}
-
 // Returns true if TTE tag is valid and matches virtual address value in context
 // requires virtual address mask value calculated from TTE entry size
 static inline int ultrasparc_tag_match(SparcTLBEntry *tlb,
                                        uint64_t address, uint64_t context,
-                                       target_phys_addr_t *physical,
-                                       int is_nucleus)
+                                       target_phys_addr_t *physical)
 {
     uint64_t mask;
 
@@ -413,8 +407,7 @@ static inline int ultrasparc_tag_match(SparcTLBEntry *tlb,
 
     // valid, context match, virtual address match?
     if (TTE_IS_VALID(tlb->tte) &&
-        ((is_nucleus && compare_masked(0, tlb->tag, 0x1fff))
-         || TTE_IS_GLOBAL(tlb->tte) || compare_masked(context, tlb->tag, 0x1fff))
+        (TTE_IS_GLOBAL(tlb->tte) || tlb_compare_context(tlb, context))
         && compare_masked(address, tlb->tag, mask))
     {
         // decode physical address
@@ -431,7 +424,6 @@ static int get_physical_address_data(CPUState *env,
 {
     unsigned int i;
     uint64_t context;
-    int is_nucleus;
 
     if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
         *physical = ultrasparc_truncate_physical(address);
@@ -439,14 +431,16 @@ static int get_physical_address_data(CPUState *env,
         return 0;
     }
 
-    context = env->dmmu.mmu_primary_context & 0x1fff;
-    is_nucleus = env->tl > 0;
+    if (env->tl == 0) {
+        context = env->dmmu.mmu_primary_context & 0x1fff;
+    } else {
+        context = 0;
+    }
 
     for (i = 0; i < 64; i++) {
         // ctx match, vaddr match, valid?
         if (ultrasparc_tag_match(&env->dtlb[i],
-                                 address, context, physical,
-                                 is_nucleus)) {
+                                 address, context, physical)) {
             // access ok?
             if (((env->dtlb[i].tte & 0x4) && is_user) ||
                 (!(env->dtlb[i].tte & 0x2) && (rw == 1))) {
@@ -492,7 +486,6 @@ static int get_physical_address_code(CPUState *env,
 {
     unsigned int i;
     uint64_t context;
-    int is_nucleus;
 
     if ((env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0) {
         /* IMMU disabled */
@@ -501,14 +494,16 @@ static int get_physical_address_code(CPUState *env,
         return 0;
     }
 
-    context = env->dmmu.mmu_primary_context & 0x1fff;
-    is_nucleus = env->tl > 0;
+    if (env->tl == 0) {
+        context = env->dmmu.mmu_primary_context & 0x1fff;
+    } else {
+        context = 0;
+    }
 
     for (i = 0; i < 64; i++) {
         // ctx match, vaddr match, valid?
         if (ultrasparc_tag_match(&env->itlb[i],
-                                 address, context, physical,
-                                 is_nucleus)) {
+                                 address, context, physical)) {
             // access ok?
             if ((env->itlb[i].tte & 0x4) && is_user) {
                 if (env->immu.sfsr) /* Fault status register */
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index b27778b..245eba7 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -129,24 +129,59 @@ static void demap_tlb(SparcTLBEntry *tlb, target_ulong demap_addr,
 {
     unsigned int i;
     target_ulong mask;
+    uint64_t context;
+
+    int is_demap_context = (demap_addr >> 6) & 1;
+
+    // demap context
+    switch ((demap_addr >> 4) & 3) {
+    case 0: // primary
+        context = env1->dmmu.mmu_primary_context;
+        break;
+    case 1: // secondary
+        context = env1->dmmu.mmu_secondary_context;
+        break;
+    case 2: // nucleus
+        context = 0;
+        break;
+    case 3: // reserved
+    default:
+        return;
+    }
 
     for (i = 0; i < 64; i++) {
         if (TTE_IS_VALID(tlb[i].tte)) {
 
-            mask = 0xffffffffffffe000ULL;
-            mask <<= 3 * ((tlb[i].tte >> 61) & 3);
+            if (is_demap_context) {
+                // will remove non-global entries matching context value
+                if (TTE_IS_GLOBAL(tlb[i].tte) ||
+                    !tlb_compare_context(&tlb[i], context)) {
+                    continue;
+                }
+            } else {
+                // demap page
+                // will remove any entry matching VA
+                mask = 0xffffffffffffe000ULL;
+                mask <<= 3 * ((tlb[i].tte >> 61) & 3);
 
-            if ((demap_addr & mask) == (tlb[i].tag & mask)) {
-                replace_tlb_entry(&tlb[i], 0, 0, env1);
+                if (!compare_masked(demap_addr, tlb[i].tag, mask)) {
+                    continue;
+                }
+
+                // entry should be global or matching context value
+                if (!TTE_IS_GLOBAL(tlb[i].tte) &&
+                    !tlb_compare_context(&tlb[i], context)) {
+                    continue;
+                }
+            }
+
+            replace_tlb_entry(&tlb[i], 0, 0, env1);
 #ifdef DEBUG_MMU
-                DPRINTF_MMU("%s demap invalidated entry [%02u]\n", strmmu, i);
-                dump_mmu(env1);
+            DPRINTF_MMU("%s demap invalidated entry [%02u]\n", strmmu, i);
+            dump_mmu(env1);
 #endif
-            }
-            //return;
         }
     }
-
 }
 
 static void replace_tlb_1bit_lru(SparcTLBEntry *tlb,
commit 788686ec59bb8277ff70ae3853a0720c8b2b865d
Author: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Date:   Mon May 3 11:29:34 2010 +0400

    sparc64: more ultrasparc asi extensions for disassembler
    
    Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/sparc-dis.c b/sparc-dis.c
index 611e74f..cdd337a 100644
--- a/sparc-dis.c
+++ b/sparc-dis.c
@@ -2153,6 +2153,28 @@ static const arg asi_table_v9[] =
   { 0x8a, "#ASI_PRIMARY_NOFAULT_LITTLE" },
   { 0x8b, "#ASI_SECONDARY_NOFAULT_LITTLE" },
   /* These are UltraSPARC extensions.  */
+  { 0x14, "#ASI_PHYS_USE_EC"},
+  { 0x15, "#ASI_PHYS_BYPASS_EC_WITH_EBIT"},
+  { 0x45, "#ASI_LSU_CONTROL_REG"},
+  { 0x47, "#ASI_DCACHE_TAG"},
+  { 0x4a, "#ASI_UPA_CONFIG_REG"},
+  { 0x50, "#ASI_IMMU" },
+  { 0x51, "#ASI_IMMU_TSB_8KB_PTR_REG" },
+  { 0x52, "#ASI_IMMU_TSB_64KB_PTR_REG" },
+  /*{ 0x53, "#reserved?" },*/
+  { 0x54, "#ASI_ITLB_DATA_IN_REG" },
+  { 0x55, "#ASI_ITLB_DATA_ACCESS_REG" },
+  { 0x56, "#ASI_ITLB_TAG_READ_REG" },
+  { 0x57, "#ASI_IMMU_DEMAP" },
+  { 0x58, "#ASI_DMMU" },
+  { 0x59, "#ASI_DMMU_TSB_8KB_PTR_REG" },
+  { 0x5a, "#ASI_DMMU_TSB_64KB_PTR_REG" },
+  { 0x5b, "#ASI_DMMU_TSB_DIRECT_PTR_REG" },
+  { 0x5c, "#ASI_DTLB_DATA_IN_REG" },
+  { 0x5d, "#ASI_DTLB_DATA_ACCESS_REG" },
+  { 0x5e, "#ASI_DTLB_TAG_READ_REG" },
+  { 0x5f, "#ASI_DMMU_DEMAP" },
+  { 0x67, "#ASI_IC_TAG"},
   /* FIXME: There are dozens of them.  Not sure we want them all.
      Most are for kernel building but some are for vis type stuff.  */
   { 0, NULL }
commit 733f0b02c80c3a7106d8327a83948ab68db10ea7
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Tue Apr 6 14:18:19 2010 +0300

    qemu: address todo comment in exec.c
    
    exec.c has a comment 'XXX: optimize' for lduw_phys/stw_phys,
    so let's do it, along the lines of stl_phys.
    
    The reason to address 16 bit accesses specifically is that virtio relies
    on these accesses to be done atomically, using memset as we do now
    breaks this assumption, which is reported to cause qemu with kvm
    to read wrong index values under stress.
    
    https://bugzilla.redhat.com/show_bug.cgi?id=525323
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/exec.c b/exec.c
index cddaf36..e980788 100644
--- a/exec.c
+++ b/exec.c
@@ -3715,12 +3715,36 @@ uint32_t ldub_phys(target_phys_addr_t addr)
     return val;
 }
 
-/* XXX: optimize */
+/* warning: addr must be aligned */
 uint32_t lduw_phys(target_phys_addr_t addr)
 {
-    uint16_t val;
-    cpu_physical_memory_read(addr, (uint8_t *)&val, 2);
-    return tswap16(val);
+    int io_index;
+    uint8_t *ptr;
+    uint64_t val;
+    unsigned long pd;
+    PhysPageDesc *p;
+
+    p = phys_page_find(addr >> TARGET_PAGE_BITS);
+    if (!p) {
+        pd = IO_MEM_UNASSIGNED;
+    } else {
+        pd = p->phys_offset;
+    }
+
+    if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
+        !(pd & IO_MEM_ROMD)) {
+        /* I/O case */
+        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
+        if (p)
+            addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
+        val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr);
+    } else {
+        /* RAM case */
+        ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
+            (addr & ~TARGET_PAGE_MASK);
+        val = lduw_p(ptr);
+    }
+    return val;
 }
 
 /* warning: addr must be aligned. The ram page is not masked as dirty
@@ -3837,11 +3861,40 @@ void stb_phys(target_phys_addr_t addr, uint32_t val)
     cpu_physical_memory_write(addr, &v, 1);
 }
 
-/* XXX: optimize */
+/* warning: addr must be aligned */
 void stw_phys(target_phys_addr_t addr, uint32_t val)
 {
-    uint16_t v = tswap16(val);
-    cpu_physical_memory_write(addr, (const uint8_t *)&v, 2);
+    int io_index;
+    uint8_t *ptr;
+    unsigned long pd;
+    PhysPageDesc *p;
+
+    p = phys_page_find(addr >> TARGET_PAGE_BITS);
+    if (!p) {
+        pd = IO_MEM_UNASSIGNED;
+    } else {
+        pd = p->phys_offset;
+    }
+
+    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
+        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
+        if (p)
+            addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
+        io_mem_write[io_index][1](io_mem_opaque[io_index], addr, val);
+    } else {
+        unsigned long addr1;
+        addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
+        /* RAM case */
+        ptr = qemu_get_ram_ptr(addr1);
+        stw_p(ptr, val);
+        if (!cpu_physical_memory_is_dirty(addr1)) {
+            /* invalidate code */
+            tb_invalidate_phys_page_range(addr1, addr1 + 2, 0);
+            /* set dirty bit */
+            cpu_physical_memory_set_dirty_flags(addr1,
+                (0xff & ~CODE_DIRTY_FLAG));
+        }
+    }
 }
 
 /* XXX: optimize */
commit 3e0650a9c95f343ca5da2b89dc4ad1cd67c2c2d7
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Mar 29 10:54:42 2010 -0700

    Fix zero-length write(2).
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/exec.c b/exec.c
index 95b92f7..cddaf36 100644
--- a/exec.c
+++ b/exec.c
@@ -2429,6 +2429,9 @@ int page_check_range(target_ulong start, target_ulong len, int flags)
     assert(start < ((abi_ulong)1 << L1_MAP_ADDR_SPACE_BITS));
 #endif
 
+    if (len == 0) {
+        return 0;
+    }
     if (start + len - 1 < start) {
         /* We've wrapped around.  */
         return -1;
commit c581deda322080e8beb88b2e468d4af54454e4b3
Author: Paul Brook <paul at codesourcery.com>
Date:   Wed May 5 16:32:59 2010 +0100

    Better default guest_base
    
    Avoid loading linux-user applications in address space already used/reserved
    by the host.
    
    Signed-off-by: Paul Brook <paul at codesourcery.com>

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 13f63cf..4ef77bc 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1666,19 +1666,80 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
      */
     if (!have_guest_base) {
         /*
-         * Go through ELF program header table and find out whether
-	 * any of the segments drop below our current mmap_min_addr and
-         * in that case set guest_base to corresponding address.
-         */
+         * Go through ELF program header table and find the address
+         * range used by loadable segments.  Check that this is available on
+         * the host, and if not find a suitable value for guest_base.  */
+        abi_ulong app_start = ~0;
+        abi_ulong app_end = 0;
+        abi_ulong addr;
+        unsigned long host_start;
+        unsigned long real_start;
+        unsigned long host_size;
         for (i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum;
             i++, elf_ppnt++) {
             if (elf_ppnt->p_type != PT_LOAD)
                 continue;
-            if (HOST_PAGE_ALIGN(elf_ppnt->p_vaddr) < mmap_min_addr) {
-                guest_base = HOST_PAGE_ALIGN(mmap_min_addr);
+            addr = elf_ppnt->p_vaddr;
+            if (addr < app_start) {
+                app_start = addr;
+            }
+            addr += elf_ppnt->p_memsz;
+            if (addr > app_end) {
+                app_end = addr;
+            }
+        }
+
+        /* If we don't have any loadable segments then something
+           is very wrong.  */
+        assert(app_start < app_end);
+
+        /* Round addresses to page boundaries.  */
+        app_start = app_start & qemu_host_page_mask;
+        app_end = HOST_PAGE_ALIGN(app_end);
+        if (app_start < mmap_min_addr) {
+            host_start = HOST_PAGE_ALIGN(mmap_min_addr);
+        } else {
+            host_start = app_start;
+            if (host_start != app_start) {
+                fprintf(stderr, "qemu: Address overflow loading ELF binary\n");
+                abort();
+            }
+        }
+        host_size = app_end - app_start;
+        while (1) {
+            /* Do not use mmap_find_vma here because that is limited to the
+               guest address space.  We are going to make the
+               guest address space fit whatever we're given.  */
+            real_start = (unsigned long)mmap((void *)host_start, host_size,
+                PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, -1, 0);
+            if (real_start == (unsigned long)-1) {
+                fprintf(stderr, "qemu: Virtual memory exausted\n");
+                abort();
+            }
+            if (real_start == host_start) {
                 break;
             }
+            /* That address didn't work.  Unmap and try a different one.
+               The address the host picked because is typically
+               right at the top of the host address space and leaves the
+               guest with no usable address space.  Resort to a linear search.
+               We already compensated for mmap_min_addr, so this should not
+               happen often.  Probably means we got unlucky and host address
+               space randomization put a shared library somewhere
+               inconvenient.  */
+            munmap((void *)real_start, host_size);
+            host_start += qemu_host_page_size;
+            if (host_start == app_start) {
+                /* Theoretically possible if host doesn't have any
+                   suitably aligned areas.  Normally the first mmap will
+                   fail.  */
+                fprintf(stderr, "qemu: Unable to find space for application\n");
+                abort();
+            }
         }
+        qemu_log("Relocating guest address space from 0x" TARGET_ABI_FMT_lx
+                 " to 0x%lx\n", app_start, real_start);
+        guest_base = real_start - app_start;
     }
 #endif /* CONFIG_USE_GUEST_BASE */
 
commit 2e9a5713f0567fffaa3518f495b8d16a2b74f84a
Author: Paul Brook <paul at codesourcery.com>
Date:   Wed May 5 16:32:59 2010 +0100

    Remove PAGE_RESERVED
    
    The usermode PAGE_RESERVED code is not required by the current mmap
    implementation, and is already broken when guest_base != 0.
    Unfortunately the bsd emulation still uses the old mmap implementation,
    so we can't rip it out altogether.
    
    Signed-off-by: Paul Brook <paul at codesourcery.com>

diff --git a/cpu-all.h b/cpu-all.h
index 7b1594c..52a1817 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -742,7 +742,10 @@ extern unsigned long qemu_host_page_mask;
 /* original state of the write flag (used when tracking self-modifying
    code */
 #define PAGE_WRITE_ORG 0x0010
+#if defined(CONFIG_BSD) && defined(CONFIG_USER_ONLY)
+/* FIXME: Code that sets/uses this is broken and needs to go away.  */
 #define PAGE_RESERVED  0x0020
+#endif
 
 #if defined(CONFIG_USER_ONLY)
 void page_dump(FILE *f);
diff --git a/exec.c b/exec.c
index 14d1fd7..95b92f7 100644
--- a/exec.c
+++ b/exec.c
@@ -288,7 +288,7 @@ static void page_init(void)
         qemu_host_page_bits++;
     qemu_host_page_mask = ~(qemu_host_page_size - 1);
 
-#if !defined(_WIN32) && defined(CONFIG_USER_ONLY)
+#if defined(CONFIG_BSD) && defined(CONFIG_USER_ONLY)
     {
 #ifdef HAVE_KINFO_GETVMMAP
         struct kinfo_vmentry *freep;
@@ -324,11 +324,7 @@ static void page_init(void)
 
         last_brk = (unsigned long)sbrk(0);
 
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
         f = fopen("/compat/linux/proc/self/maps", "r");
-#else
-        f = fopen("/proc/self/maps", "r");
-#endif
         if (f) {
             mmap_lock();
 
@@ -365,24 +361,11 @@ static PageDesc *page_find_alloc(tb_page_addr_t index, int alloc)
     int i;
 
 #if defined(CONFIG_USER_ONLY)
-    /* We can't use qemu_malloc because it may recurse into a locked mutex.
-       Neither can we record the new pages we reserve while allocating a
-       given page because that may recurse into an unallocated page table
-       entry.  Stuff the allocations we do make into a queue and process
-       them after having completed one entire page table allocation.  */
-
-    unsigned long reserve[2 * (V_L1_SHIFT / L2_BITS)];
-    int reserve_idx = 0;
-
+    /* We can't use qemu_malloc because it may recurse into a locked mutex. */
 # define ALLOC(P, SIZE)                                 \
     do {                                                \
         P = mmap(NULL, SIZE, PROT_READ | PROT_WRITE,    \
                  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);   \
-        if (h2g_valid(P)) {                             \
-            reserve[reserve_idx] = h2g(P);              \
-            reserve[reserve_idx + 1] = SIZE;            \
-            reserve_idx += 2;                           \
-        }                                               \
     } while (0)
 #else
 # define ALLOC(P, SIZE) \
@@ -417,16 +400,6 @@ static PageDesc *page_find_alloc(tb_page_addr_t index, int alloc)
     }
 
 #undef ALLOC
-#if defined(CONFIG_USER_ONLY)
-    for (i = 0; i < reserve_idx; i += 2) {
-        unsigned long addr = reserve[i];
-        unsigned long len = reserve[i + 1];
-
-        page_set_flags(addr & TARGET_PAGE_MASK,
-                       TARGET_PAGE_ALIGN(addr + len),
-                       PAGE_RESERVED);
-    }
-#endif
 
     return pd + (index & (L2_SIZE - 1));
 }
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 4d3dd89..13f63cf 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -2159,12 +2159,6 @@ static int vma_walker(void *priv, abi_ulong start, abi_ulong end,
 {
     struct mm_struct *mm = (struct mm_struct *)priv;
 
-    /*
-     * Don't dump anything that qemu has reserved for internal use.
-     */
-    if (flags & PAGE_RESERVED)
-        return (0);
-
     vma_add_mapping(mm, start, end, flags);
     return (0);
 }
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 46923c7..9c062e7 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -85,14 +85,6 @@ void *qemu_vmalloc(size_t size)
     /* Use map and mark the pages as used.  */
     p = mmap(NULL, size, PROT_READ | PROT_WRITE,
              MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-
-    if (h2g_valid(p)) {
-        /* Allocated region overlaps guest address space. This may recurse.  */
-        abi_ulong addr = h2g(p);
-        page_set_flags(addr & TARGET_PAGE_MASK, TARGET_PAGE_ALIGN(addr + size),
-                       PAGE_RESERVED);
-    }
-
     mmap_unlock();
     return p;
 }
@@ -484,9 +476,6 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
         }
         start = h2g(host_start);
     } else {
-        int flg;
-        target_ulong addr;
-
         if (start & ~TARGET_PAGE_MASK) {
             errno = EINVAL;
             goto fail;
@@ -504,14 +493,6 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
             goto fail;
         }
 
-        for(addr = real_start; addr < real_end; addr += TARGET_PAGE_SIZE) {
-            flg = page_get_flags(addr);
-            if (flg & PAGE_RESERVED) {
-                errno = ENXIO;
-                goto fail;
-            }
-        }
-
         /* worst case: we cannot map the file because the offset is not
            aligned, so we read it */
         if (!(flags & MAP_ANONYMOUS) &&
commit 048d179f20c1499c7f55957df125392de664b6a7
Author: Paul Brook <paul at codesourcery.com>
Date:   Wed May 5 16:32:59 2010 +0100

    Avoid libaio for usermode
    
    Linux AIO is aonly used by system emulation, so should not be linked into
    the userspace emulatior.
    
    Signed-off-by: Paul Brook <paul at codesourcery.com>

diff --git a/configure b/configure
index 87942f4..36d028f 100755
--- a/configure
+++ b/configure
@@ -1579,7 +1579,8 @@ int main(void) { io_setup(0, NULL); io_set_eventfd(NULL, 0); eventfd(0, 0); retu
 EOF
   if compile_prog "" "-laio" ; then
     linux_aio=yes
-    LIBS="$LIBS -laio"
+    libs_softmmu="$libs_softmmu -laio"
+    libs_tools="$libs_tools -laio"
   else
     if test "$linux_aio" = "yes" ; then
       feature_not_found "linux AIO"
commit a73b1fd9afe937d70be82a0b3994c8844c072085
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Apr 28 16:07:57 2010 -0700

    Enable -d cpu logging by default.
    
    When -d cpu logging was handled by target-foo/translate.c,
    it was controled by DEBUG_DISAS, which is enabled by default.
    Use the same condition in cpu_exec.
    
    At the same time, reduce the if-deffery by assuming no flags
    update is required for the target.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/cpu-exec.c b/cpu-exec.c
index 0f84857..dc81e79 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -546,40 +546,24 @@ int cpu_exec(CPUState *env1)
                     env->exception_index = EXCP_INTERRUPT;
                     cpu_loop_exit();
                 }
-#ifdef CONFIG_DEBUG_EXEC
+#if defined(DEBUG_DISAS) || defined(CONFIG_DEBUG_EXEC)
                 if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
                     /* restore flags in standard format */
 #if defined(TARGET_I386)
                     env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
                     log_cpu_state(env, X86_DUMP_CCOP);
                     env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
-#elif defined(TARGET_ARM)
-                    log_cpu_state(env, 0);
-#elif defined(TARGET_SPARC)
-                    log_cpu_state(env, 0);
-#elif defined(TARGET_PPC)
-                    log_cpu_state(env, 0);
 #elif defined(TARGET_M68K)
                     cpu_m68k_flush_flags(env, env->cc_op);
                     env->cc_op = CC_OP_FLAGS;
                     env->sr = (env->sr & 0xffe0)
                               | env->cc_dest | (env->cc_x << 4);
                     log_cpu_state(env, 0);
-#elif defined(TARGET_MICROBLAZE)
-                    log_cpu_state(env, 0);
-#elif defined(TARGET_MIPS)
-                    log_cpu_state(env, 0);
-#elif defined(TARGET_SH4)
-		    log_cpu_state(env, 0);
-#elif defined(TARGET_ALPHA)
-                    log_cpu_state(env, 0);
-#elif defined(TARGET_CRIS)
-                    log_cpu_state(env, 0);
 #else
-#error unsupported target CPU
+                    log_cpu_state(env, 0);
 #endif
                 }
-#endif
+#endif /* DEBUG_DISAS || CONFIG_DEBUG_EXEC */
                 spin_lock(&tb_lock);
                 tb = tb_find_fast();
                 /* Note: we do it here to avoid a gcc bug on Mac OS X when
commit 6f0f607f96f4af5ed54391b960686c557f8738d6
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Apr 5 15:58:20 2010 -0700

    target-sh4: Remove duplicate CPU log.
    
    Logging for -d cpu is done in generic code.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index 3537f8c..d0d6c00 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -1916,12 +1916,6 @@ gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb,
     ctx.features = env->features;
     ctx.has_movcal = (tb->flags & TB_FLAG_PENDING_MOVCA);
 
-#ifdef DEBUG_DISAS
-    qemu_log_mask(CPU_LOG_TB_CPU,
-                 "------------------------------------------------\n");
-    log_cpu_state_mask(CPU_LOG_TB_CPU, env, 0);
-#endif
-
     ii = -1;
     num_insns = 0;
     max_insns = tb->cflags & CF_COUNT_MASK;
commit 8d0d2eb6b213953a120de1b5a53b5801ada118a4
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Apr 5 15:57:41 2010 -0700

    target-ppc: Remove duplicate cpu log.
    
    Logging for -d cpu is done in generic code.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 3d9d5ee..86cca51 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -9109,8 +9109,6 @@ static inline void gen_intermediate_code_internal(CPUState *env,
         tb->icount = num_insns;
     }
 #if defined(DEBUG_DISAS)
-    qemu_log_mask(CPU_LOG_TB_CPU, "---------------- excp: %04x\n", ctx.exception);
-    log_cpu_state_mask(CPU_LOG_TB_CPU, env, 0);
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
         int flags;
         flags = env->bfd_mach;
commit 564856bb97bdcf70d7bcd22260c26944a3c4e1c2
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Apr 5 15:56:51 2010 -0700

    target-mips: Remove duplicate CPU log.
    
    Logging for -d cpu is done in generic code.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-mips/translate.c b/target-mips/translate.c
index 7cb539d..c95ecb1 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -9426,11 +9426,6 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
     max_insns = tb->cflags & CF_COUNT_MASK;
     if (max_insns == 0)
         max_insns = CF_COUNT_MASK;
-#ifdef DEBUG_DISAS
-    qemu_log_mask(CPU_LOG_TB_CPU, "------------------------------------------------\n");
-    /* FIXME: This may print out stale hflags from env... */
-    log_cpu_state_mask(CPU_LOG_TB_CPU, env, 0);
-#endif
     LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
     gen_icount_start();
     while (ctx.bstate == BS_NONE) {
@@ -9544,7 +9539,6 @@ done_generating:
         log_target_disas(pc_start, ctx.pc - pc_start, 0);
         qemu_log("\n");
     }
-    qemu_log_mask(CPU_LOG_TB_CPU, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
 #endif
 }
 
commit 6e9cc3ed0eb103f4d0d064edf0d05b10330f298e
Author: Richard Henderson <rth at twiddle.net>
Date:   Sun Apr 4 11:40:44 2010 -0700

    target-i386: Remove duplicate CPU log.
    
    The proper logging for -d cpu is done in generic code.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 6311b68..38c6016 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -7891,7 +7891,6 @@ static inline void gen_intermediate_code_internal(CPUState *env,
     }
 
 #ifdef DEBUG_DISAS
-    log_cpu_state_mask(CPU_LOG_TB_CPU, env, X86_DUMP_CCOP);
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
         int disas_flags;
         qemu_log("----------------\n");


More information about the Spice-commits mailing list