[Spice-commits] 91 commits - MAINTAINERS Makefile Makefile.objs QMP/README QMP/qmp-shell QMP/qmp.py QMP/vm-info alpha-dis.c arch_init.c arm-dis.c audio/audio_pt_int.c block-migration.c block/qcow.c block/qcow2.h block/raw-posix.c block/vdi.c block/vmdk.c block/vpc.c blockdev.c blockdev.h buffered_file.c cpu-common.h cpu-exec.c darwin-user/machload.c darwin-user/qemu.h dis-asm.h exec.c hmp-commands.hx hw/cirrus_vga.c hw/e1000.c hw/eepro100.c hw/hw.h hw/ide hw/ioh3420.c hw/lsi53c895a.c hw/openpic.c hw/pci.c hw/pci.h hw/pci_bridge.c hw/pcie.h hw/pcie_aer.c hw/pcie_aer.h hw/pcie_port.c hw/pcie_regs.h hw/qdev.c hw/qdev.h hw/scsi-bus.c hw/scsi-defs.h hw/scsi-disk.c hw/scsi-generic.c hw/scsi.h hw/usb-ohci.c hw/vhost.c hw/virtio.c hw/xen_disk.c hw/xio3130_downstream.c hw/xio3130_upstream.c kvm-all.c linux-user/main.c linux-user/mips linux-user/mmap.c linux-user/ppc linux-user/qemu.h linux-user/signal.c linux-user/syscall.c linux-user/syscall_defs.h m68k-dis.c microblaze-dis.c migration.c mi ps-dis.c monitor.c pc-bios/README pc-bios/gpxe-eepro100-80861229.rom qemu-binfmt-conf.sh qemu-char.c qemu-char.h qemu-common.h qemu-lock.h qmp-commands.hx savevm.c sh4-dis.c target-arm/cpu.h target-arm/helper.c target-arm/op_helper.c target-ppc/kvm.c target-sparc/cpu.h target-sparc/helper.c tcg/ia64 tcg/tcg-op.h vl.c

Gerd Hoffmann kraxel at kemper.freedesktop.org
Thu Dec 9 02:21:47 PST 2010


 MAINTAINERS                  |  494 ++++++++++++++++++++++----
 Makefile                     |    1 
 Makefile.objs                |    2 
 QMP/README                   |    5 
 QMP/qmp-shell                |  254 +++++++++++--
 QMP/qmp.py                   |  157 +++++---
 QMP/vm-info                  |   33 -
 alpha-dis.c                  |    3 
 arch_init.c                  |   35 +
 arm-dis.c                    |   14 
 audio/audio_pt_int.c         |    3 
 block-migration.c            |   14 
 block/qcow.c                 |    1 
 block/qcow2.h                |    1 
 block/raw-posix.c            |    2 
 block/vdi.c                  |    1 
 block/vmdk.c                 |    1 
 block/vpc.c                  |    2 
 blockdev.c                   |   39 ++
 blockdev.h                   |    3 
 buffered_file.c              |    9 
 cpu-common.h                 |    3 
 cpu-exec.c                   |    6 
 darwin-user/machload.c       |    2 
 darwin-user/qemu.h           |    2 
 dev/null                     |binary
 dis-asm.h                    |   10 
 exec.c                       |   23 +
 hmp-commands.hx              |   18 
 hw/cirrus_vga.c              |    4 
 hw/e1000.c                   |    4 
 hw/eepro100.c                |   14 
 hw/hw.h                      |    8 
 hw/ide/cmd646.c              |    8 
 hw/ide/core.c                |   31 -
 hw/ide/internal.h            |    2 
 hw/ide/pci.c                 |  131 ++----
 hw/ide/pci.h                 |    7 
 hw/ide/piix.c                |    8 
 hw/ide/via.c                 |   10 
 hw/ioh3420.c                 |   80 +++-
 hw/lsi53c895a.c              |    7 
 hw/openpic.c                 |    2 
 hw/pci.c                     |  174 ++++++++-
 hw/pci.h                     |    1 
 hw/pci_bridge.c              |   11 
 hw/pcie.h                    |   14 
 hw/pcie_aer.c                |  815 +++++++++++++++++++++++++++++++++++++++++++
 hw/pcie_aer.h                |  106 +++++
 hw/pcie_port.c               |    8 
 hw/pcie_regs.h               |    2 
 hw/qdev.c                    |   87 ++++
 hw/qdev.h                    |   18 
 hw/scsi-bus.c                |   12 
 hw/scsi-defs.h               |   20 -
 hw/scsi-disk.c               |  137 +++----
 hw/scsi-generic.c            |   10 
 hw/scsi.h                    |   11 
 hw/usb-ohci.c                |    2 
 hw/vhost.c                   |    1 
 hw/virtio.c                  |   27 -
 hw/xen_disk.c                |   12 
 hw/xio3130_downstream.c      |   43 +-
 hw/xio3130_upstream.c        |   33 +
 kvm-all.c                    |    2 
 linux-user/main.c            |    4 
 linux-user/mips/syscall_nr.h |   38 +-
 linux-user/mmap.c            |    4 
 linux-user/ppc/syscall_nr.h  |   30 -
 linux-user/qemu.h            |    8 
 linux-user/signal.c          |  156 ++++++++
 linux-user/syscall.c         |   85 +++-
 linux-user/syscall_defs.h    |    2 
 m68k-dis.c                   |    2 
 microblaze-dis.c             |    2 
 migration.c                  |    6 
 mips-dis.c                   |    2 
 monitor.c                    |   38 ++
 pc-bios/README               |    2 
 qemu-binfmt-conf.sh          |    8 
 qemu-char.c                  |   64 +++
 qemu-char.h                  |    7 
 qemu-common.h                |    3 
 qemu-lock.h                  |   10 
 qmp-commands.hx              |   45 ++
 savevm.c                     |    4 
 sh4-dis.c                    |   16 
 target-arm/cpu.h             |    6 
 target-arm/helper.c          |   16 
 target-arm/op_helper.c       |   14 
 target-ppc/kvm.c             |    2 
 target-sparc/cpu.h           |    6 
 target-sparc/helper.c        |   14 
 tcg/ia64/tcg-target.c        |   13 
 tcg/tcg-op.h                 |    4 
 vl.c                         |    1 
 96 files changed, 2911 insertions(+), 701 deletions(-)

New commits:
commit 138b38b61bf92d4e9588acf934e532499c94e185
Author: Alexander Graf <agraf at suse.de>
Date:   Thu Nov 25 08:20:46 2010 +0100

    ppc: kvm: fix signedness warning
    
    I get a warning on a signed comparison with an unsigned variable, so
    let's make the variable signed and be happy.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Edgar E. Iglesias <edgar at axis.com>

diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 5cacef7..5caa07c 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -132,7 +132,7 @@ int kvm_arch_get_registers(CPUState *env)
 {
     struct kvm_regs regs;
     struct kvm_sregs sregs;
-    uint32_t i, ret;
+    int i, ret;
 
     ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, &regs);
     if (ret < 0)
commit 2c90fe2b71df2534884bce96d90cbfcc93aeedb8
Author: Kirill Batuzov <batuzovk at ispras.ru>
Date:   Thu Dec 2 16:12:46 2010 +0300

    Speedup 'tb_find_slow' by using the same heuristic as during memory page lookup
    
    Move the last found TB to the head of the list so it will be found more quickly next time it will be looked for.
    
    Signed-off-by: Kirill Batuzov <batuzovk at ispras.ru>
    Signed-off-by: Pavel Yushchenko <pau at ispras.ru>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cpu-exec.c b/cpu-exec.c
index dbdfdcc..39e5eea 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -167,6 +167,12 @@ static TranslationBlock *tb_find_slow(target_ulong pc,
     tb = tb_gen_code(env, pc, cs_base, flags, 0);
 
  found:
+    /* Move the last found TB to the head of the list */
+    if (likely(*ptb1)) {
+        *ptb1 = tb->phys_hash_next;
+        tb->phys_hash_next = tb_phys_hash[h];
+        tb_phys_hash[h] = tb;
+    }
     /* we add the TB in the virtual pc hash table */
     env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
     return tb;
commit 53016fa69c1fc7ed257272f36cb84b6623f73332
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Dec 1 19:44:38 2010 +0000

    Remove unused spin_trylock() function
    
    Remove the spin_trylock() function, as it is not used anywhere,
    and is not even implemented if CONFIG_USE_NPTL is defined.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/qemu-lock.h b/qemu-lock.h
index 9a3e6ac..65ca084 100644
--- a/qemu-lock.h
+++ b/qemu-lock.h
@@ -224,11 +224,6 @@ static inline void spin_unlock(spinlock_t *lock)
 {
     resetlock(lock);
 }
-
-static inline int spin_trylock(spinlock_t *lock)
-{
-    return !testandset(lock);
-}
 #else
 static inline void spin_lock(spinlock_t *lock)
 {
@@ -237,11 +232,6 @@ static inline void spin_lock(spinlock_t *lock)
 static inline void spin_unlock(spinlock_t *lock)
 {
 }
-
-static inline int spin_trylock(spinlock_t *lock)
-{
-    return 1;
-}
 #endif
 
 #endif
commit edcdd562baff02bb8de974c46a2b984b7d5b0da9
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Mon Nov 15 21:00:48 2010 +0100

    darwin-user: Use GCC_FMT_ATTR (format checking)
    
    The redundant forward declaration of qerror in machload.c
    is removed because it should be taken from qemu.h.
    
    Please note that this patch is untested because
    I have no matching environment to compile it.
    
    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/darwin-user/machload.c b/darwin-user/machload.c
index 4bb5c72..3bc3b65 100644
--- a/darwin-user/machload.c
+++ b/darwin-user/machload.c
@@ -82,7 +82,7 @@ void *macho_text_sect = 0;
 int   macho_offset = 0;
 
 int load_object(const char *filename, struct target_pt_regs * regs, void ** mh);
-void qerror(const char *format, ...);
+
 #ifdef TARGET_I386
 typedef struct mach_i386_thread_state {
     unsigned int    eax;
diff --git a/darwin-user/qemu.h b/darwin-user/qemu.h
index 0c5081b..b6d3e6c 100644
--- a/darwin-user/qemu.h
+++ b/darwin-user/qemu.h
@@ -100,7 +100,7 @@ int do_sigaction(int sig, const struct sigaction *act,
 int do_sigaltstack(const struct sigaltstack *ss, struct sigaltstack *oss);
 
 void gemu_log(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
-void qerror(const char *fmt, ...);
+void qerror(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
 
 void write_dt(void *ptr, unsigned long addr, unsigned long limit, int flags);
 
commit ab9de3692e34dc874ce44c7905590ef98445ce33
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Mon Nov 15 20:54:12 2010 +0100

    audio: Use GCC_FMT_ATTR (format checking)
    
    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/audio/audio_pt_int.c b/audio/audio_pt_int.c
index f15cc70..908c569 100644
--- a/audio/audio_pt_int.c
+++ b/audio/audio_pt_int.c
@@ -8,7 +8,8 @@
 
 #include <signal.h>
 
-static void logerr (struct audio_pt *pt, int err, const char *fmt, ...)
+static void GCC_FMT_ATTR(3, 4) logerr (struct audio_pt *pt, int err,
+                                       const char *fmt, ...)
 {
     va_list ap;
 
commit 047b39e47ca07cf68bdf4074031e8e41bf7de641
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Mon Nov 15 19:58:41 2010 +0100

    target-sparc: Use fprintf_function (format checking)
    
    This change was missing in commit
    9a78eead0c74333a394c0f7bbfc4423ac746fcd5.
    
    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/cpu.h b/target-sparc/cpu.h
index 3e93bbb..1be66e7 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -2,6 +2,7 @@
 #define CPU_SPARC_H
 
 #include "config.h"
+#include "qemu-common.h"
 
 #if !defined(TARGET_SPARC64)
 #define TARGET_LONG_BITS 32
@@ -442,8 +443,7 @@ typedef struct CPUSPARCState {
 /* helper.c */
 CPUSPARCState *cpu_sparc_init(const char *cpu_model);
 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu);
-void sparc_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt,
-                                                 ...));
+void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf);
 int cpu_sparc_handle_mmu_fault(CPUSPARCState *env1, target_ulong address, int rw,
                                int mmu_idx, int is_softmmu);
 #define cpu_handle_mmu_fault cpu_sparc_handle_mmu_fault
commit 6e2d864edf5ef4d75e2fec061f4cd247b4d315be
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Mon Nov 15 19:39:43 2010 +0100

    *-dis: Replace fprintf_ftype by fprintf_function (format checking)
    
    This patch adds more printf format checking.
    
    Additional modifications were needed for this code change:
    
    * alpha-dis.c: The local definition of MAX conflicts with
      a previous definition from osdep.h, so add an #undef.
    
    * dis-asm.h: Add include for fprintf_function (qemu-common.h).
      The standard (now redundant) includes are removed.
    
    * mis-dis.c: The definition of ARRAY_SIZE is no longer needed
      and must be removed (conflict with previous definition from
      qemu-common.h).
    
    * sh4-dis.c: Remove some unneeded forward declarations.
    
    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/alpha-dis.c b/alpha-dis.c
index 970da5b..8a2411e 100644
--- a/alpha-dis.c
+++ b/alpha-dis.c
@@ -22,6 +22,9 @@ along with this file; see the file COPYING.  If not, see
 #include <stdio.h>
 #include "dis-asm.h"
 
+/* MAX is redefined below, so remove any previous definition. */
+#undef MAX
+
 /* The opcode table is an array of struct alpha_opcode.  */
 
 struct alpha_opcode
diff --git a/arm-dis.c b/arm-dis.c
index fe7ac99..af21739 100644
--- a/arm-dis.c
+++ b/arm-dis.c
@@ -1587,7 +1587,7 @@ arm_decode_bitfield (const char *ptr, unsigned long insn,
 }
 
 static void
-arm_decode_shift (long given, fprintf_ftype func, void *stream,
+arm_decode_shift (long given, fprintf_function func, void *stream,
 		  int print_shift)
 {
   func (stream, "%s", arm_regnames[given & 0xf]);
@@ -1633,7 +1633,7 @@ print_insn_coprocessor (bfd_vma pc, struct disassemble_info *info, long given,
 {
   const struct opcode32 *insn;
   void *stream = info->stream;
-  fprintf_ftype func = info->fprintf_func;
+  fprintf_function func = info->fprintf_func;
   unsigned long mask;
   unsigned long value;
   int cond;
@@ -2127,7 +2127,7 @@ static void
 print_arm_address (bfd_vma pc, struct disassemble_info *info, long given)
 {
   void *stream = info->stream;
-  fprintf_ftype func = info->fprintf_func;
+  fprintf_function func = info->fprintf_func;
 
   if (((given & 0x000f0000) == 0x000f0000)
       && ((given & 0x02000000) == 0))
@@ -2222,7 +2222,7 @@ print_insn_neon (struct disassemble_info *info, long given, bfd_boolean thumb)
 {
   const struct opcode32 *insn;
   void *stream = info->stream;
-  fprintf_ftype func = info->fprintf_func;
+  fprintf_function func = info->fprintf_func;
 
   if (thumb)
     {
@@ -2676,7 +2676,7 @@ print_insn_arm_internal (bfd_vma pc, struct disassemble_info *info, long given)
 {
   const struct opcode32 *insn;
   void *stream = info->stream;
-  fprintf_ftype func = info->fprintf_func;
+  fprintf_function func = info->fprintf_func;
 
   if (print_insn_coprocessor (pc, info, given, false))
     return;
@@ -3036,7 +3036,7 @@ print_insn_thumb16 (bfd_vma pc, struct disassemble_info *info, long given)
 {
   const struct opcode16 *insn;
   void *stream = info->stream;
-  fprintf_ftype func = info->fprintf_func;
+  fprintf_function func = info->fprintf_func;
 
   for (insn = thumb_opcodes; insn->assembler; insn++)
     if ((given & insn->mask) == insn->value)
@@ -3312,7 +3312,7 @@ print_insn_thumb32 (bfd_vma pc, struct disassemble_info *info, long given)
 {
   const struct opcode32 *insn;
   void *stream = info->stream;
-  fprintf_ftype func = info->fprintf_func;
+  fprintf_function func = info->fprintf_func;
 
   if (print_insn_coprocessor (pc, info, given, true))
     return;
diff --git a/dis-asm.h b/dis-asm.h
index 9b9657e..3fb4838 100644
--- a/dis-asm.h
+++ b/dis-asm.h
@@ -9,11 +9,7 @@
 #ifndef DIS_ASM_H
 #define DIS_ASM_H
 
-#include <stdlib.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <string.h>
-#include <inttypes.h>
+#include "qemu-common.h"
 
 typedef void *PTR;
 typedef uint64_t bfd_vma;
@@ -237,8 +233,6 @@ typedef struct symbol_cache_entry
     } udata;
 } asymbol;
 
-typedef int (*fprintf_ftype) (FILE*, const char*, ...);
-
 enum dis_insn_type {
   dis_noninsn,			/* Not a valid instruction */
   dis_nonbranch,		/* Not a branch instruction */
@@ -261,7 +255,7 @@ enum dis_insn_type {
    by hand, or using one of the initialization macros below.  */
 
 typedef struct disassemble_info {
-  fprintf_ftype fprintf_func;
+  fprintf_function fprintf_func;
   FILE *stream;
   PTR application_data;
 
diff --git a/m68k-dis.c b/m68k-dis.c
index d93943e..04f837a 100644
--- a/m68k-dis.c
+++ b/m68k-dis.c
@@ -1732,7 +1732,7 @@ match_insn_m68k (bfd_vma memaddr,
   const char *d;
 
   bfd_byte *buffer = priv->the_buffer;
-  fprintf_ftype save_printer = info->fprintf_func;
+  fprintf_function save_printer = info->fprintf_func;
   void (* save_print_address) (bfd_vma, struct disassemble_info *)
     = info->print_address_func;
 
diff --git a/microblaze-dis.c b/microblaze-dis.c
index 7694a43..16c312f 100644
--- a/microblaze-dis.c
+++ b/microblaze-dis.c
@@ -789,7 +789,7 @@ read_insn_microblaze (bfd_vma memaddr,
 int 
 print_insn_microblaze (bfd_vma memaddr, struct disassemble_info * info)
 {
-  fprintf_ftype       fprintf_func = info->fprintf_func;
+  fprintf_function    fprintf_func = info->fprintf_func;
   void *              stream = info->stream;
   unsigned long       inst, prev_inst;
   struct op_code_struct * op, *pop;
diff --git a/mips-dis.c b/mips-dis.c
index 279b591..4d8e85b 100644
--- a/mips-dis.c
+++ b/mips-dis.c
@@ -3117,8 +3117,6 @@ struct mips_arch_choice
 #define bfd_mach_mipsisa64             64
 #define bfd_mach_mipsisa64r2           65
 
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
-
 static const struct mips_arch_choice mips_arch_choices[] =
 {
   { "numeric",	0, 0, 0, 0,
diff --git a/sh4-dis.c b/sh4-dis.c
index 078a6b2..673bc78 100644
--- a/sh4-dis.c
+++ b/sh4-dis.c
@@ -1163,15 +1163,9 @@ const sh_opcode_info sh_table[] =
 #define INCLUDE_SHMEDIA
 #endif
 
-static void print_movxy
-  (const sh_opcode_info *, int, int, fprintf_ftype, void *);
-static void print_insn_ddt (int, struct disassemble_info *);
-static void print_dsp_reg (int, fprintf_ftype, void *);
-static void print_insn_ppi (int, struct disassemble_info *);
-
 static void
 print_movxy (const sh_opcode_info *op, int rn, int rm,
-	     fprintf_ftype fprintf_fn, void *stream)
+             fprintf_function fprintf_fn, void *stream)
 {
   int n;
 
@@ -1247,7 +1241,7 @@ print_movxy (const sh_opcode_info *op, int rn, int rm,
 static void
 print_insn_ddt (int insn, struct disassemble_info *info)
 {
-  fprintf_ftype fprintf_fn = info->fprintf_func;
+  fprintf_function fprintf_fn = info->fprintf_func;
   void *stream = info->stream;
 
   /* If this is just a nop, make sure to emit something.  */
@@ -1332,7 +1326,7 @@ print_insn_ddt (int insn, struct disassemble_info *info)
 }
 
 static void
-print_dsp_reg (int rm, fprintf_ftype fprintf_fn, void *stream)
+print_dsp_reg (int rm, fprintf_function fprintf_fn, void *stream)
 {
   switch (rm)
     {
@@ -1377,7 +1371,7 @@ print_insn_ppi (int field_b, struct disassemble_info *info)
 {
   static const char *sx_tab[] = { "x0", "x1", "a0", "a1" };
   static const char *sy_tab[] = { "y0", "y1", "m0", "m1" };
-  fprintf_ftype fprintf_fn = info->fprintf_func;
+  fprintf_function fprintf_fn = info->fprintf_func;
   void *stream = info->stream;
   unsigned int nib1, nib2, nib3;
   unsigned int altnib1, nib4;
@@ -1520,7 +1514,7 @@ print_insn_ppi (int field_b, struct disassemble_info *info)
 int
 print_insn_sh (bfd_vma memaddr, struct disassemble_info *info)
 {
-  fprintf_ftype fprintf_fn = info->fprintf_func;
+  fprintf_function fprintf_fn = info->fprintf_func;
   void *stream = info->stream;
   unsigned char insn[4];
   unsigned char nibs[8];
commit e6e055c9d79c665de200fc46c746d403d3d943ad
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Dec 4 17:37:35 2010 +0000

    Fix mingw32 and OpenBSD warnings
    
    ffsl() is not universally available, so there are these warnings
    on both mingw32 and OpenBSD:
    /src/qemu/hw/pcie_aer.c: In function 'pcie_aer_update_log':
    /src/qemu/hw/pcie_aer.c:399: warning: implicit declaration of function 'ffsl'
    
    Since status field in PCIEAERErr is uint32_t, we can just use ffs() instead.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/pcie_aer.c b/hw/pcie_aer.c
index 235ac53..47d6400 100644
--- a/hw/pcie_aer.c
+++ b/hw/pcie_aer.c
@@ -396,7 +396,7 @@ static void pcie_aer_msg(PCIDevice *dev, const PCIEAERMsg *msg)
 static void pcie_aer_update_log(PCIDevice *dev, const PCIEAERErr *err)
 {
     uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
-    uint8_t first_bit = ffsl(err->status) - 1;
+    uint8_t first_bit = ffs(err->status) - 1;
     uint32_t errcap = pci_get_long(aer_cap + PCI_ERR_CAP);
     int i;
 
commit bcd478781ab1d11911ab5505c34b5577de904eeb
Merge: db1923d... b2e7aab...
Author: Edgar E. Iglesias <edgar at axis.com>
Date:   Sat Dec 4 04:18:28 2010 +0100

    Merge branch 'linux-user-for-upstream' of git://gitorious.org/qemu-maemo/qemu
    
    * 'linux-user-for-upstream' of git://gitorious.org/qemu-maemo/qemu:
      linux-user: fix mips and ppc to use UID16
      update binfmt conf
      linux-user: fix compiler error on nptl
      ARM: linux-user: Restore iWMMXT state from ucontext on sigreturn
      ARM: linux-user: Expose iWMMXT registers to signal handlers
      ARM: linux-user: Restore VFP state from ucontext on sigreturn
      ARM: linux-user: Expose VFP registers to signal handlers
      ARM: Expose vfp_get_fpscr() and vfp_set_fpscr() to C code
      ARM: linux-user: Correct size of padding in target_ucontext_v2
      target-sparc: remove unused functions cpu_lock(), cpu_unlock()
      ARM: enable XScale/iWMMXT in linux-user mode
      linux-user: Translate getsockopt level option
      linux-user: remove unnecessary local from __get_user(), __put_user()
      linux-user: fix memory leaks with NPTL emulation
      linux-user: mmap_reserve() not controlled by RESERVED_VA
      [PATCH] target-arm: remove unused functions cpu_lock(), cpu_unlock()

commit db1923de6099fd2d1eee0693757a639978b15e1b
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Fri Dec 3 17:09:01 2010 +0000

    exec: Remove debugging fprintf() that slipped into qemu_ram_alloc_from_ptr()
    
    Remove the debugging fprintf() slipped in via the following commit:
    
        commit b2e0a138e77245290428a7d599a929e2e1bfe510
        Author: Michael S. Tsirkin <mst at redhat.com>
        Date:   Mon Nov 22 19:52:34 2010 +0200
    
            migration: stable ram block ordering
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/exec.c b/exec.c
index 6c8f635..42a35e0 100644
--- a/exec.c
+++ b/exec.c
@@ -2858,7 +2858,6 @@ ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
     new_block->length = size;
 
     QLIST_INSERT_HEAD(&ram_list.blocks, new_block, next);
-    fprintf(stderr, "alloc ram %s len 0x%x\n", new_block->idstr, (int)new_block->length);
 
     ram_list.phys_dirty = qemu_realloc(ram_list.phys_dirty,
                                        last_ram_offset() >> TARGET_PAGE_BITS);
commit b2e7aab2502260a18c68072f6b6e4271385663c4
Author: Martin Mohring <martin.mohring at 5edatasoft.com>
Date:   Sun Nov 7 20:31:57 2010 +0100

    linux-user: fix mips and ppc to use UID16
    
    Signed-off-by: Martin Mohring <martin.mohring at 5edatasoft.com>
    Signed-off-by: Jan-Simon Möller <jsmoeller at linuxfoundation.org>
    Signed-off-by: Riku Voipio <riku.voipio at nokia.com>

diff --git a/linux-user/mips/syscall_nr.h b/linux-user/mips/syscall_nr.h
index 8228616..0595308 100644
--- a/linux-user/mips/syscall_nr.h
+++ b/linux-user/mips/syscall_nr.h
@@ -18,15 +18,15 @@
 #define TARGET_NR_time			(TARGET_NR_Linux +  13)
 #define TARGET_NR_mknod			(TARGET_NR_Linux +  14)
 #define TARGET_NR_chmod			(TARGET_NR_Linux +  15)
-#define TARGET_NR_lchown32		(TARGET_NR_Linux +  16)
+#define TARGET_NR_lchown		(TARGET_NR_Linux +  16)
 #define TARGET_NR_break			(TARGET_NR_Linux +  17)
 #define TARGET_NR_unused18		(TARGET_NR_Linux +  18)
 #define TARGET_NR_lseek			(TARGET_NR_Linux +  19)
 #define TARGET_NR_getpid		(TARGET_NR_Linux +  20)
 #define TARGET_NR_mount			(TARGET_NR_Linux +  21)
 #define TARGET_NR_umount		(TARGET_NR_Linux +  22)
-#define TARGET_NR_setuid32		(TARGET_NR_Linux +  23)
-#define TARGET_NR_getuid32		(TARGET_NR_Linux +  24)
+#define TARGET_NR_setuid		(TARGET_NR_Linux +  23)
+#define TARGET_NR_getuid		(TARGET_NR_Linux +  24)
 #define TARGET_NR_stime			(TARGET_NR_Linux +  25)
 #define TARGET_NR_ptrace		(TARGET_NR_Linux +  26)
 #define TARGET_NR_alarm			(TARGET_NR_Linux +  27)
@@ -48,11 +48,11 @@
 #define TARGET_NR_times			(TARGET_NR_Linux +  43)
 #define TARGET_NR_prof			(TARGET_NR_Linux +  44)
 #define TARGET_NR_brk			(TARGET_NR_Linux +  45)
-#define TARGET_NR_setgid32		(TARGET_NR_Linux +  46)
-#define TARGET_NR_getgid32		(TARGET_NR_Linux +  47)
+#define TARGET_NR_setgid		(TARGET_NR_Linux +  46)
+#define TARGET_NR_getgid		(TARGET_NR_Linux +  47)
 #define TARGET_NR_signal		(TARGET_NR_Linux +  48)
-#define TARGET_NR_geteuid32		(TARGET_NR_Linux +  49)
-#define TARGET_NR_getegid32		(TARGET_NR_Linux +  50)
+#define TARGET_NR_geteuid		(TARGET_NR_Linux +  49)
+#define TARGET_NR_getegid		(TARGET_NR_Linux +  50)
 #define TARGET_NR_acct			(TARGET_NR_Linux +  51)
 #define TARGET_NR_umount2		(TARGET_NR_Linux +  52)
 #define TARGET_NR_lock			(TARGET_NR_Linux +  53)
@@ -72,8 +72,8 @@
 #define TARGET_NR_sigaction		(TARGET_NR_Linux +  67)
 #define TARGET_NR_sgetmask		(TARGET_NR_Linux +  68)
 #define TARGET_NR_ssetmask		(TARGET_NR_Linux +  69)
-#define TARGET_NR_setreuid32		(TARGET_NR_Linux +  70)
-#define TARGET_NR_setregid32		(TARGET_NR_Linux +  71)
+#define TARGET_NR_setreuid		(TARGET_NR_Linux +  70)
+#define TARGET_NR_setregid		(TARGET_NR_Linux +  71)
 #define TARGET_NR_sigsuspend		(TARGET_NR_Linux +  72)
 #define TARGET_NR_sigpending		(TARGET_NR_Linux +  73)
 #define TARGET_NR_sethostname		(TARGET_NR_Linux +  74)
@@ -82,8 +82,8 @@
 #define TARGET_NR_getrusage		(TARGET_NR_Linux +  77)
 #define TARGET_NR_gettimeofday		(TARGET_NR_Linux +  78)
 #define TARGET_NR_settimeofday		(TARGET_NR_Linux +  79)
-#define TARGET_NR_getgroups32		(TARGET_NR_Linux +  80)
-#define TARGET_NR_setgroups32		(TARGET_NR_Linux +  81)
+#define TARGET_NR_getgroups		(TARGET_NR_Linux +  80)
+#define TARGET_NR_setgroups		(TARGET_NR_Linux +  81)
 #define TARGET_NR_reserved82		(TARGET_NR_Linux +  82)
 #define TARGET_NR_symlink		(TARGET_NR_Linux +  83)
 #define TARGET_NR_unused84		(TARGET_NR_Linux +  84)
@@ -97,7 +97,7 @@
 #define TARGET_NR_truncate		(TARGET_NR_Linux +  92)
 #define TARGET_NR_ftruncate		(TARGET_NR_Linux +  93)
 #define TARGET_NR_fchmod		(TARGET_NR_Linux +  94)
-#define TARGET_NR_fchown32		(TARGET_NR_Linux +  95)
+#define TARGET_NR_fchown		(TARGET_NR_Linux +  95)
 #define TARGET_NR_getpriority		(TARGET_NR_Linux +  96)
 #define TARGET_NR_setpriority		(TARGET_NR_Linux +  97)
 #define TARGET_NR_profil		(TARGET_NR_Linux +  98)
@@ -140,8 +140,8 @@
 #define TARGET_NR_sysfs			(TARGET_NR_Linux + 135)
 #define TARGET_NR_personality		(TARGET_NR_Linux + 136)
 #define TARGET_NR_afs_syscall		(TARGET_NR_Linux + 137) /* Syscall for Andrew File System */
-#define TARGET_NR_setfsuid32		(TARGET_NR_Linux + 138)
-#define TARGET_NR_setfsgid32		(TARGET_NR_Linux + 139)
+#define TARGET_NR_setfsuid		(TARGET_NR_Linux + 138)
+#define TARGET_NR_setfsgid		(TARGET_NR_Linux + 139)
 #define TARGET_NR__llseek		(TARGET_NR_Linux + 140)
 #define TARGET_NR_getdents		(TARGET_NR_Linux + 141)
 #define TARGET_NR__newselect		(TARGET_NR_Linux + 142)
@@ -187,13 +187,13 @@
 #define TARGET_NR_shutdown		(TARGET_NR_Linux + 182)
 #define TARGET_NR_socket		(TARGET_NR_Linux + 183)
 #define TARGET_NR_socketpair		(TARGET_NR_Linux + 184)
-#define TARGET_NR_setresuid32		(TARGET_NR_Linux + 185)
-#define TARGET_NR_getresuid32		(TARGET_NR_Linux + 186)
+#define TARGET_NR_setresuid		(TARGET_NR_Linux + 185)
+#define TARGET_NR_getresuid		(TARGET_NR_Linux + 186)
 #define TARGET_NR_query_module		(TARGET_NR_Linux + 187)
 #define TARGET_NR_poll			(TARGET_NR_Linux + 188)
 #define TARGET_NR_nfsservctl		(TARGET_NR_Linux + 189)
-#define TARGET_NR_setresgid32		(TARGET_NR_Linux + 190)
-#define TARGET_NR_getresgid32		(TARGET_NR_Linux + 191)
+#define TARGET_NR_setresgid		(TARGET_NR_Linux + 190)
+#define TARGET_NR_getresgid		(TARGET_NR_Linux + 191)
 #define TARGET_NR_prctl			(TARGET_NR_Linux + 192)
 #define TARGET_NR_rt_sigreturn		(TARGET_NR_Linux + 193)
 #define TARGET_NR_rt_sigaction		(TARGET_NR_Linux + 194)
@@ -204,7 +204,7 @@
 #define TARGET_NR_rt_sigsuspend		(TARGET_NR_Linux + 199)
 #define TARGET_NR_pread64		(TARGET_NR_Linux + 200)
 #define TARGET_NR_pwrite64		(TARGET_NR_Linux + 201)
-#define TARGET_NR_chown32		(TARGET_NR_Linux + 202)
+#define TARGET_NR_chown 		(TARGET_NR_Linux + 202)
 #define TARGET_NR_getcwd		(TARGET_NR_Linux + 203)
 #define TARGET_NR_capget		(TARGET_NR_Linux + 204)
 #define TARGET_NR_capset		(TARGET_NR_Linux + 205)
diff --git a/linux-user/ppc/syscall_nr.h b/linux-user/ppc/syscall_nr.h
index f54276b..cc84a4c 100644
--- a/linux-user/ppc/syscall_nr.h
+++ b/linux-user/ppc/syscall_nr.h
@@ -17,15 +17,15 @@
 #define TARGET_NR_time                    13
 #define TARGET_NR_mknod                   14
 #define TARGET_NR_chmod                   15
-#define TARGET_NR_lchown32                16
+#define TARGET_NR_lchown                  16
 #define TARGET_NR_break                   17
 #define TARGET_NR_oldstat                 18
 #define TARGET_NR_lseek                   19
 #define TARGET_NR_getpid                  20
 #define TARGET_NR_mount                   21
 #define TARGET_NR_umount                  22
-#define TARGET_NR_setuid32                23
-#define TARGET_NR_getuid32                24
+#define TARGET_NR_setuid                  23
+#define TARGET_NR_getuid                  24
 #define TARGET_NR_stime                   25
 #define TARGET_NR_ptrace                  26
 #define TARGET_NR_alarm                   27
@@ -47,11 +47,11 @@
 #define TARGET_NR_times                   43
 #define TARGET_NR_prof                    44
 #define TARGET_NR_brk                     45
-#define TARGET_NR_setgid32                46
-#define TARGET_NR_getgid32                47
+#define TARGET_NR_setgid                  46
+#define TARGET_NR_getgid                  47
 #define TARGET_NR_signal                  48
-#define TARGET_NR_geteuid32               49
-#define TARGET_NR_getegid32               50
+#define TARGET_NR_geteuid                 49
+#define TARGET_NR_getegid                 50
 #define TARGET_NR_acct                    51
 #define TARGET_NR_umount2                 52
 #define TARGET_NR_lock                    53
@@ -71,8 +71,8 @@
 #define TARGET_NR_sigaction               67
 #define TARGET_NR_sgetmask                68
 #define TARGET_NR_ssetmask                69
-#define TARGET_NR_setreuid32              70
-#define TARGET_NR_setregid32              71
+#define TARGET_NR_setreuid                70
+#define TARGET_NR_setregid                71
 #define TARGET_NR_sigsuspend              72
 #define TARGET_NR_sigpending              73
 #define TARGET_NR_sethostname             74
@@ -81,8 +81,8 @@
 #define TARGET_NR_getrusage               77
 #define TARGET_NR_gettimeofday            78
 #define TARGET_NR_settimeofday            79
-#define TARGET_NR_getgroups32             80
-#define TARGET_NR_setgroups32             81
+#define TARGET_NR_getgroups               80
+#define TARGET_NR_setgroups               81
 #define TARGET_NR_select                  82
 #define TARGET_NR_symlink                 83
 #define TARGET_NR_oldlstat                84
@@ -96,7 +96,7 @@
 #define TARGET_NR_truncate                92
 #define TARGET_NR_ftruncate               93
 #define TARGET_NR_fchmod                  94
-#define TARGET_NR_fchown32                95
+#define TARGET_NR_fchown                  95
 #define TARGET_NR_getpriority             96
 #define TARGET_NR_setpriority             97
 #define TARGET_NR_profil                  98
@@ -139,8 +139,8 @@
 #define TARGET_NR_sysfs                  135
 #define TARGET_NR_personality            136
 #define TARGET_NR_afs_syscall            137 /* Syscall for Andrew File System */
-#define TARGET_NR_setfsuid32             138
-#define TARGET_NR_setfsgid32             139
+#define TARGET_NR_setfsuid               138
+#define TARGET_NR_setfsgid               139
 #define TARGET_NR__llseek                140
 #define TARGET_NR_getdents               141
 #define TARGET_NR__newselect             142
@@ -182,7 +182,7 @@
 #define TARGET_NR_rt_sigsuspend          178
 #define TARGET_NR_pread64                179
 #define TARGET_NR_pwrite64               180
-#define TARGET_NR_chown32                181
+#define TARGET_NR_chown                  181
 #define TARGET_NR_getcwd                 182
 #define TARGET_NR_capget                 183
 #define TARGET_NR_capset                 184
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 6c57e24..20c93d0 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -49,7 +49,7 @@
 #define TARGET_IOC_TYPEBITS	8
 
 #if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) \
-    || defined(TARGET_M68K) || defined(TARGET_SH4) || defined(TARGET_CRIS)
+    || defined(TARGET_M68K) || defined(TARGET_SH4) || defined(TARGET_CRIS) || defined(TARGET_PPC) || defined(TARGET_MIPS)
     /* 16 bit uid wrappers emulation */
 #define USE_UID16
 #endif
commit 644d67777947d64d13a27bc67fff9f66815ef4c0
Author: Riku Voipio <riku.voipio at nokia.com>
Date:   Wed Dec 1 14:53:10 2010 +0200

    update binfmt conf
    
    1) dont register i386 qemu on x86_64 host
    2) widen sparc and arm match
    3) add sh4, based on patch by David Kozub <zub at linux.fjfi.cvut.cz>
    
    Rest based on patch by Jan-Simon Möller <jsmoeller at linuxfoundation.org>

diff --git a/qemu-binfmt-conf.sh b/qemu-binfmt-conf.sh
index ba916ac..c50beb7 100644
--- a/qemu-binfmt-conf.sh
+++ b/qemu-binfmt-conf.sh
@@ -12,7 +12,7 @@ fi
 # probe cpu type
 cpu=`uname -m`
 case "$cpu" in
-  i386|i486|i586|i686|i86pc|BePC)
+  i386|i486|i586|i686|i86pc|BePC|x86_64)
     cpu="i386"
   ;;
   m68k)
@@ -24,7 +24,7 @@ case "$cpu" in
   "Power Macintosh"|ppc|ppc64)
     cpu="ppc"
   ;;
-  armv4l)
+  armv[4-9]*)
     cpu="arm"
   ;;
 esac
@@ -60,3 +60,7 @@ if [ $cpu != "mips" ] ; then
     echo   ':mips64:M::\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-mips64:' > /proc/sys/fs/binfmt_misc/register
     echo   ':mips64el:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-mips64el:' > /proc/sys/fs/binfmt_misc/register
 fi
+if [ $cpu != "sh" ] ; then
+    echo    ':sh4:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2a\x00:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-sh4:' > /proc/sys/fs/binfmt_misc/register
+    echo    ':sh4eb:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2a:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-sh4eb:' > /proc/sys/fs/binfmt_misc/register
+fi
commit 9190749fbe075ece4a72380cc3dea919a8f960c3
Author: Riku Voipio <riku.voipio at nokia.com>
Date:   Fri Nov 26 16:21:34 2010 +0200

    linux-user: fix compiler error on nptl
    
    Some compilers detect that new_stack isnt used after dd75d784
    
    Signed-off-by: Riku Voipio <riku.voipio at nokia.com>

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 070241b..c3e8706 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -3635,11 +3635,12 @@ static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp,
 {
     int ret;
     TaskState *ts;
-    uint8_t *new_stack;
     CPUState *new_env;
 #if defined(CONFIG_USE_NPTL)
     unsigned int nptl_flags;
     sigset_t sigmask;
+#else
+    uint8_t *new_stack;
 #endif
 
     /* Emulate vfork() with fork() */
commit a59d69da66da551fa078e05ff08cf535b768c308
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Nov 24 15:20:08 2010 +0000

    ARM: linux-user: Restore iWMMXT state from ucontext on sigreturn
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Riku Voipio <riku.voipio at nokia.com>

diff --git a/linux-user/signal.c b/linux-user/signal.c
index b4b610b..c846b8c 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1602,6 +1602,30 @@ static abi_ulong *restore_sigframe_v2_vfp(CPUState *env, abi_ulong *regspace)
     return (abi_ulong*)(vfpframe + 1);
 }
 
+static abi_ulong *restore_sigframe_v2_iwmmxt(CPUState *env, abi_ulong *regspace)
+{
+    int i;
+    abi_ulong magic, sz;
+    struct target_iwmmxt_sigframe *iwmmxtframe;
+    iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
+
+    __get_user(magic, &iwmmxtframe->magic);
+    __get_user(sz, &iwmmxtframe->size);
+    if (magic != TARGET_IWMMXT_MAGIC || sz != sizeof(*iwmmxtframe)) {
+        return 0;
+    }
+    for (i = 0; i < 16; i++) {
+        __get_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
+    }
+    __get_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
+    __get_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
+    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
+    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
+    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
+    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
+    return (abi_ulong*)(iwmmxtframe + 1);
+}
+
 static int do_sigframe_return_v2(CPUState *env, target_ulong frame_addr,
                                  struct target_ucontext_v2 *uc)
 {
@@ -1622,6 +1646,12 @@ static int do_sigframe_return_v2(CPUState *env, target_ulong frame_addr,
             return 1;
         }
     }
+    if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
+        regspace = restore_sigframe_v2_iwmmxt(env, regspace);
+        if (!regspace) {
+            return 1;
+        }
+    }
 
     if (do_sigaltstack(frame_addr + offsetof(struct target_ucontext_v2, tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
         return 1;
commit 08e11256f6a0caae9b8f18fb6a71359b590d97c6
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Nov 24 15:20:07 2010 +0000

    ARM: linux-user: Expose iWMMXT registers to signal handlers
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Riku Voipio <riku.voipio at nokia.com>

diff --git a/linux-user/signal.c b/linux-user/signal.c
index 63d893b..b4b610b 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1130,7 +1130,21 @@ struct target_vfp_sigframe {
     struct target_user_vfp_exc ufp_exc;
 } __attribute__((__aligned__(8)));
 
+struct target_iwmmxt_sigframe {
+    abi_ulong magic;
+    abi_ulong size;
+    uint64_t regs[16];
+    /* Note that not all the coprocessor control registers are stored here */
+    uint32_t wcssf;
+    uint32_t wcasf;
+    uint32_t wcgr0;
+    uint32_t wcgr1;
+    uint32_t wcgr2;
+    uint32_t wcgr3;
+} __attribute__((__aligned__(8)));
+
 #define TARGET_VFP_MAGIC 0x56465001
+#define TARGET_IWMMXT_MAGIC 0x12ef842a
 
 struct sigframe_v1
 {
@@ -1292,6 +1306,25 @@ static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUState *env)
     return (abi_ulong*)(vfpframe+1);
 }
 
+static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace, CPUState *env)
+{
+    int i;
+    struct target_iwmmxt_sigframe *iwmmxtframe;
+    iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
+    __put_user(TARGET_IWMMXT_MAGIC, &iwmmxtframe->magic);
+    __put_user(sizeof(*iwmmxtframe), &iwmmxtframe->size);
+    for (i = 0; i < 16; i++) {
+        __put_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
+    }
+    __put_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
+    __put_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
+    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
+    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
+    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
+    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
+    return (abi_ulong*)(iwmmxtframe+1);
+}
+
 static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
                               target_sigset_t *set, CPUState *env)
 {
@@ -1314,6 +1347,10 @@ static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
     if (arm_feature(env, ARM_FEATURE_VFP)) {
         regspace = setup_sigframe_v2_vfp(regspace, env);
     }
+    if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
+        regspace = setup_sigframe_v2_iwmmxt(regspace, env);
+    }
+
     /* Write terminating magic word */
     __put_user(0, regspace);
 
commit 5f9099d9cee0e9ed377aee705ca9f4db75e8948d
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Nov 24 15:20:06 2010 +0000

    ARM: linux-user: Restore VFP state from ucontext on sigreturn
    
    Restore the VFP registers from the ucontext on return from a signal
    handler in linux-user mode. This means that signal handlers cannot
    accidentally corrupt the interrupted code's VFP state, and allows
    them to deliberately modify the state via the ucontext structure.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Riku Voipio <riku.voipio at nokia.com>

diff --git a/linux-user/signal.c b/linux-user/signal.c
index af1e0eb..63d893b 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1535,10 +1535,41 @@ badframe:
 	return 0;
 }
 
+static abi_ulong *restore_sigframe_v2_vfp(CPUState *env, abi_ulong *regspace)
+{
+    int i;
+    abi_ulong magic, sz;
+    uint32_t fpscr, fpexc;
+    struct target_vfp_sigframe *vfpframe;
+    vfpframe = (struct target_vfp_sigframe *)regspace;
+
+    __get_user(magic, &vfpframe->magic);
+    __get_user(sz, &vfpframe->size);
+    if (magic != TARGET_VFP_MAGIC || sz != sizeof(*vfpframe)) {
+        return 0;
+    }
+    for (i = 0; i < 32; i++) {
+        __get_user(env->vfp.regs[i], &vfpframe->ufp.fpregs[i]);
+    }
+    __get_user(fpscr, &vfpframe->ufp.fpscr);
+    vfp_set_fpscr(env, fpscr);
+    __get_user(fpexc, &vfpframe->ufp_exc.fpexc);
+    /* Sanitise FPEXC: ensure VFP is enabled, FPINST2 is invalid
+     * and the exception flag is cleared
+     */
+    fpexc |= (1 << 30);
+    fpexc &= ~((1 << 31) | (1 << 28));
+    env->vfp.xregs[ARM_VFP_FPEXC] = fpexc;
+    __get_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
+    __get_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
+    return (abi_ulong*)(vfpframe + 1);
+}
+
 static int do_sigframe_return_v2(CPUState *env, target_ulong frame_addr,
                                  struct target_ucontext_v2 *uc)
 {
     sigset_t host_set;
+    abi_ulong *regspace;
 
     target_to_host_sigset(&host_set, &uc->tuc_sigmask);
     sigprocmask(SIG_SETMASK, &host_set, NULL);
@@ -1546,6 +1577,15 @@ static int do_sigframe_return_v2(CPUState *env, target_ulong frame_addr,
     if (restore_sigcontext(env, &uc->tuc_mcontext))
         return 1;
 
+    /* Restore coprocessor signal frame */
+    regspace = uc->tuc_regspace;
+    if (arm_feature(env, ARM_FEATURE_VFP)) {
+        regspace = restore_sigframe_v2_vfp(env, regspace);
+        if (!regspace) {
+            return 1;
+        }
+    }
+
     if (do_sigaltstack(frame_addr + offsetof(struct target_ucontext_v2, tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
         return 1;
 
commit 0d871bdbaac428601c84d29233a49f7cf6ecb6fc
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Nov 24 15:20:05 2010 +0000

    ARM: linux-user: Expose VFP registers to signal handlers
    
    For ARM linux-user mode signal handlers, fill in the ucontext with
    VFP register contents in the same way that the kernel does. We only
    do this for v2 format sigframe (2.6.12 and above); this is actually
    bug-for-bug compatible with the older kernels, which don't save and
    restore VFP registers either.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Riku Voipio <riku.voipio at nokia.com>

diff --git a/linux-user/signal.c b/linux-user/signal.c
index e195eef..af1e0eb 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1112,6 +1112,26 @@ struct target_ucontext_v2 {
     abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
 };
 
+struct target_user_vfp {
+    uint64_t fpregs[32];
+    abi_ulong fpscr;
+};
+
+struct target_user_vfp_exc {
+    abi_ulong fpexc;
+    abi_ulong fpinst;
+    abi_ulong fpinst2;
+};
+
+struct target_vfp_sigframe {
+    abi_ulong magic;
+    abi_ulong size;
+    struct target_user_vfp ufp;
+    struct target_user_vfp_exc ufp_exc;
+} __attribute__((__aligned__(8)));
+
+#define TARGET_VFP_MAGIC 0x56465001
+
 struct sigframe_v1
 {
     struct target_sigcontext sc;
@@ -1255,11 +1275,29 @@ setup_return(CPUState *env, struct target_sigaction *ka,
 	return 0;
 }
 
+static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUState *env)
+{
+    int i;
+    struct target_vfp_sigframe *vfpframe;
+    vfpframe = (struct target_vfp_sigframe *)regspace;
+    __put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
+    __put_user(sizeof(*vfpframe), &vfpframe->size);
+    for (i = 0; i < 32; i++) {
+        __put_user(env->vfp.regs[i], &vfpframe->ufp.fpregs[i]);
+    }
+    __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
+    __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
+    __put_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
+    __put_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
+    return (abi_ulong*)(vfpframe+1);
+}
+
 static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
                               target_sigset_t *set, CPUState *env)
 {
     struct target_sigaltstack stack;
     int i;
+    abi_ulong *regspace;
 
     /* Clear all the bits of the ucontext we don't use.  */
     memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
@@ -1271,7 +1309,14 @@ static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
     memcpy(&uc->tuc_stack, &stack, sizeof(stack));
 
     setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
-    /* FIXME: Save coprocessor signal frame.  */
+    /* Save coprocessor signal frame.  */
+    regspace = uc->tuc_regspace;
+    if (arm_feature(env, ARM_FEATURE_VFP)) {
+        regspace = setup_sigframe_v2_vfp(regspace, env);
+    }
+    /* Write terminating magic word */
+    __put_user(0, regspace);
+
     for(i = 0; i < TARGET_NSIG_WORDS; i++) {
         __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
     }
commit 0165329578eb8f40901825177c0874efb815e342
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Nov 24 15:20:04 2010 +0000

    ARM: Expose vfp_get_fpscr() and vfp_set_fpscr() to C code
    
    Expose the vfp_get_fpscr() and vfp_set_fpscr() functions to C
    code as well as generated code, so we can use them to read and
    write the FPSCR when saving and restoring VFP registers across
    signal handlers in linux-user mode.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Riku Voipio <riku.voipio at nokia.com>

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 0284bad..340933e 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -300,6 +300,10 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
     }
 }
 
+/* Return the current FPSCR value.  */
+uint32_t vfp_get_fpscr(CPUARMState *env);
+void vfp_set_fpscr(CPUARMState *env, uint32_t val);
+
 enum arm_cpu_mode {
   ARM_CPU_MODE_USR = 0x10,
   ARM_CPU_MODE_FIQ = 0x11,
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 94aef39..2a1f448 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2251,6 +2251,11 @@ uint32_t HELPER(vfp_get_fpscr)(CPUState *env)
     return fpscr;
 }
 
+uint32_t vfp_get_fpscr(CPUState *env)
+{
+    return HELPER(vfp_get_fpscr)(env);
+}
+
 /* Convert vfp exception flags to target form.  */
 static inline int vfp_exceptbits_to_host(int target_bits)
 {
@@ -2307,6 +2312,11 @@ void HELPER(vfp_set_fpscr)(CPUState *env, uint32_t val)
     set_float_exception_flags(i, &env->vfp.fp_status);
 }
 
+void vfp_set_fpscr(CPUState *env, uint32_t val)
+{
+    HELPER(vfp_set_fpscr)(env, val);
+}
+
 #define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p))
 
 #define VFP_BINOP(name) \
commit 5f0b7c888b5e626d61e0969a6c0dbf4fcf0f522c
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Nov 24 15:20:03 2010 +0000

    ARM: linux-user: Correct size of padding in target_ucontext_v2
    
    The padding in the target_ucontext_v2 is defined by the size of
    the target's sigset_t type, not the host's. (This bug only causes
    problems when we start using the uc_regspace[] array to expose
    VFP registers to userspace signal handlers.)
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Riku Voipio <riku.voipio at nokia.com>

diff --git a/linux-user/signal.c b/linux-user/signal.c
index 7c62fac..e195eef 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1108,7 +1108,7 @@ struct target_ucontext_v2 {
     target_stack_t tuc_stack;
     struct target_sigcontext tuc_mcontext;
     target_sigset_t  tuc_sigmask;	/* mask last for extensibility */
-    char __unused[128 - sizeof(sigset_t)];
+    char __unused[128 - sizeof(target_sigset_t)];
     abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
 };
 
commit ef5e4ea587c10d3a936f807d6fa2a81c71a86511
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Nov 19 13:54:39 2010 +0000

    target-sparc: remove unused functions cpu_lock(), cpu_unlock()

diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 7e0d17c..3e93bbb 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -444,8 +444,6 @@ CPUSPARCState *cpu_sparc_init(const char *cpu_model);
 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu);
 void sparc_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt,
                                                  ...));
-void cpu_lock(void);
-void cpu_unlock(void);
 int cpu_sparc_handle_mmu_fault(CPUSPARCState *env1, target_ulong address, int rw,
                                int mmu_idx, int is_softmmu);
 #define cpu_handle_mmu_fault cpu_sparc_handle_mmu_fault
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index e84c312..7e45d7a 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -41,20 +41,6 @@ static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
 
 /* Sparc MMU emulation */
 
-/* thread support */
-
-static spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
-
-void cpu_lock(void)
-{
-    spin_lock(&global_cpu_lock);
-}
-
-void cpu_unlock(void)
-{
-    spin_unlock(&global_cpu_lock);
-}
-
 #if defined(CONFIG_USER_ONLY)
 
 int cpu_sparc_handle_mmu_fault(CPUState *env1, target_ulong address, int rw,
commit 3a807decfa5245d3eb50c9301e73fc5da4a484e1
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Nov 19 15:36:47 2010 +0000

    ARM: enable XScale/iWMMXT in linux-user mode
    
    In linux-user mode, the XScale/iWMMXT coprocessors must be enabled
    at reset so that we can run code that uses these instructions.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 996d40d..94aef39 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -203,7 +203,13 @@ void cpu_reset(CPUARMState *env)
         cpu_reset_model_id(env, id);
 #if defined (CONFIG_USER_ONLY)
     env->uncached_cpsr = ARM_CPU_MODE_USR;
+    /* For user mode we must enable access to coprocessors */
     env->vfp.xregs[ARM_VFP_FPEXC] = 1 << 30;
+    if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
+        env->cp15.c15_cpar = 3;
+    } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
+        env->cp15.c15_cpar = 1;
+    }
 #else
     /* SVC mode with interrupts disabled.  */
     env->uncached_cpsr = ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
commit f3b974cd3bb624cc7a3004db902b59d599ff016a
Author: Jamie Lentin <jm at lentin.co.uk>
Date:   Fri Nov 26 15:04:08 2010 +0200

    linux-user: Translate getsockopt level option
    
    n setsockopt, the socket level options are translated to the hosts'
    architecture before the real syscall is called, e.g.
    TARGET_SO_TYPE -> SO_TYPE. This patch does the same with getsockopt.
    
    Tested on a x86 host emulating MIPS.  Without it:-
    
    $ grep getsockopt host.strace
    31311 getsockopt(3, SOL_SOCKET, 0x1007 /* SO_??? */, 0xbff17208,
    0xbff17204) = -1 ENOPROTOOPT (Protocol not available)
    
    With:-
    
    $ grep getsockopt host.strace
    25706 getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
    
    Whitespace cleanup: Riku Voipio
    
    Signed-off-by: Jamie Lentin <jm at lentin.co.uk>
    Signed-off-by: Riku Voipio <riku.voipio at iki.fi>

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 5761106..070241b 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -1374,15 +1374,66 @@ static abi_long do_getsockopt(int sockfd, int level, int optname,
 
     switch(level) {
     case TARGET_SOL_SOCKET:
-    	level = SOL_SOCKET;
-	switch (optname) {
-	case TARGET_SO_LINGER:
-	case TARGET_SO_RCVTIMEO:
-	case TARGET_SO_SNDTIMEO:
-	case TARGET_SO_PEERCRED:
-	case TARGET_SO_PEERNAME:
-	    /* These don't just return a single integer */
-	    goto unimplemented;
+        level = SOL_SOCKET;
+        switch (optname) {
+        /* These don't just return a single integer */
+        case TARGET_SO_LINGER:
+        case TARGET_SO_RCVTIMEO:
+        case TARGET_SO_SNDTIMEO:
+        case TARGET_SO_PEERCRED:
+        case TARGET_SO_PEERNAME:
+            goto unimplemented;
+        /* Options with 'int' argument.  */
+        case TARGET_SO_DEBUG:
+            optname = SO_DEBUG;
+            goto int_case;
+        case TARGET_SO_REUSEADDR:
+            optname = SO_REUSEADDR;
+            goto int_case;
+        case TARGET_SO_TYPE:
+            optname = SO_TYPE;
+            goto int_case;
+        case TARGET_SO_ERROR:
+            optname = SO_ERROR;
+            goto int_case;
+        case TARGET_SO_DONTROUTE:
+            optname = SO_DONTROUTE;
+            goto int_case;
+        case TARGET_SO_BROADCAST:
+            optname = SO_BROADCAST;
+            goto int_case;
+        case TARGET_SO_SNDBUF:
+            optname = SO_SNDBUF;
+            goto int_case;
+        case TARGET_SO_RCVBUF:
+            optname = SO_RCVBUF;
+            goto int_case;
+        case TARGET_SO_KEEPALIVE:
+            optname = SO_KEEPALIVE;
+            goto int_case;
+        case TARGET_SO_OOBINLINE:
+            optname = SO_OOBINLINE;
+            goto int_case;
+        case TARGET_SO_NO_CHECK:
+            optname = SO_NO_CHECK;
+            goto int_case;
+        case TARGET_SO_PRIORITY:
+            optname = SO_PRIORITY;
+            goto int_case;
+#ifdef SO_BSDCOMPAT
+        case TARGET_SO_BSDCOMPAT:
+            optname = SO_BSDCOMPAT;
+            goto int_case;
+#endif
+        case TARGET_SO_PASSCRED:
+            optname = SO_PASSCRED;
+            goto int_case;
+        case TARGET_SO_TIMESTAMP:
+            optname = SO_TIMESTAMP;
+            goto int_case;
+        case TARGET_SO_RCVLOWAT:
+            optname = SO_RCVLOWAT;
+            goto int_case;
         default:
             goto int_case;
         }
@@ -1406,7 +1457,7 @@ static abi_long do_getsockopt(int sockfd, int level, int optname,
         } else {
             if (put_user_u8(val, optval_addr))
                 return -TARGET_EFAULT;
-	}
+        }
         if (put_user_u32(len, optlen))
             return -TARGET_EFAULT;
         break;
commit bee70008074570ef2c368aec80918c2494065247
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Nov 8 18:13:58 2010 +0000

    linux-user: remove unnecessary local from __get_user(), __put_user()
    
    Remove an unnecessary local variable from the __get_user() and
    __put_user() macros. This avoids confusing compilation failures
    if the name of the local variable ('size') happens to be the
    same as the variable the macro user is trying to read/write.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Riku Voipio <riku.voipio at nokia.com>

diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 00c6549..e66a02b 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -264,8 +264,7 @@ static inline int access_ok(int type, abi_ulong addr, abi_ulong size)
  */
 #define __put_user(x, hptr)\
 ({\
-    int size = sizeof(*hptr);\
-    switch(size) {\
+    switch(sizeof(*hptr)) {\
     case 1:\
         *(uint8_t *)(hptr) = (uint8_t)(typeof(*hptr))(x);\
         break;\
@@ -286,8 +285,7 @@ static inline int access_ok(int type, abi_ulong addr, abi_ulong size)
 
 #define __get_user(x, hptr) \
 ({\
-    int size = sizeof(*hptr);\
-    switch(size) {\
+    switch(sizeof(*hptr)) {\
     case 1:\
         x = (typeof(*hptr))*(uint8_t *)(hptr);\
         break;\
commit 48e15fc2de29276f0c93482f5175b95e50557fbf
Author: Nathan Froyd <froydnj at codesourcery.com>
Date:   Fri Oct 29 07:48:57 2010 -0700

    linux-user: fix memory leaks with NPTL emulation
    
    Running programs that create large numbers of threads, such as this
    snippet from libstdc++'s pthread7-rope.cc:
    
      const int max_thread_count = 4;
      const int max_loop_count = 10000;
      ...
      for (int j = 0; j < max_loop_count; j++)
        {
          ...
          for (int i = 0; i < max_thread_count; i++)
    	pthread_create (&tid[i], NULL, thread_main, 0);
    
          for (int i = 0; i < max_thread_count; i++)
    	pthread_join (tid[i], NULL);
        }
    
    in user-mode emulation will quickly run out of memory.  This is caused
    by a failure to free memory in do_syscall prior to thread exit:
    
              /* TODO: Free CPU state.  */
              pthread_exit(NULL);
    
    The first step in fixing this is to make all TaskStates used by QEMU
    dynamically allocated.  The TaskState used by the initial thread was
    not, as it was allocated on main's stack.  So fix that, free the
    cpu_env, free the TaskState, and we're home free, right?
    
    Not exactly.  When we create a thread, we do:
    
            ts = qemu_mallocz(sizeof(TaskState) + NEW_STACK_SIZE);
            ...
            new_stack = ts->stack;
            ...
            ret = pthread_attr_setstack(&attr, new_stack, NEW_STACK_SIZE);
    
    If we blindly free the TaskState, then, we yank the current (host)
    thread's stack out from underneath it while it still has things to do,
    like calling pthread_exit.  That causes problems, as you might expect.
    
    The solution adopted here is to let the C library allocate the thread's
    stack (so the C library can properly clean it up at pthread_exit) and
    provide a hint that we want NEW_STACK_SIZE bytes of stack.
    
    With those two changes, we're done, right?  Well, almost.  You see,
    we're creating all these host threads and their parent threads never
    bother to check that their children are finished.  There's no good place
    for the parent threads to do so.  Therefore, we need to create the
    threads in a detached state so the parent thread doesn't have to call
    pthread_join on the child to release the child's resources; the child
    does so automatically.
    
    With those three major changes, we can comfortably run programs like the
    above without exhausting memory.  We do need to delete 'stack' from the
    TaskState structure.
    
    Signed-off-by: Nathan Froyd <froydnj at codesourcery.com>
    Signed-off-by: Riku Voipio <riku.voipio at nokia.com>

diff --git a/linux-user/main.c b/linux-user/main.c
index dbba8be..7d41d4a 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2711,7 +2711,7 @@ int main(int argc, char **argv, char **envp)
     struct target_pt_regs regs1, *regs = &regs1;
     struct image_info info1, *info = &info1;
     struct linux_binprm bprm;
-    TaskState ts1, *ts = &ts1;
+    TaskState *ts;
     CPUState *env;
     int optind;
     const char *r;
@@ -3038,7 +3038,7 @@ int main(int argc, char **argv, char **envp)
     }
     target_argv[target_argc] = NULL;
 
-    memset(ts, 0, sizeof(TaskState));
+    ts = qemu_mallocz (sizeof(TaskState));
     init_task_state(ts);
     /* build Task State */
     ts->info = info;
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 708021e..00c6549 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -126,8 +126,6 @@ typedef struct TaskState {
     struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
     struct sigqueue *first_free; /* first free siginfo queue entry */
     int signal_pending; /* non zero if a signal may be pending */
-
-    uint8_t stack[0];
 } __attribute__((aligned(16))) TaskState;
 
 extern char *exec_path;
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index d44f512..5761106 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -3601,9 +3601,8 @@ static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp,
         new_thread_info info;
         pthread_attr_t attr;
 #endif
-        ts = qemu_mallocz(sizeof(TaskState) + NEW_STACK_SIZE);
+        ts = qemu_mallocz(sizeof(TaskState));
         init_task_state(ts);
-        new_stack = ts->stack;
         /* we create a new CPU instance. */
         new_env = cpu_copy(env);
 #if defined(TARGET_I386) || defined(TARGET_SPARC) || defined(TARGET_PPC)
@@ -3639,7 +3638,8 @@ static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp,
             info.parent_tidptr = parent_tidptr;
 
         ret = pthread_attr_init(&attr);
-        ret = pthread_attr_setstack(&attr, new_stack, NEW_STACK_SIZE);
+        ret = pthread_attr_setstacksize(&attr, NEW_STACK_SIZE);
+        ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
         /* It is not safe to deliver signals until the child has finished
            initializing, so temporarily block all signals.  */
         sigfillset(&sigmask);
@@ -3667,6 +3667,7 @@ static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp,
         if (flags & CLONE_NPTL_FLAGS2)
             return -EINVAL;
         /* This is probably going to die very quickly, but do it anyway.  */
+        new_stack = qemu_mallocz (NEW_STACK_SIZE);
 #ifdef __ia64__
         ret = __clone2(clone_func, new_stack, NEW_STACK_SIZE, flags, new_env);
 #else
@@ -4240,7 +4241,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
               sys_futex(g2h(ts->child_tidptr), FUTEX_WAKE, INT_MAX,
                         NULL, NULL, 0);
           }
-          /* TODO: Free CPU state.  */
+          thread_env = NULL;
+          qemu_free(cpu_env);
+          qemu_free(ts);
           pthread_exit(NULL);
       }
 #endif
commit c65ffe6d6ca8b156e729e81054ca7597864354a9
Author: amateur <tianlei.zhao at gmail.com>
Date:   Tue Sep 14 13:22:34 2010 +0800

    linux-user: mmap_reserve() not controlled by RESERVED_VA
    
    mmap_reserve() should be called only when RESERVED_VA is enabled.
    Otherwise, unmaped virtual address space will never be reusable. This
    bug will exhaust virtual address space in extreme conditions.
    
    Signed-off-by: Riku Voipio <riku.voipio at nokia.com>

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 035dfbd..abf21f6 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -697,7 +697,9 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
                                          old_size, new_size,
                                          flags | MREMAP_FIXED,
                                          g2h(mmap_start));
-            mmap_reserve(old_addr, old_size);
+            if ( RESERVED_VA ) {
+                mmap_reserve(old_addr, old_size);
+            }
         }
     } else {
         int prot = 0;
commit b0e102dd22e7a158fa3dc4148ab6c2e78b363071
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Nov 19 13:54:44 2010 +0000

    [PATCH] target-arm: remove unused functions cpu_lock(), cpu_unlock()
    
    Signed-off-by: Riku Voipio <riku.voipio at nokia.com>

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index b87c605..0284bad 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -227,8 +227,6 @@ int cpu_arm_handle_mmu_fault (CPUARMState *env, target_ulong address, int rw,
                               int mmu_idx, int is_softmuu);
 #define cpu_handle_mmu_fault cpu_arm_handle_mmu_fault
 
-void cpu_lock(void);
-void cpu_unlock(void);
 static inline void cpu_set_tls(CPUARMState *env, target_ulong newtls)
 {
   env->cp15.c13_tls2 = newtls;
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 9b1a014..43baa63 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -28,20 +28,6 @@ void raise_exception(int tt)
     cpu_loop_exit();
 }
 
-/* thread support */
-
-static spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
-
-void cpu_lock(void)
-{
-    spin_lock(&global_cpu_lock);
-}
-
-void cpu_unlock(void)
-{
-    spin_unlock(&global_cpu_lock);
-}
-
 uint32_t HELPER(neon_tbl)(uint32_t ireg, uint32_t def,
                           uint32_t rn, uint32_t maxindex)
 {
commit 6a8657528d94fa1be78d1be0821a01a251fa2de9
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Dec 2 14:41:59 2010 -0600

    Fix build
    
    msix.o and msi.o get pulled into the build unconditionally for QMP.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/Makefile.objs b/Makefile.objs
index 257623b..04625eb 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -218,7 +218,6 @@ hw-obj-$(CONFIG_PIIX4) += piix4.o
 hw-obj-$(CONFIG_PCI) += wdt_i6300esb.o
 
 hw-obj-$(CONFIG_PCI) += pcie.o pcie_aer.o pcie_port.o
-hw-obj-$(CONFIG_PCI) += msix.o msi.o
 
 # PCI network cards
 hw-obj-$(CONFIG_NE2000_PCI) += ne2000.o
commit 19c71ff41c029517c11ae67d6fbcb093a5d1150f
Merge: 393f398... 0c600ce...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Dec 2 14:16:40 2010 -0600

    Merge remote branch 'mst/for_anthony' into staging

commit 0c600ce2a7a419c7247b2ac63327dea5daa3d5a2
Author: Jason Wang <jasowang at redhat.com>
Date:   Sat Nov 27 22:05:07 2010 +0800

    vhost: Fix address calculation in vhost_dev_sync_region()
    
    We still need advance address even we find there's no dirty pages in
    current chunk.
    
    Signed-off-by: Jason Wang <jasowang at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/vhost.c b/hw/vhost.c
index 8586f66..6082da2 100644
--- a/hw/vhost.c
+++ b/hw/vhost.c
@@ -37,6 +37,7 @@ static void vhost_dev_sync_region(struct vhost_dev *dev,
         /* We first check with non-atomic: much cheaper,
          * and we expect non-dirty to be the common case. */
         if (!*from) {
+            addr += VHOST_LOG_CHUNK;
             continue;
         }
         /* Data must be read atomically. We don't really
commit 3d002df33eb034757d98e1ae529318f57df78f91
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Tue Nov 23 19:05:54 2010 +0200

    migration: allow rate > 4g
    
    I'd like to disable bandwidth limit or make it very high,
    Use int64_t all over to make values >= 4g work.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    Tested-by: Jason Wang <jasowang at redhat.com>

diff --git a/buffered_file.c b/buffered_file.c
index 1836e7e..8435a31 100644
--- a/buffered_file.c
+++ b/buffered_file.c
@@ -206,20 +206,23 @@ static int buffered_rate_limit(void *opaque)
     return 0;
 }
 
-static size_t buffered_set_rate_limit(void *opaque, size_t new_rate)
+static int64_t buffered_set_rate_limit(void *opaque, int64_t new_rate)
 {
     QEMUFileBuffered *s = opaque;
-
     if (s->has_error)
         goto out;
 
+    if (new_rate > SIZE_MAX) {
+        new_rate = SIZE_MAX;
+    }
+
     s->xfer_limit = new_rate / 10;
     
 out:
     return s->xfer_limit;
 }
 
-static size_t buffered_get_rate_limit(void *opaque)
+static int64_t buffered_get_rate_limit(void *opaque)
 {
     QEMUFileBuffered *s = opaque;
   
diff --git a/hw/hw.h b/hw/hw.h
index 9d2cfc2..77bfb58 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -39,8 +39,8 @@ typedef int (QEMUFileRateLimit)(void *opaque);
  * the new actual bandwidth. It should be new_rate if everything goes ok, and
  * the old rate otherwise
  */
-typedef size_t (QEMUFileSetRateLimit)(void *opaque, size_t new_rate);
-typedef size_t (QEMUFileGetRateLimit)(void *opaque);
+typedef int64_t (QEMUFileSetRateLimit)(void *opaque, int64_t new_rate);
+typedef int64_t (QEMUFileGetRateLimit)(void *opaque);
 
 QEMUFile *qemu_fopen_ops(void *opaque, QEMUFilePutBufferFunc *put_buffer,
                          QEMUFileGetBufferFunc *get_buffer,
@@ -83,8 +83,8 @@ unsigned int qemu_get_be16(QEMUFile *f);
 unsigned int qemu_get_be32(QEMUFile *f);
 uint64_t qemu_get_be64(QEMUFile *f);
 int qemu_file_rate_limit(QEMUFile *f);
-size_t qemu_file_set_rate_limit(QEMUFile *f, size_t new_rate);
-size_t qemu_file_get_rate_limit(QEMUFile *f);
+int64_t qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate);
+int64_t qemu_file_get_rate_limit(QEMUFile *f);
 int qemu_file_has_error(QEMUFile *f);
 void qemu_file_set_error(QEMUFile *f);
 
diff --git a/migration.c b/migration.c
index 9ee8b17..622a9d2 100644
--- a/migration.c
+++ b/migration.c
@@ -32,7 +32,7 @@
 #endif
 
 /* Migration speed throttling */
-static uint32_t max_throttle = (32 << 20);
+static int64_t max_throttle = (32 << 20);
 
 static MigrationState *current_migration;
 
@@ -136,7 +136,9 @@ int do_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data)
     FdMigrationState *s;
 
     d = qdict_get_int(qdict, "value");
-    d = MAX(0, MIN(UINT32_MAX, d));
+    if (d < 0) {
+        d = 0;
+    }
     max_throttle = d;
 
     s = migrate_to_fms(current_migration);
diff --git a/savevm.c b/savevm.c
index 4e49765..d38f79e 100644
--- a/savevm.c
+++ b/savevm.c
@@ -611,7 +611,7 @@ int qemu_file_rate_limit(QEMUFile *f)
     return 0;
 }
 
-size_t qemu_file_get_rate_limit(QEMUFile *f)
+int64_t qemu_file_get_rate_limit(QEMUFile *f)
 {
     if (f->get_rate_limit)
         return f->get_rate_limit(f->opaque);
@@ -619,7 +619,7 @@ size_t qemu_file_get_rate_limit(QEMUFile *f)
     return 0;
 }
 
-size_t qemu_file_set_rate_limit(QEMUFile *f, size_t new_rate)
+int64_t qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate)
 {
     /* any failed or completed migration keeps its state to allow probing of
      * migration data, but has no associated file anymore */
commit b2e0a138e77245290428a7d599a929e2e1bfe510
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Mon Nov 22 19:52:34 2010 +0200

    migration: stable ram block ordering
    
    This makes ram block ordering under migration stable, ordered by offset.
    This is especially useful for migration to exec, for debugging.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    Tested-by: Jason Wang <jasowang at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index 4486925..e32e289 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -23,6 +23,7 @@
  */
 #include <stdint.h>
 #include <stdarg.h>
+#include <stdlib.h>
 #ifndef _WIN32
 #include <sys/types.h>
 #include <sys/mman.h>
@@ -212,6 +213,39 @@ uint64_t ram_bytes_total(void)
     return total;
 }
 
+static int block_compar(const void *a, const void *b)
+{
+    RAMBlock * const *ablock = a;
+    RAMBlock * const *bblock = b;
+    if ((*ablock)->offset < (*bblock)->offset) {
+        return -1;
+    } else if ((*ablock)->offset > (*bblock)->offset) {
+        return 1;
+    }
+    return 0;
+}
+
+static void sort_ram_list(void)
+{
+    RAMBlock *block, *nblock, **blocks;
+    int n;
+    n = 0;
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        ++n;
+    }
+    blocks = qemu_malloc(n * sizeof *blocks);
+    n = 0;
+    QLIST_FOREACH_SAFE(block, &ram_list.blocks, next, nblock) {
+        blocks[n++] = block;
+        QLIST_REMOVE(block, next);
+    }
+    qsort(blocks, n, sizeof *blocks, block_compar);
+    while (--n >= 0) {
+        QLIST_INSERT_HEAD(&ram_list.blocks, blocks[n], next);
+    }
+    qemu_free(blocks);
+}
+
 int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
 {
     ram_addr_t addr;
@@ -234,6 +268,7 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
         bytes_transferred = 0;
         last_block = NULL;
         last_offset = 0;
+        sort_ram_list();
 
         /* Make sure all dirty bits are set */
         QLIST_FOREACH(block, &ram_list.blocks, next) {
diff --git a/cpu-common.h b/cpu-common.h
index a543b5d..bb6b137 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -46,6 +46,9 @@ ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size);
 void qemu_ram_free(ram_addr_t addr);
 /* This should only be used for ram local to a device.  */
 void *qemu_get_ram_ptr(ram_addr_t addr);
+/* Same but slower, to use for migration, where the order of
+ * RAMBlocks must not change. */
+void *qemu_safe_ram_ptr(ram_addr_t addr);
 /* This should not be used by devices.  */
 int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr);
 ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr);
diff --git a/exec.c b/exec.c
index db9ff55..6c8f635 100644
--- a/exec.c
+++ b/exec.c
@@ -2030,10 +2030,10 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
 
     /* we modify the TLB cache so that the dirty bit will be set again
        when accessing the range */
-    start1 = (unsigned long)qemu_get_ram_ptr(start);
+    start1 = (unsigned long)qemu_safe_ram_ptr(start);
     /* Chek that we don't span multiple blocks - this breaks the
        address comparisons below.  */
-    if ((unsigned long)qemu_get_ram_ptr(end - 1) - start1
+    if ((unsigned long)qemu_safe_ram_ptr(end - 1) - start1
             != (end - 1) - start) {
         abort();
     }
@@ -2858,6 +2858,7 @@ ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
     new_block->length = size;
 
     QLIST_INSERT_HEAD(&ram_list.blocks, new_block, next);
+    fprintf(stderr, "alloc ram %s len 0x%x\n", new_block->idstr, (int)new_block->length);
 
     ram_list.phys_dirty = qemu_realloc(ram_list.phys_dirty,
                                        last_ram_offset() >> TARGET_PAGE_BITS);
@@ -2931,6 +2932,25 @@ void *qemu_get_ram_ptr(ram_addr_t addr)
     return NULL;
 }
 
+/* Return a host pointer to ram allocated with qemu_ram_alloc.
+ * Same as qemu_get_ram_ptr but avoid reordering ramblocks.
+ */
+void *qemu_safe_ram_ptr(ram_addr_t addr)
+{
+    RAMBlock *block;
+
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        if (addr - block->offset < block->length) {
+            return block->host + (addr - block->offset);
+        }
+    }
+
+    fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
+    abort();
+
+    return NULL;
+}
+
 int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr)
 {
     RAMBlock *block;
diff --git a/kvm-all.c b/kvm-all.c
index 37b99c7..cae24bb 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -162,7 +162,7 @@ static int kvm_set_user_memory_region(KVMState *s, KVMSlot *slot)
     mem.slot = slot->slot;
     mem.guest_phys_addr = slot->start_addr;
     mem.memory_size = slot->memory_size;
-    mem.userspace_addr = (unsigned long)qemu_get_ram_ptr(slot->phys_offset);
+    mem.userspace_addr = (unsigned long)qemu_safe_ram_ptr(slot->phys_offset);
     mem.flags = slot->flags;
     if (s->migration_log) {
         mem.flags |= KVM_MEM_LOG_DIRTY_PAGES;
commit 393f398b69f9baadc3f29d822a0b5b74ca63b919
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Nov 22 14:57:58 2010 -0800

    tcg-ia64: Fix warning in qemu_ld.
    
    The usermode version of qemu_ld doesn't used mem_index,
    leading to set-but-not-used warnings.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Edgar E. Iglesias <edgar at axis.com>

diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c
index 57d0bcc..3ddf434 100644
--- a/tcg/ia64/tcg-target.c
+++ b/tcg/ia64/tcg-target.c
@@ -1658,11 +1658,10 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
     static uint64_t const opc_sxt_i29[4] = {
         OPC_SXT1_I29, OPC_SXT2_I29, OPC_SXT4_I29, 0
     };
-    int addr_reg, data_reg, mem_index, s_bits, bswap;
+    int addr_reg, data_reg, s_bits, bswap;
 
     data_reg = *args++;
     addr_reg = *args++;
-    mem_index = *args;
     s_bits = opc & 3;
 
 #ifdef TARGET_WORDS_BIGENDIAN
commit 07f59737d8350fda70171bb7c23d18512d9c038a
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Nov 22 14:57:57 2010 -0800

    tcg-ia64: Fix address compilation in qemu_st.
    
    A typo in the usermode address calculation path; R3 used where R2 needed.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Edgar E. Iglesias <edgar at axis.com>

diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c
index da81f1b..57d0bcc 100644
--- a/tcg/ia64/tcg-target.c
+++ b/tcg/ia64/tcg-target.c
@@ -1818,7 +1818,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
         tcg_out_bundle(s, miI,
                        tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
                        tcg_opc_i29(TCG_REG_P0, OPC_ZXT4_I29,
-                                   TCG_REG_R3, addr_reg),
+                                   TCG_REG_R2, addr_reg),
                        tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0));
     }
 
commit 650a217a652a940c164d5a38cedc4d6671da88ce
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Nov 22 14:57:56 2010 -0800

    tcg-ia64: Fix tlb read error for 32-bit targets.
    
    Use ld4 not ld8 for reading the tlb of 32-bit targets.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Edgar E. Iglesias <edgar at axis.com>

diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c
index 62f0804..da81f1b 100644
--- a/tcg/ia64/tcg-target.c
+++ b/tcg/ia64/tcg-target.c
@@ -1459,7 +1459,9 @@ static inline void tcg_out_qemu_tlb(TCGContext *s, TCGArg addr_reg,
                    tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1, TCG_REG_R2,
                                TCG_REG_R2, TCG_AREG0));
     tcg_out_bundle(s, mII,
-                   tcg_opc_m3 (TCG_REG_P0, OPC_LD8_M3, TCG_REG_R57,
+                   tcg_opc_m3 (TCG_REG_P0,
+                               (TARGET_LONG_BITS == 32
+                                ? OPC_LD4_M3 : OPC_LD8_M3), TCG_REG_R57,
                                TCG_REG_R2, offset_addend - offset_rw),
                    tcg_opc_a1 (TCG_REG_P0, OPC_AND_A1, TCG_REG_R3,
                                TCG_REG_R3, TCG_REG_R56),
commit b3b0091f07e1c25ba795b3df3ee3c169285f852d
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Nov 22 14:57:55 2010 -0800

    tcg-ia64: Implement qemu_ld32.
    
    The port was not properly merged following
    86feb1c860dc38e9c89e787c5210e8191800385e
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Edgar E. Iglesias <edgar at axis.com>

diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c
index 80c6950..62f0804 100644
--- a/tcg/ia64/tcg-target.c
+++ b/tcg/ia64/tcg-target.c
@@ -2124,6 +2124,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
     case INDEX_op_qemu_ld16s:
         tcg_out_qemu_ld(s, args, 1 | 4);
         break;
+    case INDEX_op_qemu_ld32:
     case INDEX_op_qemu_ld32u:
         tcg_out_qemu_ld(s, args, 2);
         break;
commit 255108c0e3c78bc437789a3626e53079ef322a4e
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Nov 22 14:57:54 2010 -0800

    tcg-ia64: Provide default GUEST_BASE.
    
    Fix compilation error when GUEST_BASE is not defined.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Edgar E. Iglesias <edgar at axis.com>

diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c
index a0f3877..80c6950 100644
--- a/tcg/ia64/tcg-target.c
+++ b/tcg/ia64/tcg-target.c
@@ -45,6 +45,9 @@ static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
 #else
 #define TCG_GUEST_BASE_REG TCG_REG_R0
 #endif
+#ifndef GUEST_BASE
+#define GUEST_BASE 0
+#endif
 
 /* Branch registers */
 enum {
commit 0909cbde9a1d42be9ab81f4f7e7d89c358212fd1
Author: Richard Henderson <rth at redhat.com>
Date:   Mon Nov 22 14:57:53 2010 -0800

    tcg: Fix default definition of divu_i32 and remu_i32.
    
    The arguments to tcg_gen_helper32 for these functions were not
    updated correctly in rev 2bece2c88331f024a46527634e3dd91c71d22141.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Edgar E. Iglesias <edgar at axis.com>

diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
index c68927e..3ee0a58 100644
--- a/tcg/tcg-op.h
+++ b/tcg/tcg-op.h
@@ -727,7 +727,7 @@ static inline void tcg_gen_divu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
     sizemask |= tcg_gen_sizemask(1, 0, 0);
     sizemask |= tcg_gen_sizemask(2, 0, 0);
 
-    tcg_gen_helper32(tcg_helper_divu_i32, ret, arg1, arg2, 0);
+    tcg_gen_helper32(tcg_helper_divu_i32, sizemask, ret, arg1, arg2);
 }
 
 static inline void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
@@ -738,7 +738,7 @@ static inline void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
     sizemask |= tcg_gen_sizemask(1, 0, 0);
     sizemask |= tcg_gen_sizemask(2, 0, 0);
 
-    tcg_gen_helper32(tcg_helper_remu_i32, ret, arg1, arg2, 0);
+    tcg_gen_helper32(tcg_helper_remu_i32, sizemask, ret, arg1, arg2);
 }
 #endif
 
commit c924f36a300cbc54d3cb511116e8e2bae17f5ae6
Merge: 1abeb5a... 09fa35e...
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Wed Dec 1 07:11:51 2010 +0200

    Merge remote branch 'origin/master' into pci
    
    Conflicts:
    	Makefile.objs
    	hw/virtio.c

diff --cc Makefile
index 2883d27,d3bc0f2..c80566c
--- a/Makefile
+++ b/Makefile
@@@ -178,9 -204,11 +204,10 @@@ ar      de     en-us  fi  fr-be  h
  common  de-ch  es     fo  fr-ca  hu     ja  mk  nl-be      pt  sl     tr
  
  ifdef INSTALL_BLOBS
- BLOBS=bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \
- openbios-sparc32 openbios-sparc64 openbios-ppc \
+ BLOBS=bios.bin vgabios.bin vgabios-cirrus.bin \
+ vgabios-stdvga.bin vgabios-vmware.bin \
+ ppc_rom.bin openbios-sparc32 openbios-sparc64 openbios-ppc \
  gpxe-eepro100-80861209.rom \
 -gpxe-eepro100-80861229.rom \
  pxe-e1000.bin \
  pxe-ne2k_pci.bin pxe-pcnet.bin \
  pxe-rtl8139.bin pxe-virtio.bin \
diff --cc Makefile.objs
index c5919af,13ba26f..257623b
--- a/Makefile.objs
+++ b/Makefile.objs
@@@ -205,15 -215,15 +215,16 @@@ hw-obj-$(CONFIG_PPCE500_PCI) += ppce500
  hw-obj-$(CONFIG_PIIX4) += piix4.o
  
  # PCI watchdog devices
- hw-obj-y += wdt_i6300esb.o
+ hw-obj-$(CONFIG_PCI) += wdt_i6300esb.o
  
- hw-obj-y += pcie.o pcie_aer.o pcie_port.o
- hw-obj-y += msix.o msi.o
 -hw-obj-$(CONFIG_PCI) += pcie.o pcie_port.o
++hw-obj-$(CONFIG_PCI) += pcie.o pcie_aer.o pcie_port.o
++hw-obj-$(CONFIG_PCI) += msix.o msi.o
  
  # PCI network cards
- hw-obj-y += ne2000.o
- hw-obj-y += eepro100.o
- hw-obj-y += pcnet.o
+ hw-obj-$(CONFIG_NE2000_PCI) += ne2000.o
+ hw-obj-$(CONFIG_EEPRO100_PCI) += eepro100.o
+ hw-obj-$(CONFIG_PCNET_PCI) += pcnet-pci.o
+ hw-obj-$(CONFIG_PCNET_COMMON) += pcnet.o
  
  hw-obj-$(CONFIG_SMC91C111) += smc91c111.o
  hw-obj-$(CONFIG_LAN9118) += lan9118.o
commit 09fa35e5cdc7d17ed3e1528ca743893ae77a0ea2
Merge: 9233da7... b76876e...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Nov 30 15:25:34 2010 -0600

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

commit 9233da785f55c924c5850cd1ce1b7f5f200d631b
Merge: fd5d5c5... a6f9dd0...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Nov 30 15:24:26 2010 -0600

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

commit fd5d5c566af040be15f2cae1b14a47919974453d
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Sep 9 14:51:31 2010 -0500

    Use a Linux-style MAINTAINERS file
    
    I make no claims that this is accurate or exhaustive but I think it's a
    reasonable place to start.
    
    As the file mentions, the purpose of this file is to give contributors
    information about who they can go to with questions about a particular piece of
    code or who they can ask for review.
    
    If you sign up for a piece of code and indicate that it's Maintained or
    Supported, please be prepared to be responsive to questions about that
    subsystem.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    ---
    
    v1 -> v2
     - Sort alphabetically
     - Copy in instructions from linux MAINTAINERS
     - Fix entries based on review feedback

diff --git a/MAINTAINERS b/MAINTAINERS
index e5165fb..59effc7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1,88 +1,428 @@
 QEMU Maintainers
 ================
 
-Project leaders:
-----------------
+The intention of this file is not to establish who owns what portions of the
+code base, but to provide a set of names that developers can consult when they
+have a question about a particular subset and also to provide a set of names
+to be CC'd when submitting a patch to obtain appropriate review.
 
-Fabrice Bellard
-Paul Brook
+In general, if you have a question about inclusion of a patch, you should
+consult qemu-devel and not any specific individual privately.
 
-CPU cores:
-----------
+Descriptions of section entries:
+
+	M: Mail patches to: FullName <address at domain>
+	L: Mailing list that is relevant to this area
+	W: Web-page with status/info
+	Q: Patchwork web based patch tracking system site
+	T: SCM tree type and location.  Type is one of: git, hg, quilt, stgit.
+	S: Status, one of the following:
+	   Supported:	Someone is actually paid to look after this.
+	   Maintained:	Someone actually looks after it.
+	   Odd Fixes:	It has a maintainer but they don't have time to do
+			much other than throw the odd patch in. See below..
+	   Orphan:	No current maintainer [but maybe you could take the
+			role as you write your new code].
+	   Obsolete:	Old code. Something tagged obsolete generally means
+			it has been replaced by a better system and you
+			should be using that.
+	F: Files and directories with wildcard patterns.
+	   A trailing slash includes all files and subdirectory files.
+	   F:	drivers/net/	all files in and below drivers/net
+	   F:	drivers/net/*	all files in drivers/net, but not below
+	   F:	*/net/*		all files in "any top level directory"/net
+	   One pattern per line.  Multiple F: lines acceptable.
+	X: Files and directories that are NOT maintained, same rules as F:
+	   Files exclusions are tested before file matches.
+	   Can be useful for excluding a specific subdirectory, for instance:
+	   F:	net/
+	   X:	net/ipv6/
+	   matches all files in and below net excluding net/ipv6/
+	K: Keyword perl extended regex pattern to match content in a
+	   patch or file.  For instance:
+	   K: of_get_profile
+	      matches patches or files that contain "of_get_profile"
+	   K: \b(printk|pr_(info|err))\b
+	      matches patches or files that contain one or more of the words
+	      printk, pr_info or pr_err
+	   One regex pattern per line.  Multiple K: lines acceptable.
+
+
+General Project Administration
+------------------------------
+M: Anthony Liguori <aliguori at us.ibm.com>
+M: Paul Brook <paul at codesourcery.com>
+
+Guest CPU cores (TCG):
+----------------------
+Alpha
+M: qemu-devel at nongnu.org
+S: Orphan
+F: target-alpha/
 
-x86                Fabrice Bellard
-ARM                Paul Brook
-SPARC              Blue Swirl
-MIPS               ?
-PowerPC            Alexander Graf
-M68K               Paul Brook
-SH4                ?
-CRIS               Edgar E. Iglesias
-Alpha              ?
-MicroBlaze         Edgar E. Iglesias
-S390               ?
-
-Machines (sorted by CPU):
--------------------------
-
-x86
-  pc.c                    Fabrice Bellard (new maintainer needed)
 ARM
-  integratorcp.c          Paul Brook
-  versatilepb.c           Paul Brook
-  Real View               Paul Brook
-  spitz.c                 Andrzej Zaborowski
-  palm.c                  Andrzej Zaborowski
-  nseries.c               Andrzej Zaborowski
-  stellaris.c             Paul Brook
-  gumstix.c               Thorsten Zitterell
-  mainstone.c             Armin Kuster
-  musicpal.c              Jan Kiszka
-SPARC
-  sun4u.c                 Blue Swirl
-  sun4m.c                 Blue Swirl
+M: Paul Brook <paul at codesourcery.com>
+S: Maintained
+F: target-arm/
+
+CRIS
+M: Edgar E. Iglesias <edgar.iglesias at gmail.com>
+S: Maintained
+F: target-cris/
+
+M68K
+M: Paul Brook <paul at codesourcery.com>
+S: Maintained
+F: target-m68k/
+
+MicroBlaze
+M: Edgar E. Iglesias <edgar.iglesias at gmail.com>
+S: Maintained
+F: target-microblaze/
+
 MIPS
-  mips_r4k.c              Aurelien Jarno
-  mips_malta.c            Aurelien Jarno
-  mips_jazz.c             Hervé Poussineau
-  mips_mipssim.c          ?
+M: qemu-devel at nongnu.org
+S: Orphan
+F: target-mips/
+
 PowerPC
-  ppc_prep.c              ?
-  ppc_oldworld.c          Alexander Graf
-  ppc_newworld.c          Alexander Graf
-  ppc405_boards.c         Alexander Graf
-M86K
-  mcf5208.c               Paul Brook
-  an5206.c                Paul Brook
-  dummy_m68k.c            Paul Brook
+M: Alexander Graf <agraf at suse.de>
+S: Maintained
+F: target-ppc/
+
+S390
+M: Alexander Graf <agraf at suse.de>
+S: Maintained
+F: target-s390x/
+
 SH4
-  shix.c                  ?
-  r2d.c                   Magnus Damm
-CRIS
-  etraxfs.c               Edgar E. Iglesias
-  axis_dev88.c            Edgar E. Iglesias
-Alpha
-MicroBlaze
-  petalogix_s3adsp1800.c  Edgar E. Iglesias
+M: qemu-devel at nongnu.org
+S: Orphan
+F: target-sh4/
+
+SPARC
+M: Blue Swirl <blauwirbel at gmail.com>
+S: Maintained
+F: target-sparc/
+
+X86
+M: qemu-devel at nongnu.org
+S: Odd Fixes
+F: target-i386/
+
+Guest CPU Cores (KVM):
+----------------------
+
+Overall
+M: Avi Kivity <avi at redhat.com>
+M: Marcelo Tosatti <mtosatti at redhat.com>
+L: kvm at vger.kernel.org
+S: Supported
+F: kvm-*
+F: */kvm.*
+
+PPC
+M: Alexander Graf <agraf at suse.de>
+S: Maintained
+F: target-ppc/kvm.c
+
 S390
-  s390-*.c                Alexander Graf
-
-Generic Subsystems:
--------------------  
-
-Dynamic translator        Fabrice Bellard
-Main loop                 Fabrice Bellard (new maintainer needed)
-TCG                       Fabrice Bellard
-IDE device                ?
-SCSI device               Paul Brook
-PCI layer                 Michael S. Tsirkin
-USB layer                 ?
-Block layer               ?
-Graphic layer             ?
-Audio device layer        Vassili Karpov (malc)
-Character device layer    ?
-Network device layer      ?
-GDB stub                  ?
-Linux user                ?
-Darwin user               ?
-SLIRP                     ?
+M: Alexander Graf <agraf at suse.de>
+S: Maintained
+F: target-s390x/kvm.c
+
+X86
+M: Avi Kivity <avi at redhat.com>
+M: Marcelo Tosatti <mtosatti at redhat.com>
+L: kvm at vger.kernel.org
+S: Supported
+F: target-i386/kvm.c
+
+ARM Machines
+------------
+Gumstix
+M: qemu-devel at nongnu.org
+S: Orphan
+F: hw/gumstix.c
+
+Integrator CP
+M: Paul Brook <paul at codesourcery.com>
+S: Maintained
+F: hw/integratorcp.c
+
+Mainstone
+M: qemu-devel at nongnu.org
+S: Orphan
+F: hw/mainstone.c
+
+Musicpal
+M: Jan Kiszka <jan.kiszka at web.de>
+S: Maintained
+F: hw/musicpal.c
+
+nSeries
+M: Andrzej Zaborowski <balrogg at gmail.com>
+S: Maintained
+F: hw/nseries.c
+
+Palm
+M: Andrzej Zaborowski <balrogg at gmail.com>
+S: Maintained
+F: hw/palm.c
+
+Real View
+M: Paul Brook <paul at codesourcery.com>
+S: Maintained
+F: hw/realview*
+
+Spitz
+M: Andrzej Zaborowski <balrogg at gmail.com>
+S: Maintained
+F: hw/spitz.c
+
+Stellaris
+M: Paul Brook <paul at codesourcery.com>
+S: Maintained
+F: hw/stellaris.c
+
+Versatile PB
+M: Paul Brook <paul at codesourcery.com>
+S: Maintained
+F: hw/versatilepb.c
+
+CRIS Machines
+-------------
+Axis Dev88
+M: Edgar E. Iglesias <edgar.iglesias at gmail.com>
+S: Maintained
+F: hw/axis_dev88.c
+
+etraxfs
+M: Edgar E. Iglesias <edgar.iglesias at gmail.com>
+S: Maintained
+F: hw/etraxfs.c
+
+M86K Machines
+-------------
+an5206
+M: Paul Brook <paul at codesourcery.com>
+S: Maintained
+F: hw/an5206.c
+
+dummy_m68k
+M: Paul Brook <paul at codesourcery.com>
+S: Maintained
+F: hw/dummy_m68k.c
+
+mcf5208
+M: Paul Brook <paul at codesourcery.com>
+S: Maintained
+F: hw/mcf5208.c
+
+MicroBlaze Machines
+-------------------
+petalogix_s3adsp1800
+M: Edgar E. Iglesias <edgar.iglesias at gmail.com>
+S: Maintained
+F: hw/petalogix_s3adsp1800.c
+
+MIPS Machines
+-------------
+Jazz
+M: Hervé Poussineau <hpoussin at reactos.org>
+S: Maintained
+F: hw/mips_jazz.c
+
+Malta
+M: Aurelien Jarno <aurelien at aurel32.net>
+S: Maintained
+F: hw/mips_malta.c
+
+Mipssim
+M: qemu-devel at nongnu.org
+S: Orphan
+F: hw/mips_mipssim.c
+
+R4000
+M: Aurelien Jarno <aurelien at aurel32.net>
+S: Maintained
+F: hw/mips_r4k.c
+
+PowerPC Machines
+----------------
+405
+M: Alexander Graf <agraf at suse.de>
+S: Maintained
+F: hw/ppc405_boards.c
+
+New World
+M: Alexander Graf <agraf at suse.de>
+S: Maintained
+F: hw/ppc_newworld.c
+
+Old World
+M: Alexander Graf <agraf at suse.de>
+S: Maintained
+F: hw/ppc_oldworld.c
+
+Prep
+M: qemu-devel at nongnu.org
+S: Orphan
+F: hw/ppc_prep.c
+
+SH4 Machines
+------------
+R2D
+M: Magnus Damm <magnus.damm at gmail.com>
+S: Maintained
+F: hw/r2d.c
+
+Shix
+M: Magnus Damm <magnus.damm at gmail.com>
+S: Oprhan
+F: hw/shix.c
+
+SPARC Machines
+--------------
+Sun4m
+M: Blue Swirl <blauwirbel at gmail.com>
+S: Maintained
+F: hw/sun4m.c
+
+Sun4u
+M: Blue Swirl <blauwirbel at gmail.com>
+S: Maintained
+F: hw/sun4u.c
+
+S390 Machines
+-------------
+S390 Virtio
+M: Alexander Graf <agraf at suse.de>
+S: Maintained
+F: hw/s390-*.c
+
+X86 Machines
+------------
+PC
+M: Anthony Liguori <aliguori at us.ibm.com>
+S: Supported
+F: hw/pc.[ch] hw/pc_piix.c
+
+Devices
+-------
+IDE
+M: Kevin Wolf <kwolf at redhat.com>
+S: Odd Fixes
+F: hw/ide/
+
+PCI
+M: Michael S. Tsirkin <mst at redhat.com>
+S: Supported
+F: hw/pci*
+F: hw/piix*
+
+SCSI
+M: Paul Brook <paul at codesourcery.com>
+M: Kevin Wolf <kwolf at redhat.com>
+S: Odd Fixes
+F: hw/lsi53c895a.c
+F: hw/scsi*
+
+USB
+M: qemu-devel at nongnu.org
+S: Odd Fixes
+F: hw/usb*
+
+vhost
+M: Michael S. Tsirkin <mst at redhat.com>
+S: Supported
+F: hw/vhost*
+
+virtio
+M: Anthony Liguori <aliguori at us.ibm.com>
+S: Supported
+F: hw/virtio*
+
+virtio-9p
+M: Venkateswararao Jujjuri (JV) <jvrao at linux.vnet.ibm.com>
+S: Supported
+F: hw/virtio-9p*
+
+virtio-blk
+M: Kevin Wolf <kwolf at redhat.com>
+S: Supported
+F: hw/virtio-blk*
+
+virtio-serial
+M: Amit Shah <amit.shah at redhat.com>
+S: Supported
+F: hw/virtio-serial*
+F: hw/virtio-console*
+
+Subsystems
+----------
+Audio
+M: Vassili Karpov (malc) <av1474 at comtv.ru>
+S: Maintained
+F: audio/
+
+Block
+M: Kevin Wolf <kwolf at redhat.com>
+S: Supported
+F: block*
+F: block/
+
+Character Devices
+M: Anthony Liguori <aliguori at us.ibm.com>
+S: Maintained
+F: qemu-char.c
+
+GDB stub
+M: qemu-devel at nongnu.org
+S: Odd Fixes
+F: gdbstub*
+F: gdb-xml/
+
+Graphics
+M: Anthony Liguori <aliguori at us.ibm.com>
+S: Maintained
+F: ui/
+
+Main loop
+M: Anthony Liguori <aliguori at us.ibm.com>
+S: Supported
+F: vl.c
+
+Monitor (QMP/HMP)
+M: Luiz Capitulino <lcapitulino at redhat.com>
+M: Markus Armbruster <armbru at redhat.com>
+S: Supported
+F: monitor.c
+
+Network device layer
+M: Anthony Liguori <aliguori at us.ibm.com>
+M: Mark McLoughlin <markmc at redhat.com>
+S: Maintained
+F: net/
+
+SLIRP
+M: qemu-devel at nongnu.org
+S: Orphan
+F: slirp/
+
+Usermode Emulation
+------------------
+BSD user
+M: Blue Swirl <blauwirbel at gmail.com>
+S: Maintained
+F: bsd-user/
+
+Darwin user
+M: qemu-devel at nongnu.org
+S: Orphan
+F: darwin-user/
+
+Linux user
+M: Riku Voipio <riku.voipio at iki.fi>
+S: Maintained
+F: linux-user/
commit b76876e602ca09ff848d99595a506feb1fd54ff4
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Nov 26 16:36:16 2010 +0100

    ide: Reset current_addr after stopping DMA
    
    Whenever SSBM is reset in the command register all state information is lost.
    Restarting DMA means that current_addr must be reset to the base address of the
    PRD table. The OS is not required to change the base address register before
    starting a DMA operation, it can reuse the value it wrote for an earlier
    request.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/ide/pci.c b/hw/ide/pci.c
index 404f045..ad406ee 100644
--- a/hw/ide/pci.c
+++ b/hw/ide/pci.c
@@ -65,6 +65,7 @@ void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val)
 #endif
             }
         } else {
+            bm->cur_addr = bm->addr;
             if (!(bm->status & BM_STATUS_DMAING)) {
                 bm->status |= BM_STATUS_DMAING;
                 /* start dma transfer if possible */
@@ -101,7 +102,6 @@ static void bmdma_addr_write(IORange *ioport, uint64_t addr,
 #endif
     bm->addr &= ~(mask << shift);
     bm->addr |= ((data & mask) << shift) & ~3;
-    bm->cur_addr = bm->addr;
 }
 
 const IORangeOps bmdma_addr_ioport_ops = {
commit c29947bbb0978d312074ec73be968bfab1b6c977
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Nov 26 16:44:53 2010 +0100

    ide: Ignore double DMA transfer starts/stops
    
    You can only start a DMA transfer if it's not running yet, and you can only
    cancel it if it's running.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/ide/pci.c b/hw/ide/pci.c
index 3722b77..404f045 100644
--- a/hw/ide/pci.c
+++ b/hw/ide/pci.c
@@ -39,38 +39,42 @@ void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val)
 #ifdef DEBUG_IDE
     printf("%s: 0x%08x\n", __func__, val);
 #endif
-    if (!(val & BM_CMD_START)) {
-        /*
-         * We can't cancel Scatter Gather DMA in the middle of the
-         * operation or a partial (not full) DMA transfer would reach
-         * the storage so we wait for completion instead (we beahve
-         * like if the DMA was completed by the time the guest trying
-         * to cancel dma with bmdma_cmd_writeb with BM_CMD_START not
-         * set).
-         *
-         * In the future we'll be able to safely cancel the I/O if the
-         * whole DMA operation will be submitted to disk with a single
-         * aio operation with preadv/pwritev.
-         */
-        if (bm->aiocb) {
-            qemu_aio_flush();
+
+    /* Ignore writes to SSBM if it keeps the old value */
+    if ((val & BM_CMD_START) != (bm->cmd & BM_CMD_START)) {
+        if (!(val & BM_CMD_START)) {
+            /*
+             * We can't cancel Scatter Gather DMA in the middle of the
+             * operation or a partial (not full) DMA transfer would reach
+             * the storage so we wait for completion instead (we beahve
+             * like if the DMA was completed by the time the guest trying
+             * to cancel dma with bmdma_cmd_writeb with BM_CMD_START not
+             * set).
+             *
+             * In the future we'll be able to safely cancel the I/O if the
+             * whole DMA operation will be submitted to disk with a single
+             * aio operation with preadv/pwritev.
+             */
+            if (bm->aiocb) {
+                qemu_aio_flush();
 #ifdef DEBUG_IDE
-            if (bm->aiocb)
-                printf("ide_dma_cancel: aiocb still pending");
-            if (bm->status & BM_STATUS_DMAING)
-                printf("ide_dma_cancel: BM_STATUS_DMAING still pending");
+                if (bm->aiocb)
+                    printf("ide_dma_cancel: aiocb still pending");
+                if (bm->status & BM_STATUS_DMAING)
+                    printf("ide_dma_cancel: BM_STATUS_DMAING still pending");
 #endif
+            }
+        } else {
+            if (!(bm->status & BM_STATUS_DMAING)) {
+                bm->status |= BM_STATUS_DMAING;
+                /* start dma transfer if possible */
+                if (bm->dma_cb)
+                    bm->dma_cb(bm, 0);
+            }
         }
-        bm->cmd = val & 0x09;
-    } else {
-        if (!(bm->status & BM_STATUS_DMAING)) {
-            bm->status |= BM_STATUS_DMAING;
-            /* start dma transfer if possible */
-            if (bm->dma_cb)
-                bm->dma_cb(bm, 0);
-        }
-        bm->cmd = val & 0x09;
     }
+
+    bm->cmd = val & 0x09;
 }
 
 static void bmdma_addr_read(IORange *ioport, uint64_t addr,
commit e3982b3cf6d17fbba6839d5252f5f757a8d585dc
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Nov 26 16:47:42 2010 +0100

    ide: Set bus master inactive on error
    
    BMIDEA in the status register must be cleared on error. This makes FreeBSD
    respond (more) correctly to I/O errors.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/ide/core.c b/hw/ide/core.c
index 7136ade..430350f 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -486,6 +486,8 @@ void ide_dma_error(IDEState *s)
     ide_transfer_stop(s);
     s->error = ABRT_ERR;
     s->status = READY_STAT | ERR_STAT;
+    ide_dma_set_inactive(s->bus->bmdma);
+    s->bus->bmdma->status |= BM_STATUS_INT;
     ide_set_irq(s->bus);
 }
 
commit 8337606d3588f80aea656db74127423bd6b61443
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Nov 26 16:31:37 2010 +0100

    ide: Factor ide_dma_set_inactive out
    
    Several places that stop a DMA transfer duplicate this code. Factor it out into
    a common function.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/hw/ide/core.c b/hw/ide/core.c
index 484e0ca..7136ade 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -473,6 +473,14 @@ static void dma_buf_commit(IDEState *s, int is_write)
     qemu_sglist_destroy(&s->sg);
 }
 
+static void ide_dma_set_inactive(BMDMAState *bm)
+{
+    bm->status &= ~BM_STATUS_DMAING;
+    bm->dma_cb = NULL;
+    bm->unit = -1;
+    bm->aiocb = NULL;
+}
+
 void ide_dma_error(IDEState *s)
 {
     ide_transfer_stop(s);
@@ -587,11 +595,8 @@ static void ide_read_dma_cb(void *opaque, int ret)
         s->status = READY_STAT | SEEK_STAT;
         ide_set_irq(s->bus);
     eot:
-        bm->status &= ~BM_STATUS_DMAING;
         bm->status |= BM_STATUS_INT;
-        bm->dma_cb = NULL;
-        bm->unit = -1;
-        bm->aiocb = NULL;
+        ide_dma_set_inactive(bm);
         return;
     }
 
@@ -733,11 +738,8 @@ static void ide_write_dma_cb(void *opaque, int ret)
         s->status = READY_STAT | SEEK_STAT;
         ide_set_irq(s->bus);
     eot:
-        bm->status &= ~BM_STATUS_DMAING;
         bm->status |= BM_STATUS_INT;
-        bm->dma_cb = NULL;
-        bm->unit = -1;
-        bm->aiocb = NULL;
+        ide_dma_set_inactive(bm);
         return;
     }
 
@@ -1061,11 +1063,8 @@ static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret)
         s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
         ide_set_irq(s->bus);
     eot:
-        bm->status &= ~BM_STATUS_DMAING;
         bm->status |= BM_STATUS_INT;
-        bm->dma_cb = NULL;
-        bm->unit = -1;
-        bm->aiocb = NULL;
+        ide_dma_set_inactive(bm);
         return;
     }
 
@@ -2954,12 +2953,10 @@ void ide_dma_cancel(BMDMAState *bm)
             printf("aio_cancel\n");
 #endif
             bdrv_aio_cancel(bm->aiocb);
-            bm->aiocb = NULL;
         }
-        bm->status &= ~BM_STATUS_DMAING;
+
         /* cancel DMA request */
-        bm->unit = -1;
-        bm->dma_cb = NULL;
+        ide_dma_set_inactive(bm);
     }
 }
 
commit 11a3cb8159278f7452b5bec8b9e17292a3ef53c3
Author: Christoph Hellwig <hch at lst.de>
Date:   Fri Nov 26 14:32:34 2010 +0100

    raw-posix: raw_pwrite comment fixup
    
    Signed-off-by: Christoph Hellwig <hch at lst.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/raw-posix.c b/block/raw-posix.c
index d0960b8..9286fb8 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -463,7 +463,7 @@ static int raw_pwrite(BlockDriverState *bs, int64_t offset,
                 count -= ret;
                 sum += ret;
             }
-            /* here, count < 512 because (count & ~sector_mask) == 0 */
+            /* here, count < sector_size because (count & ~sector_mask) == 0 */
             if (count) {
                 ret = raw_pread_aligned(bs, offset, s->aligned_buf,
                                      bs->buffer_alignment);
commit 2dd791b6302c73345f92dc9b107635787fcff938
Author: Hannes Reinecke <hare at suse.de>
Date:   Wed Nov 24 12:16:00 2010 +0100

    scsi-disk: Remove duplicate cdb parsing
    
    We parse the CDB twice, which is completely unnecessary.
    
    Signed-off-by: Hannes Reinecke <hare at suse.de>
    Acked-by: Christoph Hellwig <hch at lst.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index d692fb0..6e49404 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -1004,9 +1004,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
                                  uint8_t *buf, int lun)
 {
     SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
-    uint64_t lba;
     uint32_t len;
-    int cmdlen;
     int is_write;
     uint8_t command;
     uint8_t *outbuf;
@@ -1025,55 +1023,21 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
     outbuf = (uint8_t *)r->iov.iov_base;
     is_write = 0;
     DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", lun, tag, buf[0]);
-    switch (command >> 5) {
-    case 0:
-        lba = (uint64_t) buf[3] | ((uint64_t) buf[2] << 8) |
-              (((uint64_t) buf[1] & 0x1f) << 16);
-        len = buf[4];
-        cmdlen = 6;
-        break;
-    case 1:
-    case 2:
-        lba = (uint64_t) buf[5] | ((uint64_t) buf[4] << 8) |
-              ((uint64_t) buf[3] << 16) | ((uint64_t) buf[2] << 24);
-        len = buf[8] | (buf[7] << 8);
-        cmdlen = 10;
-        break;
-    case 4:
-        lba = (uint64_t) buf[9] | ((uint64_t) buf[8] << 8) |
-              ((uint64_t) buf[7] << 16) | ((uint64_t) buf[6] << 24) |
-              ((uint64_t) buf[5] << 32) | ((uint64_t) buf[4] << 40) |
-              ((uint64_t) buf[3] << 48) | ((uint64_t) buf[2] << 56);
-        len = buf[13] | (buf[12] << 8) | (buf[11] << 16) | (buf[10] << 24);
-        cmdlen = 16;
-        break;
-    case 5:
-        lba = (uint64_t) buf[5] | ((uint64_t) buf[4] << 8) |
-              ((uint64_t) buf[3] << 16) | ((uint64_t) buf[2] << 24);
-        len = buf[9] | (buf[8] << 8) | (buf[7] << 16) | (buf[6] << 24);
-        cmdlen = 12;
-        break;
-    default:
+
+    if (scsi_req_parse(&r->req, buf) != 0) {
         BADF("Unsupported command length, command %x\n", command);
         goto fail;
     }
 #ifdef DEBUG_SCSI
     {
         int i;
-        for (i = 1; i < cmdlen; i++) {
+        for (i = 1; i < r->req.cmd.len; i++) {
             printf(" 0x%02x", buf[i]);
         }
         printf("\n");
     }
 #endif
 
-    if (scsi_req_parse(&r->req, buf) != 0) {
-        BADF("Unsupported command length, command %x\n", command);
-        goto fail;
-    }
-    assert(r->req.cmd.len == cmdlen);
-    assert(r->req.cmd.lba == lba);
-
     if (lun || buf[1] >> 5) {
         /* Only LUN 0 supported.  */
         DPRINTF("Unimplemented LUN %d\n", lun ? lun : buf[1] >> 5);
@@ -1111,10 +1075,11 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
     case READ_10:
     case READ_12:
     case READ_16:
-        DPRINTF("Read (sector %" PRId64 ", count %d)\n", lba, len);
-        if (lba > s->max_lba)
+        len = r->req.cmd.xfer / d->blocksize;
+        DPRINTF("Read (sector %" PRId64 ", count %d)\n", r->req.cmd.lba, len);
+        if (r->req.cmd.lba > s->max_lba)
             goto illegal_lba;
-        r->sector = lba * s->cluster_size;
+        r->sector = r->req.cmd.lba * s->cluster_size;
         r->sector_count = len * s->cluster_size;
         break;
     case WRITE_6:
@@ -1124,42 +1089,45 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
     case WRITE_VERIFY:
     case WRITE_VERIFY_12:
     case WRITE_VERIFY_16:
+        len = r->req.cmd.xfer / d->blocksize;
         DPRINTF("Write %s(sector %" PRId64 ", count %d)\n",
-                (command & 0xe) == 0xe ? "And Verify " : "", lba, len);
-        if (lba > s->max_lba)
+                (command & 0xe) == 0xe ? "And Verify " : "",
+                r->req.cmd.lba, len);
+        if (r->req.cmd.lba > s->max_lba)
             goto illegal_lba;
-        r->sector = lba * s->cluster_size;
+        r->sector = r->req.cmd.lba * s->cluster_size;
         r->sector_count = len * s->cluster_size;
         is_write = 1;
         break;
     case MODE_SELECT:
-        DPRINTF("Mode Select(6) (len %d)\n", len);
+        DPRINTF("Mode Select(6) (len %lu)\n", (long)r->req.cmd.xfer);
         /* We don't support mode parameter changes.
            Allow the mode parameter header + block descriptors only. */
-        if (len > 12) {
+        if (r->req.cmd.xfer > 12) {
             goto fail;
         }
         break;
     case MODE_SELECT_10:
-        DPRINTF("Mode Select(10) (len %d)\n", len);
+        DPRINTF("Mode Select(10) (len %lu)\n", (long)r->req.cmd.xfer);
         /* We don't support mode parameter changes.
            Allow the mode parameter header + block descriptors only. */
-        if (len > 16) {
+        if (r->req.cmd.xfer > 16) {
             goto fail;
         }
         break;
     case SEEK_6:
     case SEEK_10:
-        DPRINTF("Seek(%d) (sector %" PRId64 ")\n", command == SEEK_6 ? 6 : 10, lba);
-        if (lba > s->max_lba) {
+        DPRINTF("Seek(%d) (sector %" PRId64 ")\n", command == SEEK_6 ? 6 : 10,
+                r->req.cmd.lba);
+        if (r->req.cmd.lba > s->max_lba) {
             goto illegal_lba;
         }
         break;
     default:
-	DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
+        DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
     fail:
         scsi_command_complete(r, CHECK_CONDITION, ILLEGAL_REQUEST);
-	return 0;
+        return 0;
     illegal_lba:
         scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
         return 0;
commit a6d96eb78bd1f87ab9d6a377f863f99be4b71538
Author: Hannes Reinecke <hare at suse.de>
Date:   Wed Nov 24 12:15:59 2010 +0100

    scsi: Move sense handling into the driver
    
    The current sense handling in scsi-bus is only used by the
    scsi-disk driver; the scsi-generic driver is using its own.
    So we should move the current sense handling into the
    scsi-disk driver.
    
    Signed-off-by: Hannes Reinecke <hare at suse.de>
    Acked-by: Christoph Hellwig <hch at lst.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 74a08b7..93f0e9a 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -123,16 +123,6 @@ int scsi_bus_legacy_handle_cmdline(SCSIBus *bus)
     return res;
 }
 
-void scsi_dev_clear_sense(SCSIDevice *dev)
-{
-    memset(&dev->sense, 0, sizeof(dev->sense));
-}
-
-void scsi_dev_set_sense(SCSIDevice *dev, uint8_t key)
-{
-    dev->sense.key = key;
-}
-
 SCSIRequest *scsi_req_alloc(size_t size, SCSIDevice *d, uint32_t tag, uint32_t lun)
 {
     SCSIRequest *req;
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index c41dcfc..d692fb0 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -49,6 +49,10 @@ do { fprintf(stderr, "scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
 
 typedef struct SCSIDiskState SCSIDiskState;
 
+typedef struct SCSISense {
+    uint8_t key;
+} SCSISense;
+
 typedef struct SCSIDiskReq {
     SCSIRequest req;
     /* ??? We should probably keep track of whether the data transfer is
@@ -72,6 +76,7 @@ struct SCSIDiskState
     QEMUBH *bh;
     char *version;
     char *serial;
+    SCSISense sense;
 };
 
 static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type);
@@ -100,10 +105,22 @@ static SCSIDiskReq *scsi_find_request(SCSIDiskState *s, uint32_t tag)
     return DO_UPCAST(SCSIDiskReq, req, scsi_req_find(&s->qdev, tag));
 }
 
-static void scsi_req_set_status(SCSIRequest *req, int status, int sense_code)
+static void scsi_disk_clear_sense(SCSIDiskState *s)
 {
-    req->status = status;
-    scsi_dev_set_sense(req->dev, sense_code);
+    memset(&s->sense, 0, sizeof(s->sense));
+}
+
+static void scsi_disk_set_sense(SCSIDiskState *s, uint8_t key)
+{
+    s->sense.key = key;
+}
+
+static void scsi_req_set_status(SCSIDiskReq *r, int status, int sense_code)
+{
+    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
+
+    r->req.status = status;
+    scsi_disk_set_sense(s, sense_code);
 }
 
 /* Helper function for command completion.  */
@@ -111,7 +128,7 @@ static void scsi_command_complete(SCSIDiskReq *r, int status, int sense)
 {
     DPRINTF("Command complete tag=0x%x status=%d sense=%d\n",
             r->req.tag, status, sense);
-    scsi_req_set_status(&r->req, status, sense);
+    scsi_req_set_status(r, status, sense);
     scsi_req_complete(&r->req);
     scsi_remove_request(r);
 }
@@ -822,7 +839,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf)
             goto illegal_request;
         memset(outbuf, 0, 4);
         buflen = 4;
-        if (req->dev->sense.key == NOT_READY && req->cmd.xfer >= 18) {
+        if (s->sense.key == NOT_READY && req->cmd.xfer >= 18) {
             memset(outbuf, 0, 18);
             buflen = 18;
             outbuf[7] = 10;
@@ -832,8 +849,8 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf)
         }
         outbuf[0] = 0xf0;
         outbuf[1] = 0;
-        outbuf[2] = req->dev->sense.key;
-        scsi_dev_clear_sense(req->dev);
+        outbuf[2] = s->sense.key;
+        scsi_disk_clear_sense(s);
         break;
     case INQUIRY:
         buflen = scsi_disk_emulate_inquiry(req, outbuf);
@@ -966,7 +983,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf)
     default:
         goto illegal_request;
     }
-    scsi_req_set_status(req, GOOD, NO_SENSE);
+    scsi_req_set_status(r, GOOD, NO_SENSE);
     return buflen;
 
 not_ready:
diff --git a/hw/scsi.h b/hw/scsi.h
index 9c798ae..bf02adf 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -26,10 +26,6 @@ enum SCSIXferMode {
     SCSI_XFER_TO_DEV,    /*  WRITE, MODE_SELECT, ...         */
 };
 
-typedef struct SCSISense {
-    uint8_t key;
-} SCSISense;
-
 typedef struct SCSIRequest {
     SCSIBus           *bus;
     SCSIDevice        *dev;
@@ -57,7 +53,6 @@ struct SCSIDevice
     QTAILQ_HEAD(, SCSIRequest) requests;
     int blocksize;
     int type;
-    struct SCSISense sense;
 };
 
 /* cdrom.c */
@@ -102,9 +97,6 @@ static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
 SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, int unit);
 int scsi_bus_legacy_handle_cmdline(SCSIBus *bus);
 
-void scsi_dev_clear_sense(SCSIDevice *dev);
-void scsi_dev_set_sense(SCSIDevice *dev, uint8_t key);
-
 SCSIRequest *scsi_req_alloc(size_t size, SCSIDevice *d, uint32_t tag, uint32_t lun);
 SCSIRequest *scsi_req_find(SCSIDevice *d, uint32_t tag);
 void scsi_req_free(SCSIRequest *req);
commit 39d989823f2c177415a22b84b354716a1f734b70
Author: Hannes Reinecke <hare at suse.de>
Date:   Wed Nov 24 12:15:58 2010 +0100

    scsi: INQUIRY VPD fixes
    
    We should announce and support the block device characterics page
    only on block devices, not on CDROMs. And the VPD page 0x83 has
    an off-by-one error.
    
    Signed-off-by: Hannes Reinecke <hare at suse.de>
    Acked-by: Christoph Hellwig <hch at lst.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 7d85899..c41dcfc 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -398,15 +398,20 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
 
         switch (page_code) {
         case 0x00: /* Supported page codes, mandatory */
+        {
+            int pages;
             DPRINTF("Inquiry EVPD[Supported pages] "
                     "buffer size %zd\n", req->cmd.xfer);
-            outbuf[buflen++] = 4;    // number of pages
+            pages = buflen++;
             outbuf[buflen++] = 0x00; // list of supported pages (this page)
             outbuf[buflen++] = 0x80; // unit serial number
             outbuf[buflen++] = 0x83; // device identification
-            outbuf[buflen++] = 0xb0; // block device characteristics
+            if (bdrv_get_type_hint(s->bs) != BDRV_TYPE_CDROM) {
+                outbuf[buflen++] = 0xb0; // block device characteristics
+            }
+            outbuf[pages] = buflen - pages - 1; // number of pages
             break;
-
+        }
         case 0x80: /* Device serial number, optional */
         {
             int l = strlen(s->serial);
@@ -434,7 +439,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
             DPRINTF("Inquiry EVPD[Device identification] "
                     "buffer size %zd\n", req->cmd.xfer);
 
-            outbuf[buflen++] = 3 + id_len;
+            outbuf[buflen++] = 4 + id_len;
             outbuf[buflen++] = 0x2; // ASCII
             outbuf[buflen++] = 0;   // not officially assigned
             outbuf[buflen++] = 0;   // reserved
@@ -451,6 +456,11 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
             unsigned int opt_io_size =
                     s->qdev.conf.opt_io_size / s->qdev.blocksize;
 
+            if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
+                DPRINTF("Inquiry (EVPD[%02X] not supported for CDROM\n",
+                        page_code);
+                return -1;
+            }
             /* required VPD size with unmap support */
             outbuf[3] = buflen = 0x3c;
 
commit f017132793065abcdc4b9b78d7ca575eeb3de484
Author: Hannes Reinecke <hare at suse.de>
Date:   Wed Nov 24 12:15:57 2010 +0100

    scsi: Return SAM status codes
    
    Traditionally, the linux stack is using SCSI status codes
    which are shifted by one as compared to those defined in SAM.
    A SCSI emulation should naturally return the SAM defined codes,
    not the linux ones.
    So to avoid any confusion this patch modifies the existing
    definitions to match those found in SAM and removes any
    (now obsolete) byte-shift from the returned status codes.
    
    Signed-off-by: Hannes Reinecke <hare at suse.de>
    Acked-by: Christoph Hellwig <hch at lst.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/scsi-defs.h b/hw/scsi-defs.h
index a4a3518..1473ecb 100644
--- a/hw/scsi-defs.h
+++ b/hw/scsi-defs.h
@@ -111,18 +111,20 @@
 #define BLANK 0xa1
 
 /*
- *  Status codes
+ *  SAM Status codes
  */
 
 #define GOOD                 0x00
-#define CHECK_CONDITION      0x01
-#define CONDITION_GOOD       0x02
-#define BUSY                 0x04
-#define INTERMEDIATE_GOOD    0x08
-#define INTERMEDIATE_C_GOOD  0x0a
-#define RESERVATION_CONFLICT 0x0c
-#define COMMAND_TERMINATED   0x11
-#define QUEUE_FULL           0x14
+#define CHECK_CONDITION      0x02
+#define CONDITION_GOOD       0x04
+#define BUSY                 0x08
+#define INTERMEDIATE_GOOD    0x10
+#define INTERMEDIATE_C_GOOD  0x14
+#define RESERVATION_CONFLICT 0x18
+#define COMMAND_TERMINATED   0x22
+#define TASK_SET_FULL        0x28
+#define ACA_ACTIVE           0x30
+#define TASK_ABORTED         0x40
 
 #define STATUS_MASK          0x3e
 
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index 7212091..9be1cca 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -96,17 +96,17 @@ static void scsi_command_complete(void *opaque, int ret)
         s->senselen = r->io_header.sb_len_wr;
 
     if (ret != 0)
-        r->req.status = BUSY << 1;
+        r->req.status = BUSY;
     else {
         if (s->driver_status & SG_ERR_DRIVER_TIMEOUT) {
-            r->req.status = BUSY << 1;
+            r->req.status = BUSY;
             BADF("Driver Timeout\n");
         } else if (r->io_header.status)
             r->req.status = r->io_header.status;
         else if (s->driver_status & SG_ERR_DRIVER_SENSE)
-            r->req.status = CHECK_CONDITION << 1;
+            r->req.status = CHECK_CONDITION;
         else
-            r->req.status = GOOD << 1;
+            r->req.status = GOOD;
     }
     DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
             r, r->req.tag, r->req.status);
@@ -333,7 +333,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
         s->senselen = 7;
         s->driver_status = SG_ERR_DRIVER_SENSE;
         bus = scsi_bus_from_device(d);
-        bus->complete(bus, SCSI_REASON_DONE, tag, CHECK_CONDITION << 1);
+        bus->complete(bus, SCSI_REASON_DONE, tag, CHECK_CONDITION);
         return 0;
     }
 
commit 622b520fb4ca50b5028485f1d225317ece0a42b9
Author: Hannes Reinecke <hare at suse.de>
Date:   Wed Nov 24 12:15:56 2010 +0100

    scsi: Increase the number of possible devices
    
    The SCSI parallel interface has a limit of 8 devices, but
    not the SCSI stack in general. So we should be removing the
    hard-coded limit and use MAX_SCSI_DEVS instead.
    And we only need to scan those devices which are allocated
    by the bus.
    
    Signed-off-by: Hannes Reinecke <hare at suse.de>
    Acked-by: Christoph Hellwig <hch at lst.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/blockdev.h b/blockdev.h
index 2a0559e..4cb8ca9 100644
--- a/blockdev.h
+++ b/blockdev.h
@@ -32,7 +32,7 @@ struct DriveInfo {
 };
 
 #define MAX_IDE_DEVS	2
-#define MAX_SCSI_DEVS	7
+#define MAX_SCSI_DEVS	255
 
 DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit);
 int drive_get_max_bus(BlockInterfaceType type);
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 5a3fd4b..74a08b7 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -108,7 +108,7 @@ int scsi_bus_legacy_handle_cmdline(SCSIBus *bus)
     int res = 0, unit;
 
     loc_push_none(&loc);
-    for (unit = 0; unit < MAX_SCSI_DEVS; unit++) {
+    for (unit = 0; unit < bus->ndev; unit++) {
         dinfo = drive_get(IF_SCSI, bus->busnr, unit);
         if (dinfo == NULL) {
             continue;
diff --git a/hw/scsi.h b/hw/scsi.h
index cb06d6d..9c798ae 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -3,6 +3,7 @@
 
 #include "qdev.h"
 #include "block.h"
+#include "blockdev.h"
 #include "block_int.h"
 
 #define SCSI_CMD_BUF_SIZE     16
@@ -86,7 +87,7 @@ struct SCSIBus {
     int tcq, ndev;
     scsi_completionfn complete;
 
-    SCSIDevice *devs[8];
+    SCSIDevice *devs[MAX_SCSI_DEVS];
 };
 
 void scsi_bus_new(SCSIBus *bus, DeviceState *host, int tcq, int ndev,
commit 80465c5016f23d8b39efb36db2ca77a35f67eaef
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Nov 16 18:55:01 2010 +0100

    block: Remove unused s->hd in various drivers
    
    All drivers use bs->file instead of s->hd for quite a while now, so it's time
    to remove s->hd.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/block/qcow.c b/block/qcow.c
index 9cd547d..f67d3d3 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -54,7 +54,6 @@ typedef struct QCowHeader {
 #define L2_CACHE_SIZE 16
 
 typedef struct BDRVQcowState {
-    BlockDriverState *hd;
     int cluster_bits;
     int cluster_size;
     int cluster_sectors;
diff --git a/block/qcow2.h b/block/qcow2.h
index 2d22e5e..5217bea 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -79,7 +79,6 @@ typedef struct QCowSnapshot {
 } QCowSnapshot;
 
 typedef struct BDRVQcowState {
-    BlockDriverState *hd;
     int cluster_bits;
     int cluster_size;
     int cluster_sectors;
diff --git a/block/vdi.c b/block/vdi.c
index 3b51e53..ab8f70f 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -186,7 +186,6 @@ typedef struct {
 } VdiHeader;
 
 typedef struct {
-    BlockDriverState *hd;
     /* The block map entries are little endian (even in memory). */
     uint32_t *bmap;
     /* Size of block (bytes). */
diff --git a/block/vmdk.c b/block/vmdk.c
index 872aeba..8fc9d67 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -61,7 +61,6 @@ typedef struct {
 #define L2_CACHE_SIZE 16
 
 typedef struct BDRVVmdkState {
-    BlockDriverState *hd;
     int64_t l1_table_offset;
     int64_t l1_backup_table_offset;
     uint32_t *l1_table;
diff --git a/block/vpc.c b/block/vpc.c
index 416f489..21e2a68 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -110,8 +110,6 @@ struct vhd_dyndisk_header {
 };
 
 typedef struct BDRVVPCState {
-    BlockDriverState *hd;
-
     uint8_t footer_buf[HEADER_SIZE];
     uint64_t free_data_block_offset;
     int max_table_entries;
commit 5cbdebe39e08caf5a373ef1c03a0292d5af955ce
Author: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
Date:   Wed Nov 24 13:08:03 2010 +0000

    qemu and qemu-xen: support empty write barriers in xen_disk
    
    This patch can be applied to both qemu-xen and qemu and adds support
    for empty write barriers to xen_disk.
    
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/xen_disk.c b/hw/xen_disk.c
index 134ac33..85a1c85 100644
--- a/hw/xen_disk.c
+++ b/hw/xen_disk.c
@@ -181,6 +181,10 @@ static int ioreq_parse(struct ioreq *ioreq)
 	ioreq->prot = PROT_WRITE; /* to memory */
 	break;
     case BLKIF_OP_WRITE_BARRIER:
+        if (!ioreq->req.nr_segments) {
+            ioreq->presync = 1;
+            return 0;
+        }
 	if (!syncwrite)
 	    ioreq->presync = ioreq->postsync = 1;
 	/* fall through */
@@ -305,7 +309,7 @@ static int ioreq_runio_qemu_sync(struct ioreq *ioreq)
     int i, rc, len = 0;
     off_t pos;
 
-    if (ioreq_map(ioreq) == -1)
+    if (ioreq->req.nr_segments && ioreq_map(ioreq) == -1)
 	goto err;
     if (ioreq->presync)
 	bdrv_flush(blkdev->bs);
@@ -329,6 +333,8 @@ static int ioreq_runio_qemu_sync(struct ioreq *ioreq)
 	break;
     case BLKIF_OP_WRITE:
     case BLKIF_OP_WRITE_BARRIER:
+        if (!ioreq->req.nr_segments)
+            break;
 	pos = ioreq->start;
 	for (i = 0; i < ioreq->v.niov; i++) {
 	    rc = bdrv_write(blkdev->bs, pos / BLOCK_SIZE,
@@ -386,7 +392,7 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq)
 {
     struct XenBlkDev *blkdev = ioreq->blkdev;
 
-    if (ioreq_map(ioreq) == -1)
+    if (ioreq->req.nr_segments && ioreq_map(ioreq) == -1)
 	goto err;
 
     ioreq->aio_inflight++;
@@ -403,6 +409,8 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq)
     case BLKIF_OP_WRITE:
     case BLKIF_OP_WRITE_BARRIER:
         ioreq->aio_inflight++;
+        if (!ioreq->req.nr_segments)
+            break;
         bdrv_aio_writev(blkdev->bs, ioreq->start / BLOCK_SIZE,
                         &ioreq->v, ioreq->v.size / BLOCK_SIZE,
                         qemu_aio_complete, ioreq);
commit 9fbef1ac7cc888f29435e9f636b5dd14cd3260df
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Nov 21 18:29:52 2010 +0200

    ide: convert bmdma address ioport to ioport_register()
    
    cmd646, via compile tested, pci lightly boot tested.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c
index ff80dd5..dfe6091 100644
--- a/hw/ide/cmd646.c
+++ b/hw/ide/cmd646.c
@@ -179,12 +179,8 @@ static void bmdma_map(PCIDevice *pci_dev, int region_num,
             register_ioport_read(addr, 4, 1, bmdma_readb_1, d);
         }
 
-        register_ioport_write(addr + 4, 4, 1, bmdma_addr_writeb, bm);
-        register_ioport_read(addr + 4, 4, 1, bmdma_addr_readb, bm);
-        register_ioport_write(addr + 4, 4, 2, bmdma_addr_writew, bm);
-        register_ioport_read(addr + 4, 4, 2, bmdma_addr_readw, bm);
-        register_ioport_write(addr + 4, 4, 4, bmdma_addr_writel, bm);
-        register_ioport_read(addr + 4, 4, 4, bmdma_addr_readl, bm);
+        iorange_init(&bm->addr_ioport, &bmdma_addr_ioport_ops, addr + 4, 4);
+        ioport_register(&bm->addr_ioport);
         addr += 8;
     }
 }
diff --git a/hw/ide/internal.h b/hw/ide/internal.h
index d652e06..85f4a16 100644
--- a/hw/ide/internal.h
+++ b/hw/ide/internal.h
@@ -8,6 +8,7 @@
  */
 #include <hw/ide.h>
 #include "block_int.h"
+#include "iorange.h"
 
 /* debug IDE devices */
 //#define DEBUG_IDE
@@ -496,6 +497,7 @@ struct BMDMAState {
     QEMUIOVector qiov;
     int64_t sector_num;
     uint32_t nsector;
+    IORange addr_ioport;
     QEMUBH *bh;
 };
 
diff --git a/hw/ide/pci.c b/hw/ide/pci.c
index ec90f26..3722b77 100644
--- a/hw/ide/pci.c
+++ b/hw/ide/pci.c
@@ -73,72 +73,37 @@ void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val)
     }
 }
 
-uint32_t bmdma_addr_readb(void *opaque, uint32_t addr)
+static void bmdma_addr_read(IORange *ioport, uint64_t addr,
+                            unsigned width, uint64_t *data)
 {
-    BMDMAState *bm = opaque;
-    uint32_t val;
-    val = (bm->addr >> ((addr & 3) * 8)) & 0xff;
-#ifdef DEBUG_IDE
-    printf("%s: 0x%08x\n", __func__, val);
-#endif
-    return val;
-}
+    BMDMAState *bm = container_of(ioport, BMDMAState, addr_ioport);
+    uint32_t mask = (1ULL << (width * 8)) - 1;
 
-void bmdma_addr_writeb(void *opaque, uint32_t addr, uint32_t val)
-{
-    BMDMAState *bm = opaque;
-    int shift = (addr & 3) * 8;
+    *data = (bm->addr >> (addr * 8)) & mask;
 #ifdef DEBUG_IDE
-    printf("%s: 0x%08x\n", __func__, val);
+    printf("%s: 0x%08x\n", __func__, (unsigned)*data);
 #endif
-    bm->addr &= ~(0xFF << shift);
-    bm->addr |= ((val & 0xFF) << shift) & ~3;
-    bm->cur_addr = bm->addr;
 }
 
-uint32_t bmdma_addr_readw(void *opaque, uint32_t addr)
+static void bmdma_addr_write(IORange *ioport, uint64_t addr,
+                             unsigned width, uint64_t data)
 {
-    BMDMAState *bm = opaque;
-    uint32_t val;
-    val = (bm->addr >> ((addr & 3) * 8)) & 0xffff;
-#ifdef DEBUG_IDE
-    printf("%s: 0x%08x\n", __func__, val);
-#endif
-    return val;
-}
+    BMDMAState *bm = container_of(ioport, BMDMAState, addr_ioport);
+    int shift = addr * 8;
+    uint32_t mask = (1ULL << (width * 8)) - 1;
 
-void bmdma_addr_writew(void *opaque, uint32_t addr, uint32_t val)
-{
-    BMDMAState *bm = opaque;
-    int shift = (addr & 3) * 8;
 #ifdef DEBUG_IDE
-    printf("%s: 0x%08x\n", __func__, val);
+    printf("%s: 0x%08x\n", __func__, (unsigned)data);
 #endif
-    bm->addr &= ~(0xFFFF << shift);
-    bm->addr |= ((val & 0xFFFF) << shift) & ~3;
+    bm->addr &= ~(mask << shift);
+    bm->addr |= ((data & mask) << shift) & ~3;
     bm->cur_addr = bm->addr;
 }
 
-uint32_t bmdma_addr_readl(void *opaque, uint32_t addr)
-{
-    BMDMAState *bm = opaque;
-    uint32_t val;
-    val = bm->addr;
-#ifdef DEBUG_IDE
-    printf("%s: 0x%08x\n", __func__, val);
-#endif
-    return val;
-}
-
-void bmdma_addr_writel(void *opaque, uint32_t addr, uint32_t val)
-{
-    BMDMAState *bm = opaque;
-#ifdef DEBUG_IDE
-    printf("%s: 0x%08x\n", __func__, val);
-#endif
-    bm->addr = val & ~3;
-    bm->cur_addr = bm->addr;
-}
+const IORangeOps bmdma_addr_ioport_ops = {
+    .read = bmdma_addr_read,
+    .write = bmdma_addr_write,
+};
 
 static bool ide_bmdma_current_needed(void *opaque)
 {
diff --git a/hw/ide/pci.h b/hw/ide/pci.h
index d46a95e..b81b26c 100644
--- a/hw/ide/pci.h
+++ b/hw/ide/pci.h
@@ -11,12 +11,7 @@ typedef struct PCIIDEState {
 } PCIIDEState;
 
 void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val);
-uint32_t bmdma_addr_readb(void *opaque, uint32_t addr);
-void bmdma_addr_writeb(void *opaque, uint32_t addr, uint32_t val);
-uint32_t bmdma_addr_readw(void *opaque, uint32_t addr);
-void bmdma_addr_writew(void *opaque, uint32_t addr, uint32_t val);
-uint32_t bmdma_addr_readl(void *opaque, uint32_t addr);
-void bmdma_addr_writel(void *opaque, uint32_t addr, uint32_t val);
+extern const IORangeOps bmdma_addr_ioport_ops;
 void pci_ide_create_devs(PCIDevice *dev, DriveInfo **hd_table);
 
 extern const VMStateDescription vmstate_ide_pci;
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index 07483e8..e02b89a 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -85,12 +85,8 @@ static void bmdma_map(PCIDevice *pci_dev, int region_num,
         register_ioport_write(addr + 1, 3, 1, bmdma_writeb, bm);
         register_ioport_read(addr, 4, 1, bmdma_readb, bm);
 
-        register_ioport_write(addr + 4, 4, 1, bmdma_addr_writeb, bm);
-        register_ioport_read(addr + 4, 4, 1, bmdma_addr_readb, bm);
-        register_ioport_write(addr + 4, 4, 2, bmdma_addr_writew, bm);
-        register_ioport_read(addr + 4, 4, 2, bmdma_addr_readw, bm);
-        register_ioport_write(addr + 4, 4, 4, bmdma_addr_writel, bm);
-        register_ioport_read(addr + 4, 4, 4, bmdma_addr_readl, bm);
+        iorange_init(&bm->addr_ioport, &bmdma_addr_ioport_ops, addr + 4, 4);
+        ioport_register(&bm->addr_ioport);
         addr += 8;
     }
 }
diff --git a/hw/ide/via.c b/hw/ide/via.c
index b2c7cad..3e41d00 100644
--- a/hw/ide/via.c
+++ b/hw/ide/via.c
@@ -87,12 +87,8 @@ static void bmdma_map(PCIDevice *pci_dev, int region_num,
         register_ioport_write(addr + 1, 3, 1, bmdma_writeb, bm);
         register_ioport_read(addr, 4, 1, bmdma_readb, bm);
 
-        register_ioport_write(addr + 4, 4, 1, bmdma_addr_writeb, bm);
-        register_ioport_read(addr + 4, 4, 1, bmdma_addr_readb, bm);
-        register_ioport_write(addr + 4, 4, 2, bmdma_addr_writew, bm);
-        register_ioport_read(addr + 4, 4, 2, bmdma_addr_readw, bm);
-        register_ioport_write(addr + 4, 4, 4, bmdma_addr_writel, bm);
-        register_ioport_read(addr + 4, 4, 4, bmdma_addr_readl, bm);
+        iorange_init(&bm->addr_ioport, &bmdma_addr_ioport_ops, addr + 4, 4);
+        ioport_register(&bm->addr_ioport);
         addr += 8;
     }
 }
commit 62155e2b51e3c282ddc30adbb6d7b8d3bb7c386e
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Fri Nov 12 16:07:50 2010 -0200

    block migration: do not submit multiple AIOs for same sector (v2)
    
    An old version of this patch was applied to master, so this contains the
    differences between v1 and v2.
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block-migration.c b/block-migration.c
index 3e66f49..1475325 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -146,8 +146,7 @@ static int bmds_aio_inflight(BlkMigDevState *bmds, int64_t sector)
 {
     int64_t chunk = sector / (int64_t)BDRV_SECTORS_PER_DIRTY_CHUNK;
 
-    if (bmds->aio_bitmap &&
-        (sector << BDRV_SECTOR_BITS) < bdrv_getlength(bmds->bs)) {
+    if ((sector << BDRV_SECTOR_BITS) < bdrv_getlength(bmds->bs)) {
         return !!(bmds->aio_bitmap[chunk / (sizeof(unsigned long) * 8)] &
             (1UL << (chunk % (sizeof(unsigned long) * 8))));
     } else {
@@ -169,13 +168,9 @@ static void bmds_set_aio_inflight(BlkMigDevState *bmds, int64_t sector_num,
         bit = start % (sizeof(unsigned long) * 8);
         val = bmds->aio_bitmap[idx];
         if (set) {
-            if (!(val & (1UL << bit))) {
-                val |= 1UL << bit;
-            }
+            val |= 1UL << bit;
         } else {
-            if (val & (1UL << bit)) {
-                val &= ~(1UL << bit);
-            }
+            val &= ~(1UL << bit);
         }
         bmds->aio_bitmap[idx] = val;
     }
@@ -385,8 +380,9 @@ static int mig_save_device_dirty(Monitor *mon, QEMUFile *f,
     int nr_sectors;
 
     for (sector = bmds->cur_dirty; sector < bmds->total_sectors;) {
-        if (bmds_aio_inflight(bmds, sector))
+        if (bmds_aio_inflight(bmds, sector)) {
             qemu_aio_flush();
+        }
         if (bdrv_get_dirty(bmds->bs, sector)) {
 
             if (total_sectors - sector < BDRV_SECTORS_PER_DIRTY_CHUNK) {
commit 9063f81415f3518ef8206e74085c2a92c96890a0
Author: Ryan Harper <ryanh at us.ibm.com>
Date:   Fri Nov 12 11:07:13 2010 -0600

    Implement drive_del to decouple block removal from device removal
    
    Currently device hotplug removal code is tied to device removal via
    ACPI.  All pci devices that are removable via device_del() require the
    guest to respond to the request.  In some cases the guest may not
    respond leaving the device still accessible to the guest.  The management
    layer doesn't currently have a reliable way to revoke access to host
    resource in the presence of an uncooperative guest.
    
    This patch implements a new monitor command, drive_del, which
    provides an explicit command to revoke access to a host block device.
    
    drive_del first quiesces the block device (qemu_aio_flush;
    bdrv_flush() and bdrv_close()).  This prevents further IO from being
    submitted against the host device.  Finally, drive_del cleans up
    pointers between the drive object (host resource) and the device
    object (guest resource).
    
    Signed-off-by: Ryan Harper <ryanh at us.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index 6cb179a..f6ac439 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -14,6 +14,8 @@
 #include "qemu-option.h"
 #include "qemu-config.h"
 #include "sysemu.h"
+#include "hw/qdev.h"
+#include "block_int.h"
 
 static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives);
 
@@ -597,3 +599,40 @@ int do_change_block(Monitor *mon, const char *device,
     }
     return monitor_read_bdrv_key_start(mon, bs, NULL, NULL);
 }
+
+int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
+{
+    const char *id = qdict_get_str(qdict, "id");
+    BlockDriverState *bs;
+    BlockDriverState **ptr;
+    Property *prop;
+
+    bs = bdrv_find(id);
+    if (!bs) {
+        qerror_report(QERR_DEVICE_NOT_FOUND, id);
+        return -1;
+    }
+
+    /* quiesce block driver; prevent further io */
+    qemu_aio_flush();
+    bdrv_flush(bs);
+    bdrv_close(bs);
+
+    /* clean up guest state from pointing to host resource by
+     * finding and removing DeviceState "drive" property */
+    for (prop = bs->peer->info->props; prop && prop->name; prop++) {
+        if (prop->info->type == PROP_TYPE_DRIVE) {
+            ptr = qdev_get_prop_ptr(bs->peer, prop);
+            if ((*ptr) == bs) {
+                bdrv_detach(bs, bs->peer);
+                *ptr = NULL;
+                break;
+            }
+        }
+    }
+
+    /* clean up host side */
+    drive_uninit(drive_get_by_blockdev(bs));
+
+    return 0;
+}
diff --git a/blockdev.h b/blockdev.h
index 653affc..2a0559e 100644
--- a/blockdev.h
+++ b/blockdev.h
@@ -51,5 +51,6 @@ int do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data);
 int do_block_set_passwd(Monitor *mon, const QDict *qdict, QObject **ret_data);
 int do_change_block(Monitor *mon, const char *device,
                     const char *filename, const char *fmt);
+int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
 
 #endif
diff --git a/hmp-commands.hx b/hmp-commands.hx
index e5585ba..23024ba 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -68,6 +68,24 @@ Eject a removable medium (use -f to force it).
 ETEXI
 
     {
+        .name       = "drive_del",
+        .args_type  = "id:s",
+        .params     = "device",
+        .help       = "remove host block device",
+        .user_print = monitor_user_noop,
+        .mhandler.cmd_new = do_drive_del,
+    },
+
+STEXI
+ at item drive_del @var{device}
+ at findex drive_del
+Remove host block device.  The result is that guest generated IO is no longer
+submitted against the host device underlying the disk.  Once a drive has
+been deleted, the QEMU Block layer returns -EIO which results in IO
+errors in the guest for applications that are reading/writing to the device.
+ETEXI
+
+    {
         .name       = "change",
         .args_type  = "device:B,target:F,arg:s?",
         .params     = "device filename [format]",
commit 6fa2c95f279dda62aa7e3292cc424ff3fab6a602
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Fri Nov 12 09:57:11 2010 +0000

    scsi-disk: Move active request asserts
    
    SCSI read/write requests should not be re-issued before the current
    fragment of I/O completes.  There are asserts in scsi-disk.c that guard
    this constraint but they trigger on SPARC Linux 2.4.  It turns out that
    the asserts are too early in the code path and don't allow for read
    requests to terminate.
    
    Only the read assert needs to be moved but move the write assert too for
    consistency.
    
    Reported-by: Nigel Horne <njh at bandsman.co.uk>
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index dc71957..7d85899 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -170,6 +170,9 @@ static void scsi_read_request(SCSIDiskReq *r)
         return;
     }
 
+    /* No data transfer may already be in progress */
+    assert(r->req.aiocb == NULL);
+
     n = r->sector_count;
     if (n > SCSI_DMA_BUF_SIZE / 512)
         n = SCSI_DMA_BUF_SIZE / 512;
@@ -197,9 +200,6 @@ static void scsi_read_data(SCSIDevice *d, uint32_t tag)
         return;
     }
 
-    /* No data transfer may already be in progress */
-    assert(r->req.aiocb == NULL);
-
     scsi_read_request(r);
 }
 
@@ -269,6 +269,9 @@ static void scsi_write_request(SCSIDiskReq *r)
     SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
     uint32_t n;
 
+    /* No data transfer may already be in progress */
+    assert(r->req.aiocb == NULL);
+
     n = r->iov.iov_len / 512;
     if (n) {
         qemu_iovec_init_external(&r->qiov, &r->iov, 1);
@@ -298,9 +301,6 @@ static int scsi_write_data(SCSIDevice *d, uint32_t tag)
         return 1;
     }
 
-    /* No data transfer may already be in progress */
-    assert(r->req.aiocb == NULL);
-
     scsi_write_request(r);
 
     return 0;
commit 1abeb5a65d515f8a8a9cfc4a82342f731bd9321f
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Tue Nov 23 21:55:39 2010 +0200

    virtio: fix up VQ checks
    
    When migration triggers before a VQ is initialized,
    base pa is 0 and last_used_index must be 0 too:
    we don't have a ring to compare to.
    
    Reported-by: Juan Quintela <quintela at redhat.com>
    Tested-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/virtio.c b/hw/virtio.c
index 849a60f..07dbf86 100644
--- a/hw/virtio.c
+++ b/hw/virtio.c
@@ -682,7 +682,6 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
     uint32_t features;
     uint32_t supported_features =
         vdev->binding->get_features(vdev->binding_opaque);
-    uint16_t num_heads;
 
     if (vdev->binding->load_config) {
         ret = vdev->binding->load_config(vdev->binding_opaque, f);
@@ -713,17 +712,23 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
         qemu_get_be16s(f, &vdev->vq[i].last_avail_idx);
 
         if (vdev->vq[i].pa) {
+            uint16_t nheads;
             virtqueue_init(&vdev->vq[i]);
-        }
-	num_heads = vring_avail_idx(&vdev->vq[i]) - vdev->vq[i].last_avail_idx;
-	/* Check it isn't doing very strange things with descriptor numbers. */
-	if (num_heads > vdev->vq[i].vring.num) {
-		error_report("VQ %d size 0x%x Guest index 0x%x "
-		             "inconsistent with Host index 0x%x: delta 0x%x",
-		             i, vdev->vq[i].vring.num,
-		             vring_avail_idx(&vdev->vq[i]),
-		             vdev->vq[i].last_avail_idx, num_heads);
-		return -1;
+            nheads = vring_avail_idx(&vdev->vq[i]) - vdev->vq[i].last_avail_idx;
+            /* Check it isn't doing very strange things with descriptor numbers. */
+            if (nheads > vdev->vq[i].vring.num) {
+                error_report("VQ %d size 0x%x Guest index 0x%x "
+                             "inconsistent with Host index 0x%x: delta 0x%x\n",
+                             i, vdev->vq[i].vring.num,
+                             vring_avail_idx(&vdev->vq[i]),
+                             vdev->vq[i].last_avail_idx, nheads);
+                return -1;
+            }
+        } else if (vdev->vq[i].last_avail_idx) {
+            error_report("VQ %d address 0x0 "
+                         "inconsistent with Host index 0x%x\n",
+                         i, vdev->vq[i].last_avail_idx);
+                return -1;
 	}
         if (vdev->binding->load_queue) {
             ret = vdev->binding->load_queue(vdev->binding_opaque, i, f);
commit ce67ed65000b8f56c6e0576a1a9d3c4b0f596f5c
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Mon Nov 15 20:44:36 2010 +0000

    virtio: Convert fprintf() to error_report()
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    (cherry picked from commit cd92f4cc22fbe12a7bf60c9430731f768dc1537c)

diff --git a/hw/virtio.c b/hw/virtio.c
index a2a657e..849a60f 100644
--- a/hw/virtio.c
+++ b/hw/virtio.c
@@ -14,6 +14,7 @@
 #include <inttypes.h>
 
 #include "trace.h"
+#include "qemu-error.h"
 #include "virtio.h"
 #include "sysemu.h"
 
@@ -253,8 +254,8 @@ static int virtqueue_num_heads(VirtQueue *vq, unsigned int idx)
 
     /* Check it isn't doing very strange things with descriptor numbers. */
     if (num_heads > vq->vring.num) {
-        fprintf(stderr, "Guest moved used index from %u to %u",
-                idx, vring_avail_idx(vq));
+        error_report("Guest moved used index from %u to %u",
+                     idx, vring_avail_idx(vq));
         exit(1);
     }
 
@@ -271,7 +272,7 @@ static unsigned int virtqueue_get_head(VirtQueue *vq, unsigned int idx)
 
     /* If their number is silly, that's a fatal mistake. */
     if (head >= vq->vring.num) {
-        fprintf(stderr, "Guest says index %u is available", head);
+        error_report("Guest says index %u is available", head);
         exit(1);
     }
 
@@ -293,7 +294,7 @@ static unsigned virtqueue_next_desc(target_phys_addr_t desc_pa,
     wmb();
 
     if (next >= max) {
-        fprintf(stderr, "Desc next is %u", next);
+        error_report("Desc next is %u", next);
         exit(1);
     }
 
@@ -320,13 +321,13 @@ int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes)
 
         if (vring_desc_flags(desc_pa, i) & VRING_DESC_F_INDIRECT) {
             if (vring_desc_len(desc_pa, i) % sizeof(VRingDesc)) {
-                fprintf(stderr, "Invalid size for indirect buffer table\n");
+                error_report("Invalid size for indirect buffer table");
                 exit(1);
             }
 
             /* If we've got too many, that implies a descriptor loop. */
             if (num_bufs >= max) {
-                fprintf(stderr, "Looped descriptor");
+                error_report("Looped descriptor");
                 exit(1);
             }
 
@@ -340,7 +341,7 @@ int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes)
         do {
             /* If we've got too many, that implies a descriptor loop. */
             if (++num_bufs > max) {
-                fprintf(stderr, "Looped descriptor");
+                error_report("Looped descriptor");
                 exit(1);
             }
 
@@ -374,7 +375,7 @@ void virtqueue_map_sg(struct iovec *sg, target_phys_addr_t *addr,
         len = sg[i].iov_len;
         sg[i].iov_base = cpu_physical_memory_map(addr[i], &len, is_write);
         if (sg[i].iov_base == NULL || len != sg[i].iov_len) {
-            fprintf(stderr, "virtio: trying to map MMIO memory\n");
+            error_report("virtio: trying to map MMIO memory");
             exit(1);
         }
     }
@@ -397,7 +398,7 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
 
     if (vring_desc_flags(desc_pa, i) & VRING_DESC_F_INDIRECT) {
         if (vring_desc_len(desc_pa, i) % sizeof(VRingDesc)) {
-            fprintf(stderr, "Invalid size for indirect buffer table\n");
+            error_report("Invalid size for indirect buffer table");
             exit(1);
         }
 
@@ -423,7 +424,7 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
 
         /* If we've got too many, that implies a descriptor loop. */
         if ((elem->in_num + elem->out_num) > max) {
-            fprintf(stderr, "Looped descriptor");
+            error_report("Looped descriptor");
             exit(1);
         }
     } while ((i = virtqueue_next_desc(desc_pa, i, max)) != max);
@@ -694,8 +695,8 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
     qemu_get_be16s(f, &vdev->queue_sel);
     qemu_get_be32s(f, &features);
     if (features & ~supported_features) {
-        fprintf(stderr, "Features 0x%x unsupported. Allowed features: 0x%x\n",
-                features, supported_features);
+        error_report("Features 0x%x unsupported. Allowed features: 0x%x",
+                     features, supported_features);
         return -1;
     }
     if (vdev->set_features)
@@ -717,11 +718,11 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
 	num_heads = vring_avail_idx(&vdev->vq[i]) - vdev->vq[i].last_avail_idx;
 	/* Check it isn't doing very strange things with descriptor numbers. */
 	if (num_heads > vdev->vq[i].vring.num) {
-		fprintf(stderr, "VQ %d size 0x%x Guest index 0x%x "
-                        "inconsistent with Host index 0x%x: delta 0x%x\n",
-			i, vdev->vq[i].vring.num,
-                        vring_avail_idx(&vdev->vq[i]),
-                        vdev->vq[i].last_avail_idx, num_heads);
+		error_report("VQ %d size 0x%x Guest index 0x%x "
+		             "inconsistent with Host index 0x%x: delta 0x%x",
+		             i, vdev->vq[i].vring.num,
+		             vring_avail_idx(&vdev->vq[i]),
+		             vdev->vq[i].last_avail_idx, num_heads);
 		return -1;
 	}
         if (vdev->binding->load_queue) {
commit 929176c3b9f8d5feec9395401f889a3bfb95e816
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Wed Nov 24 07:23:25 2010 +0200

    pci: fix bus walk under secondary bus reset
    
    Take into account secondary bus reset bit for
    bus walk: devices behind a reset bus should not
    respond to configuration cycles.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci.c b/hw/pci.c
index d02f980..0c15b13 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -1540,6 +1540,16 @@ void pci_bridge_update_mappings(PCIBus *b)
     }
 }
 
+/* Whether a given bus number is in range of the secondary
+ * bus of the given bridge device. */
+static bool pci_secondary_bus_in_range(PCIDevice *dev, int bus_num)
+{
+    return !(pci_get_word(dev->config + PCI_BRIDGE_CONTROL) &
+             PCI_BRIDGE_CTL_BUS_RESET) /* Don't walk the bus if it's reset. */ &&
+        dev->config[PCI_SECONDARY_BUS] < bus_num &&
+        bus_num <= dev->config[PCI_SUBORDINATE_BUS];
+}
+
 PCIBus *pci_find_bus(PCIBus *bus, int bus_num)
 {
     PCIBus *sec;
@@ -1552,20 +1562,21 @@ PCIBus *pci_find_bus(PCIBus *bus, int bus_num)
         return bus;
     }
 
+    /* Consider all bus numbers in range for the host pci bridge. */
+    if (bus->parent_dev &&
+        !pci_secondary_bus_in_range(bus->parent_dev, bus_num)) {
+        return NULL;
+    }
+
     /* try child bus */
-    if (!bus->parent_dev /* host pci bridge */ ||
-        (bus->parent_dev->config[PCI_SECONDARY_BUS] < bus_num &&
-         bus_num <= bus->parent_dev->config[PCI_SUBORDINATE_BUS])) {
-        for (; bus; bus = sec) {
-            QLIST_FOREACH(sec, &bus->child, sibling) {
-                assert(sec->parent_dev);
-                if (sec->parent_dev->config[PCI_SECONDARY_BUS] == bus_num) {
-                    return sec;
-                }
-                if (sec->parent_dev->config[PCI_SECONDARY_BUS] < bus_num &&
-                    bus_num <= sec->parent_dev->config[PCI_SUBORDINATE_BUS]) {
-                    break;
-                }
+    for (; bus; bus = sec) {
+        QLIST_FOREACH(sec, &bus->child, sibling) {
+            assert(sec->parent_dev);
+            if (sec->parent_dev->config[PCI_SECONDARY_BUS] == bus_num) {
+                return sec;
+            }
+            if (pci_secondary_bus_in_range(sec->parent_dev, bus_num)) {
+                break;
             }
         }
     }
commit a5fce077b134a486794b77b49f4eae1d3c9b960c
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri Nov 19 18:56:03 2010 +0900

    pci bridge: implement secondary bus reset
    
    Trigger secondary bus reset when secondary bus reset bit
    value changes from 0 to 1.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci_bridge.c b/hw/pci_bridge.c
index 58cc2e4..464d897 100644
--- a/hw/pci_bridge.c
+++ b/hw/pci_bridge.c
@@ -139,6 +139,10 @@ pcibus_t pci_bridge_get_limit(const PCIDevice *bridge, uint8_t type)
 void pci_bridge_write_config(PCIDevice *d,
                              uint32_t address, uint32_t val, int len)
 {
+    PCIBridge *s = container_of(d, PCIBridge, dev);
+    uint16_t oldctl = pci_get_word(d->config + PCI_BRIDGE_CONTROL);
+    uint16_t newctl;
+
     pci_default_write_config(d, address, val, len);
 
     if (/* io base/limit */
@@ -147,9 +151,14 @@ void pci_bridge_write_config(PCIDevice *d,
         /* memory base/limit, prefetchable base/limit and
            io base/limit upper 16 */
         ranges_overlap(address, len, PCI_MEMORY_BASE, 20)) {
-        PCIBridge *s = container_of(d, PCIBridge, dev);
         pci_bridge_update_mappings(&s->sec_bus);
     }
+
+    newctl = pci_get_word(d->config + PCI_BRIDGE_CONTROL);
+    if (~oldctl & newctl & PCI_BRIDGE_CTL_BUS_RESET) {
+        /* Trigger hot reset on 0->1 transition. */
+        pci_bus_reset(&s->sec_bus);
+    }
 }
 
 void pci_bridge_disable_base_limit(PCIDevice *dev)
commit 9bb3358627d87d8de25fb41b7276575539d799a7
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri Nov 19 18:56:02 2010 +0900

    pci: use qdev reset framework for pci bus reset
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci.c b/hw/pci.c
index c0a8258..d02f980 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -43,12 +43,14 @@
 
 static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent);
 static char *pcibus_get_dev_path(DeviceState *dev);
+static int pcibus_reset(BusState *qbus);
 
 struct BusInfo pci_bus_info = {
     .name       = "PCI",
     .size       = sizeof(PCIBus),
     .print_dev  = pcibus_dev_print,
     .get_dev_path = pcibus_get_dev_path,
+    .reset      = pcibus_reset,
     .props      = (Property[]) {
         DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1),
         DEFINE_PROP_STRING("romfile", PCIDevice, romfile),
@@ -136,6 +138,11 @@ static void pci_update_irq_status(PCIDevice *dev)
 static void pci_device_reset(PCIDevice *dev)
 {
     int r;
+    /* TODO: call the below unconditionally once all pci devices
+     * are qdevified */
+    if (dev->qdev.info) {
+        qdev_reset_all(&dev->qdev);
+    }
 
     dev->irq_state = 0;
     pci_update_irq_status(dev);
@@ -164,9 +171,12 @@ static void pci_device_reset(PCIDevice *dev)
     pci_update_mappings(dev);
 }
 
-static void pci_bus_reset(void *opaque)
+/*
+ * Trigger pci bus reset under a given bus.
+ * To be called on RST# assert.
+ */
+void pci_bus_reset(PCIBus *bus)
 {
-    PCIBus *bus = opaque;
     int i;
 
     for (i = 0; i < bus->nirq; i++) {
@@ -179,6 +189,15 @@ static void pci_bus_reset(void *opaque)
     }
 }
 
+static int pcibus_reset(BusState *qbus)
+{
+    pci_bus_reset(DO_UPCAST(PCIBus, qbus, qbus));
+
+    /* topology traverse is done by pci_bus_reset().
+       Tell qbus/qdev walker not to traverse the tree */
+    return 1;
+}
+
 static void pci_host_bus_register(int domain, PCIBus *bus)
 {
     struct PCIHostBus *host;
@@ -233,7 +252,6 @@ void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
     pci_host_bus_register(0, bus); /* for now only pci domain 0 is supported */
 
     vmstate_register(NULL, -1, &vmstate_pcibus, bus);
-    qemu_register_reset(pci_bus_reset, bus);
 }
 
 PCIBus *pci_bus_new(DeviceState *parent, const char *name, int devfn_min)
diff --git a/hw/pci.h b/hw/pci.h
index 09b3e4c..89f7b76 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -232,6 +232,7 @@ void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *dev);
 PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
                          void *irq_opaque, int devfn_min, int nirq);
+void pci_bus_reset(PCIBus *bus);
 
 void pci_bus_set_mem_base(PCIBus *bus, target_phys_addr_t base);
 
commit 5af0a04bea1f1704432b7c118c00a466e862bf00
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri Nov 19 18:56:01 2010 +0900

    qdev: trigger reset from a given device
    
    Introduce a helper function which triggers reset from a given device.
    Will be used by pci bus emulation.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/qdev.c b/hw/qdev.c
index b76da07..b65b63e 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -322,6 +322,11 @@ static int qbus_reset_one(BusState *bus, void *opaque)
     return 0;
 }
 
+void qdev_reset_all(DeviceState *dev)
+{
+    qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
+}
+
 void qbus_reset_all(BusState *bus)
 {
     qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
diff --git a/hw/qdev.h b/hw/qdev.h
index 5ac084f..3fac364 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -189,6 +189,7 @@ int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
                        qbus_walkerfn *busfn, void *opaque);
 int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
                        qbus_walkerfn *busfn, void *opaque);
+void qdev_reset_all(DeviceState *dev);
 void qbus_reset_all(BusState *bus);
 void qbus_free(BusState *bus);
 
commit b4694b7ce8bd87c4b9c6c14ad74075a31b15c784
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri Nov 19 18:56:00 2010 +0900

    qdev: introduce reset call back for qbus level
    
    and make it called via qbus_reset_all().
    The qbus reset callback will be used by pci bus reset.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/qdev.c b/hw/qdev.c
index 92ccc8d..b76da07 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -314,9 +314,17 @@ BusState *sysbus_get_default(void)
     return main_system_bus;
 }
 
+static int qbus_reset_one(BusState *bus, void *opaque)
+{
+    if (bus->info->reset) {
+        return bus->info->reset(bus);
+    }
+    return 0;
+}
+
 void qbus_reset_all(BusState *bus)
 {
-    qbus_walk_children(bus, qdev_reset_one, NULL, NULL);
+    qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
 }
 
 /* can be used as ->unplug() callback for the simple cases */
diff --git a/hw/qdev.h b/hw/qdev.h
index e5ed333..5ac084f 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -49,12 +49,14 @@ struct DeviceState {
 
 typedef void (*bus_dev_printfn)(Monitor *mon, DeviceState *dev, int indent);
 typedef char *(*bus_get_dev_path)(DeviceState *dev);
+typedef int (qbus_resetfn)(BusState *bus);
 
 struct BusInfo {
     const char *name;
     size_t size;
     bus_dev_printfn print_dev;
     bus_get_dev_path get_dev_path;
+    qbus_resetfn *reset;
     Property *props;
 };
 
commit ec990eb622ad46df5ddcb1e94c418c271894d416
Author: Anthony Liguori <anthony at codemonkey.ws>
Date:   Fri Nov 19 18:55:59 2010 +0900

    qdev: reset qdev along with qdev tree
    
    This patch changes the reset handling so that qdev has no knowledge of the
    global system reset.  Instead, a new bus/device level function is introduced
    that allows all devices/buses on the bus/device to be reset using a depth
    first transversal.
    
    N.B. we have to expose the implicit system bus because we have various hacks
    that result in an implicit system bus existing.  Instead, we ought to have an
    explicitly created system bus that we can trigger reset from.  That's a topic
    for a future patch though.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/qdev.c b/hw/qdev.c
index 11d845a..92ccc8d 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -257,13 +257,6 @@ DeviceState *qdev_device_add(QemuOpts *opts)
     return qdev;
 }
 
-static void qdev_reset(void *opaque)
-{
-    DeviceState *dev = opaque;
-    if (dev->info->reset)
-        dev->info->reset(dev);
-}
-
 /* Initialize a device.  Device properties should be set before calling
    this function.  IRQs and MMIO regions should be connected/mapped after
    calling this function.
@@ -279,7 +272,6 @@ int qdev_init(DeviceState *dev)
         qdev_free(dev);
         return rc;
     }
-    qemu_register_reset(qdev_reset, dev);
     if (dev->info->vmsd) {
         vmstate_register_with_alias_id(dev, -1, dev->info->vmsd, dev,
                                        dev->instance_id_alias,
@@ -308,6 +300,25 @@ int qdev_unplug(DeviceState *dev)
     return dev->info->unplug(dev);
 }
 
+static int qdev_reset_one(DeviceState *dev, void *opaque)
+{
+    if (dev->info->reset) {
+        dev->info->reset(dev);
+    }
+
+    return 0;
+}
+
+BusState *sysbus_get_default(void)
+{
+    return main_system_bus;
+}
+
+void qbus_reset_all(BusState *bus)
+{
+    qbus_walk_children(bus, qdev_reset_one, NULL, NULL);
+}
+
 /* can be used as ->unplug() callback for the simple cases */
 int qdev_simple_unplug_cb(DeviceState *dev)
 {
@@ -351,7 +362,6 @@ void qdev_free(DeviceState *dev)
         if (dev->opts)
             qemu_opts_del(dev->opts);
     }
-    qemu_unregister_reset(qdev_reset, dev);
     QLIST_REMOVE(dev, sibling);
     for (prop = dev->info->props; prop && prop->name; prop++) {
         if (prop->info->free) {
diff --git a/hw/qdev.h b/hw/qdev.h
index 550fd9b..e5ed333 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -187,10 +187,14 @@ int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
                        qbus_walkerfn *busfn, void *opaque);
 int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
                        qbus_walkerfn *busfn, void *opaque);
+void qbus_reset_all(BusState *bus);
 void qbus_free(BusState *bus);
 
 #define FROM_QBUS(type, dev) DO_UPCAST(type, qbus, dev)
 
+/* This should go away once we get rid of the NULL bus hack */
+BusState *sysbus_get_default(void);
+
 /*** monitor commands ***/
 
 void do_info_qtree(Monitor *mon);
diff --git a/vl.c b/vl.c
index c58583d..135fdeb 100644
--- a/vl.c
+++ b/vl.c
@@ -2976,6 +2976,7 @@ int main(int argc, char **argv, char **envp)
         exit(1);
     }
 
+    qemu_register_reset((void *)qbus_reset_all, sysbus_get_default());
     qemu_system_reset();
     if (loadvm) {
         if (load_vmstate(loadvm) < 0) {
commit 81699d8a90deac361e9e14fd853f8341f40b2fad
Author: Anthony Liguori <anthony at codemonkey.ws>
Date:   Fri Nov 19 18:55:58 2010 +0900

    qbus: add functions to walk both devices and busses
    
    There are some cases where you want to walk the busses, in particular, when
    searching for a bus either by name or DeviceInfo.
    Paolo suggested that we model the return values on how GCC's walkers work which
    allows an actor to skip child transversal, or terminate walking with a positive
    value that's returned as the qbus_walk_children's result.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/qdev.c b/hw/qdev.c
index 35858cb..11d845a 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -449,6 +449,52 @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
     return NULL;
 }
 
+int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
+                       qbus_walkerfn *busfn, void *opaque)
+{
+    DeviceState *dev;
+    int err;
+
+    if (busfn) {
+        err = busfn(bus, opaque);
+        if (err) {
+            return err;
+        }
+    }
+
+    QLIST_FOREACH(dev, &bus->children, sibling) {
+        err = qdev_walk_children(dev, devfn, busfn, opaque);
+        if (err < 0) {
+            return err;
+        }
+    }
+
+    return 0;
+}
+
+int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
+                       qbus_walkerfn *busfn, void *opaque)
+{
+    BusState *bus;
+    int err;
+
+    if (devfn) {
+        err = devfn(dev, opaque);
+        if (err) {
+            return err;
+        }
+    }
+
+    QLIST_FOREACH(bus, &dev->child_bus, sibling) {
+        err = qbus_walk_children(bus, devfn, busfn, opaque);
+        if (err < 0) {
+            return err;
+        }
+    }
+
+    return 0;
+}
+
 static BusState *qbus_find_recursive(BusState *bus, const char *name,
                                      const BusInfo *info)
 {
diff --git a/hw/qdev.h b/hw/qdev.h
index 579328a..550fd9b 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -173,9 +173,20 @@ BusState *qdev_get_parent_bus(DeviceState *dev);
 
 /*** BUS API. ***/
 
+/* Returns 0 to walk children, > 0 to skip walk, < 0 to terminate walk. */
+typedef int (qbus_walkerfn)(BusState *bus, void *opaque);
+typedef int (qdev_walkerfn)(DeviceState *dev, void *opaque);
+
 void qbus_create_inplace(BusState *bus, BusInfo *info,
                          DeviceState *parent, const char *name);
 BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name);
+/* Returns > 0 if either devfn or busfn skip walk somewhere in cursion,
+ *         < 0 if either devfn or busfn terminate walk somewhere in cursion,
+ *           0 otherwise. */
+int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
+                       qbus_walkerfn *busfn, void *opaque);
+int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
+                       qbus_walkerfn *busfn, void *opaque);
 void qbus_free(BusState *bus);
 
 #define FROM_QBUS(type, dev) DO_UPCAST(type, qbus, dev)
commit 0389ced419d249d8742c69e177731b5d18ef3f2f
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Fri Oct 15 22:51:07 2010 +0200

    eepro100: Use a single rom file for all i825xx devices
    
    Patching the rom data during load (in qemu) now
    also supports i82801 (which had no rom file).
    
    We only need a single rom file for the whole device family,
    so remove the second one which is no longer needed.
    
    Cc: Markus Armbruster <armbru at redhat.com>
    Cc: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/Makefile b/Makefile
index 02698e9..2883d27 100644
--- a/Makefile
+++ b/Makefile
@@ -181,7 +181,6 @@ ifdef INSTALL_BLOBS
 BLOBS=bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \
 openbios-sparc32 openbios-sparc64 openbios-ppc \
 gpxe-eepro100-80861209.rom \
-gpxe-eepro100-80861229.rom \
 pxe-e1000.bin \
 pxe-ne2k_pci.bin pxe-pcnet.bin \
 pxe-rtl8139.bin pxe-virtio.bin \
diff --git a/hw/eepro100.c b/hw/eepro100.c
index 41d792a..f8a700a 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -2048,17 +2048,9 @@ static void eepro100_register_devices(void)
     size_t i;
     for (i = 0; i < ARRAY_SIZE(e100_devices); i++) {
         PCIDeviceInfo *pci_dev = &e100_devices[i].pci;
-        switch (e100_devices[i].device_id) {
-            case PCI_DEVICE_ID_INTEL_82551IT:
-                pci_dev->romfile = "gpxe-eepro100-80861209.rom";
-                break;
-            case PCI_DEVICE_ID_INTEL_82557:
-                pci_dev->romfile = "gpxe-eepro100-80861229.rom";
-                break;
-            case 0x2449:
-                pci_dev->romfile = "gpxe-eepro100-80862449.rom";
-                break;
-        }
+        /* We use the same rom file for all device ids.
+           QEMU fixes the device id during rom load. */
+        pci_dev->romfile = "gpxe-eepro100-80861209.rom";
         pci_dev->init = e100_nic_init;
         pci_dev->exit = pci_nic_uninit;
         pci_dev->qdev.props = e100_properties;
diff --git a/pc-bios/README b/pc-bios/README
index 3172cf7..4b019e0 100644
--- a/pc-bios/README
+++ b/pc-bios/README
@@ -16,7 +16,7 @@
 - The PXE roms come from Rom-o-Matic gPXE 0.9.9 with BANNER_TIMEOUT=0
 
   e1000 8086:100E
-  eepro100 8086:1209, 8086:1229
+  eepro100 8086:1209 (also used for 8086:1229 and 8086:2449)
   ns8390 1050:0940
   pcnet32 1022:2000
   rtl8139 10ec:8139
diff --git a/pc-bios/gpxe-eepro100-80861229.rom b/pc-bios/gpxe-eepro100-80861229.rom
deleted file mode 100644
index 9cf397e..0000000
Binary files a/pc-bios/gpxe-eepro100-80861229.rom and /dev/null differ
commit ab85ceb1ad8797af2fb4c06bdc70f0ce0cf9b34f
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Tue Oct 19 23:08:21 2010 +0200

    pci: Automatically patch PCI vendor id and device id in PCI ROM
    
    PCI devices with different vendor or device ids sometimes share
    the same rom code. Only the ids and the checksum
    differs in a boot rom for such devices.
    
    The i825xx ethernet controller family is a typical example
    which is implemented in hw/eepro100.c. It uses at least
    3 different device ids, so normally 3 boot roms would be needed.
    
    By automatically patching vendor id and device id (and the checksum)
    in qemu, all emulated family members can share the same boot rom.
    
    VGA bios roms are another example with different vendor and device ids.
    
    Only qemu's built-in default rom files will be patched.
    
    v2:
        * Patch also the vendor id (and remove the sanity check for vendor id).
    
    v3:
        * Don't patch a rom file when its name was set by the user.
          Thus we avoid modifications of unknown rom data.
    
    Cc: Gerd Hoffmann <kraxel at redhat.com>
    Cc: Markus Armbruster <armbru at redhat.com>
    Cc: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci.c b/hw/pci.c
index fc5d340..c0a8258 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -61,7 +61,7 @@ struct BusInfo pci_bus_info = {
 
 static void pci_update_mappings(PCIDevice *d);
 static void pci_set_irq(void *opaque, int irq_num, int level);
-static int pci_add_option_rom(PCIDevice *pdev);
+static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom);
 static void pci_del_option_rom(PCIDevice *pdev);
 
 static uint16_t pci_default_sub_vendor_id = PCI_SUBVENDOR_ID_REDHAT_QUMRANET;
@@ -1571,6 +1571,7 @@ static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
     PCIDeviceInfo *info = container_of(base, PCIDeviceInfo, qdev);
     PCIBus *bus;
     int devfn, rc;
+    bool is_default_rom;
 
     /* initialize cap_present for pci_is_express() and pci_config_size() */
     if (info->is_express) {
@@ -1591,9 +1592,12 @@ static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
     }
 
     /* rom loading */
-    if (pci_dev->romfile == NULL && info->romfile != NULL)
+    is_default_rom = false;
+    if (pci_dev->romfile == NULL && info->romfile != NULL) {
         pci_dev->romfile = qemu_strdup(info->romfile);
-    pci_add_option_rom(pci_dev);
+        is_default_rom = true;
+    }
+    pci_add_option_rom(pci_dev, is_default_rom);
 
     if (bus->hotplug) {
         /* Let buses differentiate between hotplug and when device is
@@ -1701,8 +1705,64 @@ static void pci_map_option_rom(PCIDevice *pdev, int region_num, pcibus_t addr, p
     cpu_register_physical_memory(addr, size, pdev->rom_offset);
 }
 
+/* Patch the PCI vendor and device ids in a PCI rom image if necessary.
+   This is needed for an option rom which is used for more than one device. */
+static void pci_patch_ids(PCIDevice *pdev, uint8_t *ptr, int size)
+{
+    uint16_t vendor_id;
+    uint16_t device_id;
+    uint16_t rom_vendor_id;
+    uint16_t rom_device_id;
+    uint16_t rom_magic;
+    uint16_t pcir_offset;
+    uint8_t checksum;
+
+    /* Words in rom data are little endian (like in PCI configuration),
+       so they can be read / written with pci_get_word / pci_set_word. */
+
+    /* Only a valid rom will be patched. */
+    rom_magic = pci_get_word(ptr);
+    if (rom_magic != 0xaa55) {
+        PCI_DPRINTF("Bad ROM magic %04x\n", rom_magic);
+        return;
+    }
+    pcir_offset = pci_get_word(ptr + 0x18);
+    if (pcir_offset + 8 >= size || memcmp(ptr + pcir_offset, "PCIR", 4)) {
+        PCI_DPRINTF("Bad PCIR offset 0x%x or signature\n", pcir_offset);
+        return;
+    }
+
+    vendor_id = pci_get_word(pdev->config + PCI_VENDOR_ID);
+    device_id = pci_get_word(pdev->config + PCI_DEVICE_ID);
+    rom_vendor_id = pci_get_word(ptr + pcir_offset + 4);
+    rom_device_id = pci_get_word(ptr + pcir_offset + 6);
+
+    PCI_DPRINTF("%s: ROM id %04x%04x / PCI id %04x%04x\n", pdev->romfile,
+                vendor_id, device_id, rom_vendor_id, rom_device_id);
+
+    checksum = ptr[6];
+
+    if (vendor_id != rom_vendor_id) {
+        /* Patch vendor id and checksum (at offset 6 for etherboot roms). */
+        checksum += (uint8_t)rom_vendor_id + (uint8_t)(rom_vendor_id >> 8);
+        checksum -= (uint8_t)vendor_id + (uint8_t)(vendor_id >> 8);
+        PCI_DPRINTF("ROM checksum %02x / %02x\n", ptr[6], checksum);
+        ptr[6] = checksum;
+        pci_set_word(ptr + pcir_offset + 4, vendor_id);
+    }
+
+    if (device_id != rom_device_id) {
+        /* Patch device id and checksum (at offset 6 for etherboot roms). */
+        checksum += (uint8_t)rom_device_id + (uint8_t)(rom_device_id >> 8);
+        checksum -= (uint8_t)device_id + (uint8_t)(device_id >> 8);
+        PCI_DPRINTF("ROM checksum %02x / %02x\n", ptr[6], checksum);
+        ptr[6] = checksum;
+        pci_set_word(ptr + pcir_offset + 6, device_id);
+    }
+}
+
 /* Add an option rom for the device */
-static int pci_add_option_rom(PCIDevice *pdev)
+static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom)
 {
     int size;
     char *path;
@@ -1753,6 +1813,11 @@ static int pci_add_option_rom(PCIDevice *pdev)
     load_image(path, ptr);
     qemu_free(path);
 
+    if (is_default_rom) {
+        /* Only the default rom images will be patched (if needed). */
+        pci_patch_ids(pdev, ptr, size);
+    }
+
     pci_register_bar(pdev, PCI_ROM_SLOT, size,
                      0, pci_map_option_rom);
 
commit b90c73cf475d69959dde208d00961c3cb7a57475
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Fri Nov 19 19:29:07 2010 +0100

    pci: Replace unneeded type casts in calls of pci_register_bar
    
    There is no need for these type casts (as other existing
    code shows). So re-write the first argument without
    type cast (and remove a related TODO comment).
    
    Cc: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index aadc56f..40be55d 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -3204,10 +3204,10 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
      /* memory #0 LFB */
      /* memory #1 memory-mapped I/O */
      /* XXX: s->vga.vram_size must be a power of two */
-     pci_register_bar((PCIDevice *)d, 0, 0x2000000,
+     pci_register_bar(&d->dev, 0, 0x2000000,
                       PCI_BASE_ADDRESS_MEM_PREFETCH, cirrus_pci_lfb_map);
      if (device_id == CIRRUS_ID_CLGD5446) {
-         pci_register_bar((PCIDevice *)d, 1, CIRRUS_PNPMMIO_SIZE,
+         pci_register_bar(&d->dev, 1, CIRRUS_PNPMMIO_SIZE,
                           PCI_BASE_ADDRESS_SPACE_MEMORY, cirrus_pci_mmio_map);
      }
      return 0;
diff --git a/hw/e1000.c b/hw/e1000.c
index 677165f..b7f585b 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -1130,10 +1130,10 @@ static int pci_e1000_init(PCIDevice *pci_dev)
     d->mmio_index = cpu_register_io_memory(e1000_mmio_read,
             e1000_mmio_write, d);
 
-    pci_register_bar((PCIDevice *)d, 0, PNPMMIO_SIZE,
+    pci_register_bar(&d->dev, 0, PNPMMIO_SIZE,
                            PCI_BASE_ADDRESS_SPACE_MEMORY, e1000_mmio_map);
 
-    pci_register_bar((PCIDevice *)d, 1, IOPORT_SIZE,
+    pci_register_bar(&d->dev, 1, IOPORT_SIZE,
                            PCI_BASE_ADDRESS_SPACE_IO, ioport_map);
 
     memmove(d->eeprom_data, e1000_eeprom_template,
diff --git a/hw/ide/via.c b/hw/ide/via.c
index b2c7cad..2001a36 100644
--- a/hw/ide/via.c
+++ b/hw/ide/via.c
@@ -153,7 +153,7 @@ static int vt82c686b_ide_initfn(PCIDevice *dev)
     pci_set_long(pci_conf + PCI_CAPABILITY_LIST, 0x000000c0);
 
     qemu_register_reset(via_reset, d);
-    pci_register_bar((PCIDevice *)d, 4, 0x10,
+    pci_register_bar(&d->dev, 4, 0x10,
                            PCI_BASE_ADDRESS_SPACE_IO, bmdma_map);
 
     vmstate_register(&dev->qdev, 0, &vmstate_ide_pci, d);
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index f97335e..1aef62f 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -2177,12 +2177,11 @@ static int lsi_scsi_init(PCIDevice *dev)
     s->ram_io_addr = cpu_register_io_memory(lsi_ram_readfn,
                                             lsi_ram_writefn, s);
 
-    /* TODO: use dev and get rid of cast below */
-    pci_register_bar((struct PCIDevice *)s, 0, 256,
+    pci_register_bar(&s->dev, 0, 256,
                            PCI_BASE_ADDRESS_SPACE_IO, lsi_io_mapfunc);
-    pci_register_bar((struct PCIDevice *)s, 1, 0x400,
+    pci_register_bar(&s->dev, 1, 0x400,
                            PCI_BASE_ADDRESS_SPACE_MEMORY, lsi_mmio_mapfunc);
-    pci_register_bar((struct PCIDevice *)s, 2, 0x2000,
+    pci_register_bar(&s->dev, 2, 0x2000,
                            PCI_BASE_ADDRESS_SPACE_MEMORY, lsi_ram_mapfunc);
     QTAILQ_INIT(&s->queue);
 
diff --git a/hw/openpic.c b/hw/openpic.c
index 01bf15f..f6b8f21 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -1197,7 +1197,7 @@ qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
         pci_conf[0x3d] = 0x00; // no interrupt pin
 
         /* Register I/O spaces */
-        pci_register_bar((PCIDevice *)opp, 0, 0x40000,
+        pci_register_bar(&opp->pci_dev, 0, 0x40000,
                                PCI_BASE_ADDRESS_SPACE_MEMORY, &openpic_map);
     } else {
         opp = qemu_mallocz(sizeof(openpic_t));
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index c60fd8d..8fb2f83 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -1741,7 +1741,7 @@ static int usb_ohci_initfn_pci(struct PCIDevice *dev)
     ohci->state.irq = ohci->pci_dev.irq[0];
 
     /* TODO: avoid cast below by using dev */
-    pci_register_bar((struct PCIDevice *)ohci, 0, 256,
+    pci_register_bar(&ohci->pci_dev, 0, 256,
                            PCI_BASE_ADDRESS_SPACE_MEMORY, ohci_mapfunc);
     return 0;
 }
commit bba5ed772a562fefdb218df8d821c3b537ce5759
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri Nov 19 13:28:45 2010 +0200

    pcie/port: fix bridge control register wmask
    
    pci generic layer initialized wmask for bridge control register
    according to pci spec. pcie deviates slightly from it,
    so initialize it properly.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pcie_port.c b/hw/pcie_port.c
index 117de61..340dcdb 100644
--- a/hw/pcie_port.c
+++ b/hw/pcie_port.c
@@ -27,6 +27,14 @@ void pcie_port_init_reg(PCIDevice *d)
     pci_set_word(d->config + PCI_STATUS, 0);
     pci_set_word(d->config + PCI_SEC_STATUS, 0);
 
+    /* Unlike conventional pci bridge, some bits are hardwared to 0. */
+    pci_set_word(d->wmask + PCI_BRIDGE_CONTROL,
+                 PCI_BRIDGE_CTL_PARITY |
+                 PCI_BRIDGE_CTL_ISA |
+                 PCI_BRIDGE_CTL_VGA |
+                 PCI_BRIDGE_CTL_SERR |
+                 PCI_BRIDGE_CTL_BUS_RESET);
+
     /* 7.5.3.5 Prefetchable Memory Base Limit
      * The Prefetchable Memory Base and Prefetchable Memory Limit registers
      * must indicate that 64-bit addresses are supported, as defined in
commit f6bdfcc9352e53fac5b9a144fc9ead991163484b
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Thu Nov 18 10:42:50 2010 +0200

    pci: fix bridge control bit wmask
    
    Bits 12 to 15 in bridge control register are reserver and must be
    read-only zero, curent mask is 0xffff which makes them writeable. Fix
    this up by using symbolic bit names for writeable bits instead of a
    hardcoded constant.
    
    Fix a comment w1mask -> w1cmask as well.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci.c b/hw/pci.c
index 00ec8ea..fc5d340 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -558,7 +558,7 @@ static void pci_init_wmask(PCIDevice *dev)
 static void pci_init_w1cmask(PCIDevice *dev)
 {
     /*
-     * Note: It's okay to set w1mask even for readonly bits as
+     * Note: It's okay to set w1cmask even for readonly bits as
      * long as their value is hardwired to 0.
      */
     pci_set_word(dev->w1cmask + PCI_STATUS,
@@ -588,7 +588,29 @@ static void pci_init_wmask_bridge(PCIDevice *d)
     /* PCI_PREF_BASE_UPPER32 and PCI_PREF_LIMIT_UPPER32 */
     memset(d->wmask + PCI_PREF_BASE_UPPER32, 0xff, 8);
 
-    pci_set_word(d->wmask + PCI_BRIDGE_CONTROL, 0xffff);
+/* TODO: add this define to pci_regs.h in linux and then in qemu. */
+#define  PCI_BRIDGE_CTL_VGA_16BIT	0x10	/* VGA 16-bit decode */
+#define  PCI_BRIDGE_CTL_DISCARD		0x100	/* Primary discard timer */
+#define  PCI_BRIDGE_CTL_SEC_DISCARD	0x200	/* Secondary discard timer */
+#define  PCI_BRIDGE_CTL_DISCARD_STATUS	0x400	/* Discard timer status */
+#define  PCI_BRIDGE_CTL_DISCARD_SERR	0x800	/* Discard timer SERR# enable */
+    pci_set_word(d->wmask + PCI_BRIDGE_CONTROL,
+                 PCI_BRIDGE_CTL_PARITY |
+                 PCI_BRIDGE_CTL_SERR |
+                 PCI_BRIDGE_CTL_ISA |
+                 PCI_BRIDGE_CTL_VGA |
+                 PCI_BRIDGE_CTL_VGA_16BIT |
+                 PCI_BRIDGE_CTL_MASTER_ABORT |
+                 PCI_BRIDGE_CTL_BUS_RESET |
+                 PCI_BRIDGE_CTL_FAST_BACK |
+                 PCI_BRIDGE_CTL_DISCARD |
+                 PCI_BRIDGE_CTL_SEC_DISCARD |
+                 PCI_BRIDGE_CTL_DISCARD_STATUS |
+                 PCI_BRIDGE_CTL_DISCARD_SERR);
+    /* Below does not do anything as we never set this bit, put here for
+     * completeness. */
+    pci_set_word(d->w1cmask + PCI_BRIDGE_CONTROL,
+                 PCI_BRIDGE_CTL_DISCARD_STATUS);
 }
 
 static int pci_init_multifunction(PCIBus *bus, PCIDevice *dev)
commit 09b926d44674cbcf198425a5b8255e3cacb398ae
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Tue Nov 16 17:26:12 2010 +0900

    x3130/downstream: support aer.
    
    add aer support.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/xio3130_downstream.c b/hw/xio3130_downstream.c
index 854eba8..1a2d258 100644
--- a/hw/xio3130_downstream.c
+++ b/hw/xio3130_downstream.c
@@ -42,7 +42,7 @@ static void xio3130_downstream_write_config(PCIDevice *d, uint32_t address,
     pcie_cap_flr_write_config(d, address, val, len);
     pcie_cap_slot_write_config(d, address, val, len);
     msi_write_config(d, address, val, len);
-    /* TODO: AER */
+    pcie_aer_write_config(d, address, val, len);
 }
 
 static void xio3130_downstream_reset(DeviceState *qdev)
@@ -61,6 +61,7 @@ static int xio3130_downstream_initfn(PCIDevice *d)
     PCIEPort *p = DO_UPCAST(PCIEPort, br, br);
     PCIESlot *s = DO_UPCAST(PCIESlot, port, p);
     int rc;
+    int tmp;
 
     rc = pci_bridge_initfn(d);
     if (rc < 0) {
@@ -76,17 +77,17 @@ static int xio3130_downstream_initfn(PCIDevice *d)
                   XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_64BIT,
                   XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_MASKBIT);
     if (rc < 0) {
-        return rc;
+        goto err_bridge;
     }
     rc = pci_bridge_ssvid_init(d, XIO3130_SSVID_OFFSET,
                                XIO3130_SSVID_SVID, XIO3130_SSVID_SSID);
     if (rc < 0) {
-        return rc;
+        goto err_bridge;
     }
     rc = pcie_cap_init(d, XIO3130_EXP_OFFSET, PCI_EXP_TYPE_DOWNSTREAM,
                        p->port);
     if (rc < 0) {
-        return rc;
+        goto err_msi;
     }
     pcie_cap_flr_init(d);       /* TODO: implement FLR */
     pcie_cap_deverr_init(d);
@@ -94,19 +95,38 @@ static int xio3130_downstream_initfn(PCIDevice *d)
     pcie_chassis_create(s->chassis);
     rc = pcie_chassis_add_slot(s);
     if (rc < 0) {
-        return rc;
+        goto err_pcie_cap;
     }
     pcie_cap_ari_init(d);
-    /* TODO: AER */
+    rc = pcie_aer_init(d, XIO3130_AER_OFFSET);
+    if (rc < 0) {
+        goto err;
+    }
 
     return 0;
+
+err:
+    pcie_chassis_del_slot(s);
+err_pcie_cap:
+    pcie_cap_exit(d);
+err_msi:
+    msi_uninit(d);
+err_bridge:
+    tmp = pci_bridge_exitfn(d);
+    assert(!tmp);
+    return rc;
 }
 
 static int xio3130_downstream_exitfn(PCIDevice *d)
 {
-    /* TODO: AER */
-    msi_uninit(d);
+    PCIBridge* br = DO_UPCAST(PCIBridge, dev, d);
+    PCIEPort *p = DO_UPCAST(PCIEPort, br, br);
+    PCIESlot *s = DO_UPCAST(PCIESlot, port, p);
+
+    pcie_aer_exit(d);
+    pcie_chassis_del_slot(s);
     pcie_cap_exit(d);
+    msi_uninit(d);
     return pci_bridge_exitfn(d);
 }
 
@@ -144,7 +164,8 @@ static const VMStateDescription vmstate_xio3130_downstream = {
     .post_load = pcie_cap_slot_post_load,
     .fields = (VMStateField[]) {
         VMSTATE_PCIE_DEVICE(port.br.dev, PCIESlot),
-        /* TODO: AER */
+        VMSTATE_STRUCT(port.br.dev.exp.aer_log, PCIESlot, 0,
+                       vmstate_pcie_aer_log, PCIEAERLog),
         VMSTATE_END_OF_LIST()
     }
 };
@@ -166,7 +187,9 @@ static PCIDeviceInfo xio3130_downstream_info = {
         DEFINE_PROP_UINT8("port", PCIESlot, port.port, 0),
         DEFINE_PROP_UINT8("chassis", PCIESlot, chassis, 0),
         DEFINE_PROP_UINT16("slot", PCIESlot, slot, 0),
-        /* TODO: AER */
+        DEFINE_PROP_UINT16("aer_log_max", PCIESlot,
+                           port.br.dev.exp.aer_log.log_max,
+                           PCIE_AER_LOG_MAX_DEFAULT),
         DEFINE_PROP_END_OF_LIST(),
     }
 };
commit a158f92fa78b1e87e5d196b72b750fedefb7b43e
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Tue Nov 16 17:26:11 2010 +0900

    x3130/upstream: support aer
    
    add aer support.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/xio3130_upstream.c b/hw/xio3130_upstream.c
index d9d637f..387bf6c 100644
--- a/hw/xio3130_upstream.c
+++ b/hw/xio3130_upstream.c
@@ -41,7 +41,7 @@ static void xio3130_upstream_write_config(PCIDevice *d, uint32_t address,
     pci_bridge_write_config(d, address, val, len);
     pcie_cap_flr_write_config(d, address, val, len);
     msi_write_config(d, address, val, len);
-    /* TODO: AER */
+    pcie_aer_write_config(d, address, val, len);
 }
 
 static void xio3130_upstream_reset(DeviceState *qdev)
@@ -57,6 +57,7 @@ static int xio3130_upstream_initfn(PCIDevice *d)
     PCIBridge* br = DO_UPCAST(PCIBridge, dev, d);
     PCIEPort *p = DO_UPCAST(PCIEPort, br, br);
     int rc;
+    int tmp;
 
     rc = pci_bridge_initfn(d);
     if (rc < 0) {
@@ -72,33 +73,45 @@ static int xio3130_upstream_initfn(PCIDevice *d)
                   XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_64BIT,
                   XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_MASKBIT);
     if (rc < 0) {
-        return rc;
+        goto err_bridge;
     }
     rc = pci_bridge_ssvid_init(d, XIO3130_SSVID_OFFSET,
                                XIO3130_SSVID_SVID, XIO3130_SSVID_SSID);
     if (rc < 0) {
-        return rc;
+        goto err_bridge;
     }
     rc = pcie_cap_init(d, XIO3130_EXP_OFFSET, PCI_EXP_TYPE_UPSTREAM,
                        p->port);
     if (rc < 0) {
-        return rc;
+        goto err_msi;
     }
 
     /* TODO: implement FLR */
     pcie_cap_flr_init(d);
 
     pcie_cap_deverr_init(d);
-    /* TODO: AER */
+    rc = pcie_aer_init(d, XIO3130_AER_OFFSET);
+    if (rc < 0) {
+        goto err;
+    }
 
     return 0;
+
+err:
+    pcie_cap_exit(d);
+err_msi:
+    msi_uninit(d);
+err_bridge:
+    tmp =  pci_bridge_exitfn(d);
+    assert(!tmp);
+    return rc;
 }
 
 static int xio3130_upstream_exitfn(PCIDevice *d)
 {
-    /* TODO: AER */
-    msi_uninit(d);
+    pcie_aer_exit(d);
     pcie_cap_exit(d);
+    msi_uninit(d);
     return pci_bridge_exitfn(d);
 }
 
@@ -131,7 +144,8 @@ static const VMStateDescription vmstate_xio3130_upstream = {
     .minimum_version_id_old = 1,
     .fields = (VMStateField[]) {
         VMSTATE_PCIE_DEVICE(br.dev, PCIEPort),
-        /* TODO: AER */
+        VMSTATE_STRUCT(br.dev.exp.aer_log, PCIEPort, 0, vmstate_pcie_aer_log,
+                       PCIEAERLog),
         VMSTATE_END_OF_LIST()
     }
 };
@@ -151,7 +165,8 @@ static PCIDeviceInfo xio3130_upstream_info = {
 
     .qdev.props = (Property[]) {
         DEFINE_PROP_UINT8("port", PCIEPort, port, 0),
-        /* TODO: AER */
+        DEFINE_PROP_UINT16("aer_log_max", PCIEPort, br.dev.exp.aer_log.log_max,
+                           PCIE_AER_LOG_MAX_DEFAULT),
         DEFINE_PROP_END_OF_LIST(),
     }
 };
commit 61620c2fff7dda789dbba513c18f534c0062062b
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Tue Nov 16 17:26:10 2010 +0900

    ioh3420: support aer
    
    Add aer support.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/ioh3420.c b/hw/ioh3420.c
index 3cc129f..95adf09 100644
--- a/hw/ioh3420.c
+++ b/hw/ioh3420.c
@@ -36,25 +36,59 @@
 #define IOH_EP_EXP_OFFSET               0x90
 #define IOH_EP_AER_OFFSET               0x100
 
+/*
+ * If two MSI vector are allocated, Advanced Error Interrupt Message Number
+ * is 1. otherwise 0.
+ * 17.12.5.10 RPERRSTS,  32:27 bit Advanced Error Interrupt Message Number.
+ */
+static uint8_t ioh3420_aer_vector(const PCIDevice *d)
+{
+    switch (msi_nr_vectors_allocated(d)) {
+    case 1:
+        return 0;
+    case 2:
+        return 1;
+    case 4:
+    case 8:
+    case 16:
+    case 32:
+    default:
+        break;
+    }
+    abort();
+    return 0;
+}
+
+static void ioh3420_aer_vector_update(PCIDevice *d)
+{
+    pcie_aer_root_set_vector(d, ioh3420_aer_vector(d));
+}
+
 static void ioh3420_write_config(PCIDevice *d,
                                    uint32_t address, uint32_t val, int len)
 {
+    uint32_t root_cmd =
+        pci_get_long(d->config + d->exp.aer_cap + PCI_ERR_ROOT_COMMAND);
+
     pci_bridge_write_config(d, address, val, len);
     msi_write_config(d, address, val, len);
+    ioh3420_aer_vector_update(d);
     pcie_cap_slot_write_config(d, address, val, len);
-    /* TODO: AER */
+    pcie_aer_write_config(d, address, val, len);
+    pcie_aer_root_write_config(d, address, val, len, root_cmd);
 }
 
 static void ioh3420_reset(DeviceState *qdev)
 {
     PCIDevice *d = DO_UPCAST(PCIDevice, qdev, qdev);
     msi_reset(d);
+    ioh3420_aer_vector_update(d);
     pcie_cap_root_reset(d);
     pcie_cap_deverr_reset(d);
     pcie_cap_slot_reset(d);
+    pcie_aer_root_reset(d);
     pci_bridge_reset(qdev);
     pci_bridge_disable_base_limit(d);
-    /* TODO: AER */
 }
 
 static int ioh3420_initfn(PCIDevice *d)
@@ -63,6 +97,7 @@ static int ioh3420_initfn(PCIDevice *d)
     PCIEPort *p = DO_UPCAST(PCIEPort, br, br);
     PCIESlot *s = DO_UPCAST(PCIESlot, port, p);
     int rc;
+    int tmp;
 
     rc = pci_bridge_initfn(d);
     if (rc < 0) {
@@ -78,35 +113,57 @@ static int ioh3420_initfn(PCIDevice *d)
     rc = pci_bridge_ssvid_init(d, IOH_EP_SSVID_OFFSET,
                                IOH_EP_SSVID_SVID, IOH_EP_SSVID_SSID);
     if (rc < 0) {
-        return rc;
+        goto err_bridge;
     }
     rc = msi_init(d, IOH_EP_MSI_OFFSET, IOH_EP_MSI_NR_VECTOR,
                   IOH_EP_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_64BIT,
                   IOH_EP_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_MASKBIT);
     if (rc < 0) {
-        return rc;
+        goto err_bridge;
     }
     rc = pcie_cap_init(d, IOH_EP_EXP_OFFSET, PCI_EXP_TYPE_ROOT_PORT, p->port);
     if (rc < 0) {
-        return rc;
+        goto err_msi;
     }
     pcie_cap_deverr_init(d);
     pcie_cap_slot_init(d, s->slot);
     pcie_chassis_create(s->chassis);
     rc = pcie_chassis_add_slot(s);
     if (rc < 0) {
+        goto err_pcie_cap;
         return rc;
     }
     pcie_cap_root_init(d);
-    /* TODO: AER */
+    rc = pcie_aer_init(d, IOH_EP_AER_OFFSET);
+    if (rc < 0) {
+        goto err;
+    }
+    pcie_aer_root_init(d);
+    ioh3420_aer_vector_update(d);
     return 0;
+
+err:
+    pcie_chassis_del_slot(s);
+err_pcie_cap:
+    pcie_cap_exit(d);
+err_msi:
+    msi_uninit(d);
+err_bridge:
+    tmp = pci_bridge_exitfn(d);
+    assert(!tmp);
+    return rc;
 }
 
 static int ioh3420_exitfn(PCIDevice *d)
 {
-    /* TODO: AER */
-    msi_uninit(d);
+    PCIBridge* br = DO_UPCAST(PCIBridge, dev, d);
+    PCIEPort *p = DO_UPCAST(PCIEPort, br, br);
+    PCIESlot *s = DO_UPCAST(PCIESlot, port, p);
+
+    pcie_aer_exit(d);
+    pcie_chassis_del_slot(s);
     pcie_cap_exit(d);
+    msi_uninit(d);
     return pci_bridge_exitfn(d);
 }
 
@@ -142,7 +199,8 @@ static const VMStateDescription vmstate_ioh3420 = {
     .post_load = pcie_cap_slot_post_load,
     .fields = (VMStateField[]) {
         VMSTATE_PCIE_DEVICE(port.br.dev, PCIESlot),
-        /* TODO: AER */
+        VMSTATE_STRUCT(port.br.dev.exp.aer_log, PCIESlot, 0,
+                       vmstate_pcie_aer_log, PCIEAERLog),
         VMSTATE_END_OF_LIST()
     }
 };
@@ -164,7 +222,9 @@ static PCIDeviceInfo ioh3420_info = {
         DEFINE_PROP_UINT8("port", PCIESlot, port.port, 0),
         DEFINE_PROP_UINT8("chassis", PCIESlot, chassis, 0),
         DEFINE_PROP_UINT16("slot", PCIESlot, slot, 0),
-        /* TODO: AER */
+        DEFINE_PROP_UINT16("aer_log_max", PCIESlot,
+                           port.br.dev.exp.aer_log.log_max,
+                           PCIE_AER_LOG_MAX_DEFAULT),
         DEFINE_PROP_END_OF_LIST(),
     }
 };
commit d33d9156fdffb87c99564c9630023da52c66f37a
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Wed Nov 17 15:45:39 2010 +0200

    pcie_aer: complete unwinding recursion
    
    Open-code functions created in the previous patch,
    to make code more compact and clear.
    Detcted and documented what looks like a bug in code
    that becomes apparent from this refactoring.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pcie_aer.c b/hw/pcie_aer.c
index c565d39..235ac53 100644
--- a/hw/pcie_aer.c
+++ b/hw/pcie_aer.c
@@ -215,33 +215,6 @@ pcie_aer_msg_alldev(PCIDevice *dev, const PCIEAERMsg *msg)
     return true;
 }
 
-/* Get parent port to send up error message on.
- * TODO: clean up and open-code this logic */
-static PCIDevice *pcie_aer_parent_port(PCIDevice *dev)
-{
-    PCIDevice *parent_port;
-    if (pci_is_express(dev) &&
-        pcie_cap_get_type(dev) == PCI_EXP_TYPE_ROOT_PORT) {
-        /* Root port can notify system itself,
-           or send the error message to root complex event collector. */
-        /*
-         * if root port is associated with an event collector,
-         * return the root complex event collector here.
-         * For now root complex event collector isn't supported.
-         */
-        parent_port = NULL;
-    } else {
-        parent_port = pci_bridge_get_device(dev->bus);
-    }
-    if (parent_port) {
-        if (!pci_is_express(parent_port)) {
-            /* just ignore it */
-            return NULL;
-        }
-    }
-    return parent_port;
-}
-
 /*
  * return value:
  * true: error message is sent up
@@ -381,41 +354,42 @@ static bool pcie_aer_msg_root_port(PCIDevice *dev, const PCIEAERMsg *msg)
 /*
  * 6.2.6 Error Message Control Figure 6-3
  *
- * Returns true in case the error needs to
- * be propagated up.
- * TODO: open-code.
+ * Walk up the bus tree from the device, propagate the error message.
  */
-static bool pcie_send_aer_msg(PCIDevice *dev, const PCIEAERMsg *msg)
+static void pcie_aer_msg(PCIDevice *dev, const PCIEAERMsg *msg)
 {
     uint8_t type;
-    bool msg_sent;
-
-    assert(pci_is_express(dev));
 
-    type = pcie_cap_get_type(dev);
-    if (type == PCI_EXP_TYPE_ROOT_PORT ||
-        type == PCI_EXP_TYPE_UPSTREAM ||
-        type == PCI_EXP_TYPE_DOWNSTREAM) {
-        msg_sent = pcie_aer_msg_vbridge(dev, msg);
-        if (!msg_sent) {
+    while (dev) {
+        if (!pci_is_express(dev)) {
+            /* just ignore it */
+            /* TODO: Shouldn't we set PCI_STATUS_SIG_SYSTEM_ERROR?
+             * Consider e.g. a PCI bridge above a PCI Express device. */
             return;
         }
-    }
-    msg_sent = pcie_aer_msg_alldev(dev, msg);
-    if (type == PCI_EXP_TYPE_ROOT_PORT && msg_sent) {
-        pcie_aer_msg_root_port(dev, msg);
-    }
-    return msg_sent;
-}
 
-static void pcie_aer_msg(PCIDevice *dev, const PCIEAERMsg *msg)
-{
-    bool send_to_parent;
-    while (dev) {
-        if (!pcie_send_aer_msg(dev, msg)) {
+        type = pcie_cap_get_type(dev);
+        if ((type == PCI_EXP_TYPE_ROOT_PORT ||
+            type == PCI_EXP_TYPE_UPSTREAM ||
+            type == PCI_EXP_TYPE_DOWNSTREAM) &&
+            !pcie_aer_msg_vbridge(dev, msg)) {
+                return;
+        }
+        if (!pcie_aer_msg_alldev(dev, msg)) {
+            return;
+        }
+        if (type == PCI_EXP_TYPE_ROOT_PORT) {
+            pcie_aer_msg_root_port(dev, msg);
+            /* Root port can notify system itself,
+               or send the error message to root complex event collector. */
+            /*
+             * if root port is associated with an event collector,
+             * return the root complex event collector here.
+             * For now root complex event collector isn't supported.
+             */
             return;
         }
-        dev =  pcie_aer_parent_port(dev);
+        dev = pci_bridge_get_device(dev->bus);
     }
 }
 
commit 247c97f3f5ab0dae60778a2dea438bfed5c69e68
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Wed Nov 17 15:02:26 2010 +0200

    pcie_aer: get rid of recursion
    
    Added some TODOs: they are trivial but omitted here
    to make the patch logic as transparent as possible.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pcie_aer.c b/hw/pcie_aer.c
index acf826a..c565d39 100644
--- a/hw/pcie_aer.c
+++ b/hw/pcie_aer.c
@@ -176,14 +176,8 @@ static void pcie_aer_update_uncor_status(PCIDevice *dev)
 }
 
 /*
- * pcie_aer_msg() is called recursively by
- * pcie_aer_msg_alldev(), pci_aer_msg_vbridge() and pcie_aer_msg_root_port()
- */
-static void pcie_aer_msg(PCIDevice *dev, const PCIEAERMsg *msg);
-
-/*
  * return value:
- * true: error message is sent up
+ * true: error message needs to be sent up
  * false: error message is masked
  *
  * 6.2.6 Error Message Control
@@ -193,8 +187,6 @@ static void pcie_aer_msg(PCIDevice *dev, const PCIEAERMsg *msg);
 static bool
 pcie_aer_msg_alldev(PCIDevice *dev, const PCIEAERMsg *msg)
 {
-    PCIDevice *parent_port;
-
     if (!(pcie_aer_msg_is_uncor(msg) &&
           (pci_get_word(dev->config + PCI_COMMAND) & PCI_COMMAND_SERR))) {
         return false;
@@ -220,13 +212,21 @@ pcie_aer_msg_alldev(PCIDevice *dev, const PCIEAERMsg *msg)
     }
 
     /* send up error message */
+    return true;
+}
+
+/* Get parent port to send up error message on.
+ * TODO: clean up and open-code this logic */
+static PCIDevice *pcie_aer_parent_port(PCIDevice *dev)
+{
+    PCIDevice *parent_port;
     if (pci_is_express(dev) &&
         pcie_cap_get_type(dev) == PCI_EXP_TYPE_ROOT_PORT) {
-        /* Root port notify system itself,
+        /* Root port can notify system itself,
            or send the error message to root complex event collector. */
         /*
-         * if root port is associated to event collector, set
-         * parent_port = root complex event collector
+         * if root port is associated with an event collector,
+         * return the root complex event collector here.
          * For now root complex event collector isn't supported.
          */
         parent_port = NULL;
@@ -236,11 +236,10 @@ pcie_aer_msg_alldev(PCIDevice *dev, const PCIEAERMsg *msg)
     if (parent_port) {
         if (!pci_is_express(parent_port)) {
             /* just ignore it */
-            return false;
+            return NULL;
         }
-        pcie_aer_msg(parent_port, msg);
     }
-    return true;
+    return parent_port;
 }
 
 /*
@@ -381,8 +380,12 @@ static bool pcie_aer_msg_root_port(PCIDevice *dev, const PCIEAERMsg *msg)
 
 /*
  * 6.2.6 Error Message Control Figure 6-3
+ *
+ * Returns true in case the error needs to
+ * be propagated up.
+ * TODO: open-code.
  */
-static void pcie_aer_msg(PCIDevice *dev, const PCIEAERMsg *msg)
+static bool pcie_send_aer_msg(PCIDevice *dev, const PCIEAERMsg *msg)
 {
     uint8_t type;
     bool msg_sent;
@@ -402,6 +405,18 @@ static void pcie_aer_msg(PCIDevice *dev, const PCIEAERMsg *msg)
     if (type == PCI_EXP_TYPE_ROOT_PORT && msg_sent) {
         pcie_aer_msg_root_port(dev, msg);
     }
+    return msg_sent;
+}
+
+static void pcie_aer_msg(PCIDevice *dev, const PCIEAERMsg *msg)
+{
+    bool send_to_parent;
+    while (dev) {
+        if (!pcie_send_aer_msg(dev, msg)) {
+            return;
+        }
+        dev =  pcie_aer_parent_port(dev);
+    }
 }
 
 static void pcie_aer_update_log(PCIDevice *dev, const PCIEAERErr *err)
@@ -824,4 +839,3 @@ const VMStateDescription vmstate_pcie_aer_log = {
         VMSTATE_END_OF_LIST()
     }
 };
-
commit 34e65944c0351fabcd82aa8c85018980c7e87bff
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Tue Nov 16 17:26:09 2010 +0900

    pcie/aer: helper functions for pcie aer capability
    
    This patch implements helper functions for pcie aer capability
    which will be used later.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index faf485e..c5919af 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -207,7 +207,7 @@ hw-obj-$(CONFIG_PIIX4) += piix4.o
 # PCI watchdog devices
 hw-obj-y += wdt_i6300esb.o
 
-hw-obj-y += pcie.o pcie_port.o
+hw-obj-y += pcie.o pcie_aer.o pcie_port.o
 hw-obj-y += msix.o msi.o
 
 # PCI network cards
diff --git a/hw/pcie.h b/hw/pcie.h
index 8708504..7baa813 100644
--- a/hw/pcie.h
+++ b/hw/pcie.h
@@ -24,6 +24,7 @@
 #include "hw.h"
 #include "pci_regs.h"
 #include "pcie_regs.h"
+#include "pcie_aer.h"
 
 typedef enum {
     /* for attention and power indicator */
@@ -79,6 +80,19 @@ struct PCIExpressDevice {
                          Software Notification of Hot-Plug Events, an interrupt
                          is sent whenever the logical and of these conditions
                          transitions from false to true. */
+
+    /* AER */
+    uint16_t aer_cap;
+    PCIEAERLog aer_log;
+    unsigned int aer_intx;      /* INTx for error reporting
+                                 * default is 0 = INTA#
+                                 * If the chip wants to use other interrupt
+                                 * line, initialize this member with the
+                                 * desired number.
+                                 * If the chip dynamically changes this member,
+                                 * also initialize it when loaded as
+                                 * appropreately.
+                                 */
 };
 
 /* PCI express capability helper functions */
diff --git a/hw/pcie_aer.c b/hw/pcie_aer.c
new file mode 100644
index 0000000..acf826a
--- /dev/null
+++ b/hw/pcie_aer.c
@@ -0,0 +1,827 @@
+/*
+ * pcie_aer.c
+ *
+ * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "sysemu.h"
+#include "pci_bridge.h"
+#include "pcie.h"
+#include "msix.h"
+#include "msi.h"
+#include "pci_internals.h"
+#include "pcie_regs.h"
+
+//#define DEBUG_PCIE
+#ifdef DEBUG_PCIE
+# define PCIE_DPRINTF(fmt, ...)                                         \
+    fprintf(stderr, "%s:%d " fmt, __func__, __LINE__, ## __VA_ARGS__)
+#else
+# define PCIE_DPRINTF(fmt, ...) do {} while (0)
+#endif
+#define PCIE_DEV_PRINTF(dev, fmt, ...)                                  \
+    PCIE_DPRINTF("%s:%x "fmt, (dev)->name, (dev)->devfn, ## __VA_ARGS__)
+
+/* From 6.2.7 Error Listing and Rules. Table 6-2, 6-3 and 6-4 */
+static uint32_t pcie_aer_uncor_default_severity(uint32_t status)
+{
+    switch (status) {
+    case PCI_ERR_UNC_INTN:
+    case PCI_ERR_UNC_DLP:
+    case PCI_ERR_UNC_SDN:
+    case PCI_ERR_UNC_RX_OVER:
+    case PCI_ERR_UNC_FCP:
+    case PCI_ERR_UNC_MALF_TLP:
+        return PCI_ERR_ROOT_CMD_FATAL_EN;
+    case PCI_ERR_UNC_POISON_TLP:
+    case PCI_ERR_UNC_ECRC:
+    case PCI_ERR_UNC_UNSUP:
+    case PCI_ERR_UNC_COMP_TIME:
+    case PCI_ERR_UNC_COMP_ABORT:
+    case PCI_ERR_UNC_UNX_COMP:
+    case PCI_ERR_UNC_ACSV:
+    case PCI_ERR_UNC_MCBTLP:
+    case PCI_ERR_UNC_ATOP_EBLOCKED:
+    case PCI_ERR_UNC_TLP_PRF_BLOCKED:
+        return PCI_ERR_ROOT_CMD_NONFATAL_EN;
+    default:
+        abort();
+        break;
+    }
+    return PCI_ERR_ROOT_CMD_FATAL_EN;
+}
+
+static int aer_log_add_err(PCIEAERLog *aer_log, const PCIEAERErr *err)
+{
+    if (aer_log->log_num == aer_log->log_max) {
+        return -1;
+    }
+    memcpy(&aer_log->log[aer_log->log_num], err, sizeof *err);
+    aer_log->log_num++;
+    return 0;
+}
+
+static void aer_log_del_err(PCIEAERLog *aer_log, PCIEAERErr *err)
+{
+    assert(aer_log->log_num);
+    *err = aer_log->log[0];
+    aer_log->log_num--;
+    memmove(&aer_log->log[0], &aer_log->log[1],
+            aer_log->log_num * sizeof *err);
+}
+
+static void aer_log_clear_all_err(PCIEAERLog *aer_log)
+{
+    aer_log->log_num = 0;
+}
+
+int pcie_aer_init(PCIDevice *dev, uint16_t offset)
+{
+    PCIExpressDevice *exp;
+
+    pcie_add_capability(dev, PCI_EXT_CAP_ID_ERR, PCI_ERR_VER,
+                        offset, PCI_ERR_SIZEOF);
+    exp = &dev->exp;
+    exp->aer_cap = offset;
+
+    /* log_max is property */
+    if (dev->exp.aer_log.log_max == PCIE_AER_LOG_MAX_UNSET) {
+        dev->exp.aer_log.log_max = PCIE_AER_LOG_MAX_DEFAULT;
+    }
+    /* clip down the value to avoid unreasobale memory usage */
+    if (dev->exp.aer_log.log_max > PCIE_AER_LOG_MAX_LIMIT) {
+        return -EINVAL;
+    }
+    dev->exp.aer_log.log = qemu_mallocz(sizeof dev->exp.aer_log.log[0] *
+                                        dev->exp.aer_log.log_max);
+
+    pci_set_long(dev->w1cmask + offset + PCI_ERR_UNCOR_STATUS,
+                 PCI_ERR_UNC_SUPPORTED);
+
+    pci_set_long(dev->config + offset + PCI_ERR_UNCOR_SEVER,
+                 PCI_ERR_UNC_SEVERITY_DEFAULT);
+    pci_set_long(dev->wmask + offset + PCI_ERR_UNCOR_SEVER,
+                 PCI_ERR_UNC_SUPPORTED);
+
+    pci_long_test_and_set_mask(dev->w1cmask + offset + PCI_ERR_COR_STATUS,
+                               PCI_ERR_COR_STATUS);
+
+    pci_set_long(dev->config + offset + PCI_ERR_COR_MASK,
+                 PCI_ERR_COR_MASK_DEFAULT);
+    pci_set_long(dev->wmask + offset + PCI_ERR_COR_MASK,
+                 PCI_ERR_COR_SUPPORTED);
+
+    /* capabilities and control. multiple header logging is supported */
+    if (dev->exp.aer_log.log_max > 0) {
+        pci_set_long(dev->config + offset + PCI_ERR_CAP,
+                     PCI_ERR_CAP_ECRC_GENC | PCI_ERR_CAP_ECRC_CHKC |
+                     PCI_ERR_CAP_MHRC);
+        pci_set_long(dev->wmask + offset + PCI_ERR_CAP,
+                     PCI_ERR_CAP_ECRC_GENE | PCI_ERR_CAP_ECRC_CHKE |
+                     PCI_ERR_CAP_MHRE);
+    } else {
+        pci_set_long(dev->config + offset + PCI_ERR_CAP,
+                     PCI_ERR_CAP_ECRC_GENC | PCI_ERR_CAP_ECRC_CHKC);
+        pci_set_long(dev->wmask + offset + PCI_ERR_CAP,
+                     PCI_ERR_CAP_ECRC_GENE | PCI_ERR_CAP_ECRC_CHKE);
+    }
+
+    switch (pcie_cap_get_type(dev)) {
+    case PCI_EXP_TYPE_ROOT_PORT:
+        /* this case will be set by pcie_aer_root_init() */
+        /* fallthrough */
+    case PCI_EXP_TYPE_DOWNSTREAM:
+    case PCI_EXP_TYPE_UPSTREAM:
+        pci_word_test_and_set_mask(dev->wmask + PCI_BRIDGE_CONTROL,
+                                   PCI_BRIDGE_CTL_SERR);
+        pci_long_test_and_set_mask(dev->w1cmask + PCI_STATUS,
+                                   PCI_SEC_STATUS_RCV_SYSTEM_ERROR);
+        break;
+    default:
+        /* nothing */
+        break;
+    }
+    return 0;
+}
+
+void pcie_aer_exit(PCIDevice *dev)
+{
+    qemu_free(dev->exp.aer_log.log);
+}
+
+static void pcie_aer_update_uncor_status(PCIDevice *dev)
+{
+    uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
+    PCIEAERLog *aer_log = &dev->exp.aer_log;
+
+    uint16_t i;
+    for (i = 0; i < aer_log->log_num; i++) {
+        pci_long_test_and_set_mask(aer_cap + PCI_ERR_UNCOR_STATUS,
+                                   dev->exp.aer_log.log[i].status);
+    }
+}
+
+/*
+ * pcie_aer_msg() is called recursively by
+ * pcie_aer_msg_alldev(), pci_aer_msg_vbridge() and pcie_aer_msg_root_port()
+ */
+static void pcie_aer_msg(PCIDevice *dev, const PCIEAERMsg *msg);
+
+/*
+ * return value:
+ * true: error message is sent up
+ * false: error message is masked
+ *
+ * 6.2.6 Error Message Control
+ * Figure 6-3
+ * all pci express devices part
+ */
+static bool
+pcie_aer_msg_alldev(PCIDevice *dev, const PCIEAERMsg *msg)
+{
+    PCIDevice *parent_port;
+
+    if (!(pcie_aer_msg_is_uncor(msg) &&
+          (pci_get_word(dev->config + PCI_COMMAND) & PCI_COMMAND_SERR))) {
+        return false;
+    }
+
+    /* Signaled System Error
+     *
+     * 7.5.1.1 Command register
+     * Bit 8 SERR# Enable
+     *
+     * When Set, this bit enables reporting of Non-fatal and Fatal
+     * errors detected by the Function to the Root Complex. Note that
+     * errors are reported if enabled either through this bit or through
+     * the PCI Express specific bits in the Device Control register (see
+     * Section 7.8.4).
+     */
+    pci_word_test_and_set_mask(dev->config + PCI_STATUS,
+                               PCI_STATUS_SIG_SYSTEM_ERROR);
+
+    if (!(msg->severity &
+          pci_get_word(dev->config + dev->exp.exp_cap + PCI_EXP_DEVCTL))) {
+        return false;
+    }
+
+    /* send up error message */
+    if (pci_is_express(dev) &&
+        pcie_cap_get_type(dev) == PCI_EXP_TYPE_ROOT_PORT) {
+        /* Root port notify system itself,
+           or send the error message to root complex event collector. */
+        /*
+         * if root port is associated to event collector, set
+         * parent_port = root complex event collector
+         * For now root complex event collector isn't supported.
+         */
+        parent_port = NULL;
+    } else {
+        parent_port = pci_bridge_get_device(dev->bus);
+    }
+    if (parent_port) {
+        if (!pci_is_express(parent_port)) {
+            /* just ignore it */
+            return false;
+        }
+        pcie_aer_msg(parent_port, msg);
+    }
+    return true;
+}
+
+/*
+ * return value:
+ * true: error message is sent up
+ * false: error message is masked
+ *
+ * 6.2.6 Error Message Control
+ * Figure 6-3
+ * virtual pci bridge part
+ */
+static bool pcie_aer_msg_vbridge(PCIDevice *dev, const PCIEAERMsg *msg)
+{
+    uint16_t bridge_control = pci_get_word(dev->config + PCI_BRIDGE_CONTROL);
+
+    if (pcie_aer_msg_is_uncor(msg)) {
+        /* Received System Error */
+        pci_word_test_and_set_mask(dev->config + PCI_SEC_STATUS,
+                                   PCI_SEC_STATUS_RCV_SYSTEM_ERROR);
+    }
+
+    if (!(bridge_control & PCI_BRIDGE_CTL_SERR)) {
+        return false;
+    }
+    return true;
+}
+
+void pcie_aer_root_set_vector(PCIDevice *dev, unsigned int vector)
+{
+    uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
+    assert(vector < PCI_ERR_ROOT_IRQ_MAX);
+    pci_long_test_and_clear_mask(aer_cap + PCI_ERR_ROOT_STATUS,
+                                 PCI_ERR_ROOT_IRQ);
+    pci_long_test_and_set_mask(aer_cap + PCI_ERR_ROOT_STATUS,
+                               vector << PCI_ERR_ROOT_IRQ_SHIFT);
+}
+
+static unsigned int pcie_aer_root_get_vector(PCIDevice *dev)
+{
+    uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
+    uint32_t root_status = pci_get_long(aer_cap + PCI_ERR_ROOT_STATUS);
+    return (root_status & PCI_ERR_ROOT_IRQ) >> PCI_ERR_ROOT_IRQ_SHIFT;
+}
+
+/*
+ * return value:
+ * true: error message is sent up
+ * false: error message is masked
+ *
+ * 6.2.6 Error Message Control
+ * Figure 6-3
+ * root port part
+ */
+static bool pcie_aer_msg_root_port(PCIDevice *dev, const PCIEAERMsg *msg)
+{
+    bool msg_sent;
+    uint16_t cmd;
+    uint8_t *aer_cap;
+    uint32_t root_cmd;
+    uint32_t root_status;
+    bool msi_trigger;
+
+    msg_sent = false;
+    cmd = pci_get_word(dev->config + PCI_COMMAND);
+    aer_cap = dev->config + dev->exp.aer_cap;
+    root_cmd = pci_get_long(aer_cap + PCI_ERR_ROOT_COMMAND);
+    root_status = pci_get_long(aer_cap + PCI_ERR_ROOT_STATUS);
+    msi_trigger = false;
+
+    if (cmd & PCI_COMMAND_SERR) {
+        /* System Error.
+         *
+         * The way to report System Error is platform specific and
+         * it isn't implemented in qemu right now.
+         * So just discard the error for now.
+         * OS which cares of aer would receive errors via
+         * native aer mechanims, so this wouldn't matter.
+         */
+    }
+
+    /* Errro Message Received: Root Error Status register */
+    switch (msg->severity) {
+    case PCI_ERR_ROOT_CMD_COR_EN:
+        if (root_status & PCI_ERR_ROOT_COR_RCV) {
+            root_status |= PCI_ERR_ROOT_MULTI_COR_RCV;
+        } else {
+            if (root_cmd & PCI_ERR_ROOT_CMD_COR_EN) {
+                msi_trigger = true;
+            }
+            pci_set_word(aer_cap + PCI_ERR_ROOT_COR_SRC, msg->source_id);
+        }
+        root_status |= PCI_ERR_ROOT_COR_RCV;
+        break;
+    case PCI_ERR_ROOT_CMD_NONFATAL_EN:
+        if (!(root_status & PCI_ERR_ROOT_NONFATAL_RCV) &&
+            root_cmd & PCI_ERR_ROOT_CMD_NONFATAL_EN) {
+            msi_trigger = true;
+        }
+        root_status |= PCI_ERR_ROOT_NONFATAL_RCV;
+        break;
+    case PCI_ERR_ROOT_CMD_FATAL_EN:
+        if (!(root_status & PCI_ERR_ROOT_FATAL_RCV) &&
+            root_cmd & PCI_ERR_ROOT_CMD_FATAL_EN) {
+            msi_trigger = true;
+        }
+        if (!(root_status & PCI_ERR_ROOT_UNCOR_RCV)) {
+            root_status |= PCI_ERR_ROOT_FIRST_FATAL;
+        }
+        root_status |= PCI_ERR_ROOT_FATAL_RCV;
+        break;
+    default:
+        abort();
+        break;
+    }
+    if (pcie_aer_msg_is_uncor(msg)) {
+        if (root_status & PCI_ERR_ROOT_UNCOR_RCV) {
+            root_status |= PCI_ERR_ROOT_MULTI_UNCOR_RCV;
+        } else {
+            pci_set_word(aer_cap + PCI_ERR_ROOT_SRC, msg->source_id);
+        }
+        root_status |= PCI_ERR_ROOT_UNCOR_RCV;
+    }
+    pci_set_long(aer_cap + PCI_ERR_ROOT_STATUS, root_status);
+
+    if (root_cmd & msg->severity) {
+        /* 6.2.4.1.2 Interrupt Generation */
+        if (pci_msi_enabled(dev)) {
+            if (msi_trigger) {
+                pci_msi_notify(dev, pcie_aer_root_get_vector(dev));
+            }
+        } else {
+            qemu_set_irq(dev->irq[dev->exp.aer_intx], 1);
+        }
+        msg_sent = true;
+    }
+    return msg_sent;
+}
+
+/*
+ * 6.2.6 Error Message Control Figure 6-3
+ */
+static void pcie_aer_msg(PCIDevice *dev, const PCIEAERMsg *msg)
+{
+    uint8_t type;
+    bool msg_sent;
+
+    assert(pci_is_express(dev));
+
+    type = pcie_cap_get_type(dev);
+    if (type == PCI_EXP_TYPE_ROOT_PORT ||
+        type == PCI_EXP_TYPE_UPSTREAM ||
+        type == PCI_EXP_TYPE_DOWNSTREAM) {
+        msg_sent = pcie_aer_msg_vbridge(dev, msg);
+        if (!msg_sent) {
+            return;
+        }
+    }
+    msg_sent = pcie_aer_msg_alldev(dev, msg);
+    if (type == PCI_EXP_TYPE_ROOT_PORT && msg_sent) {
+        pcie_aer_msg_root_port(dev, msg);
+    }
+}
+
+static void pcie_aer_update_log(PCIDevice *dev, const PCIEAERErr *err)
+{
+    uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
+    uint8_t first_bit = ffsl(err->status) - 1;
+    uint32_t errcap = pci_get_long(aer_cap + PCI_ERR_CAP);
+    int i;
+
+    assert(err->status);
+    assert(err->status & (err->status - 1));
+
+    errcap &= ~(PCI_ERR_CAP_FEP_MASK | PCI_ERR_CAP_TLP);
+    errcap |= PCI_ERR_CAP_FEP(first_bit);
+
+    if (err->flags & PCIE_AER_ERR_HEADER_VALID) {
+        for (i = 0; i < ARRAY_SIZE(err->header); ++i) {
+            /* 7.10.8 Header Log Register */
+            uint8_t *header_log =
+                aer_cap + PCI_ERR_HEADER_LOG + i * sizeof err->header[0];
+            cpu_to_be32wu((uint32_t*)header_log, err->header[i]);
+        }
+    } else {
+        assert(!(err->flags & PCIE_AER_ERR_TLP_PREFIX_PRESENT));
+        memset(aer_cap + PCI_ERR_HEADER_LOG, 0, PCI_ERR_HEADER_LOG_SIZE);
+    }
+
+    if ((err->flags & PCIE_AER_ERR_TLP_PREFIX_PRESENT) &&
+        (pci_get_long(dev->config + dev->exp.exp_cap + PCI_EXP_DEVCTL2) &
+         PCI_EXP_DEVCAP2_EETLPP)) {
+        for (i = 0; i < ARRAY_SIZE(err->prefix); ++i) {
+            /* 7.10.12 tlp prefix log register */
+            uint8_t *prefix_log =
+                aer_cap + PCI_ERR_TLP_PREFIX_LOG + i * sizeof err->prefix[0];
+            cpu_to_be32wu((uint32_t*)prefix_log, err->prefix[i]);
+        }
+        errcap |= PCI_ERR_CAP_TLP;
+    } else {
+        memset(aer_cap + PCI_ERR_TLP_PREFIX_LOG, 0,
+               PCI_ERR_TLP_PREFIX_LOG_SIZE);
+    }
+    pci_set_long(aer_cap + PCI_ERR_CAP, errcap);
+}
+
+static void pcie_aer_clear_log(PCIDevice *dev)
+{
+    uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
+
+    pci_long_test_and_clear_mask(aer_cap + PCI_ERR_CAP,
+                                 PCI_ERR_CAP_FEP_MASK | PCI_ERR_CAP_TLP);
+
+    memset(aer_cap + PCI_ERR_HEADER_LOG, 0, PCI_ERR_HEADER_LOG_SIZE);
+    memset(aer_cap + PCI_ERR_TLP_PREFIX_LOG, 0, PCI_ERR_TLP_PREFIX_LOG_SIZE);
+}
+
+static void pcie_aer_clear_error(PCIDevice *dev)
+{
+    uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
+    uint32_t errcap = pci_get_long(aer_cap + PCI_ERR_CAP);
+    PCIEAERLog *aer_log = &dev->exp.aer_log;
+    PCIEAERErr err;
+
+    if (!(errcap & PCI_ERR_CAP_MHRE) || !aer_log->log_num) {
+        pcie_aer_clear_log(dev);
+        return;
+    }
+
+    /*
+     * If more errors are queued, set corresponding bits in uncorrectable
+     * error status.
+     * We emulate uncorrectable error status register as W1CS.
+     * So set bit in uncorrectable error status here again for multiple
+     * error recording support.
+     *
+     * 6.2.4.2 Multiple Error Handling(Advanced Error Reporting Capability)
+     */
+    pcie_aer_update_uncor_status(dev);
+
+    aer_log_del_err(aer_log, &err);
+    pcie_aer_update_log(dev, &err);
+}
+
+static int pcie_aer_record_error(PCIDevice *dev,
+                                 const PCIEAERErr *err)
+{
+    uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
+    uint32_t errcap = pci_get_long(aer_cap + PCI_ERR_CAP);
+    int fep = PCI_ERR_CAP_FEP(errcap);
+
+    assert(err->status);
+    assert(err->status & (err->status - 1));
+
+    if (errcap & PCI_ERR_CAP_MHRE &&
+        (pci_get_long(aer_cap + PCI_ERR_UNCOR_STATUS) & (1U << fep))) {
+        /*  Not first error. queue error */
+        if (aer_log_add_err(&dev->exp.aer_log, err) < 0) {
+            /* overflow */
+            return -1;
+        }
+        return 0;
+    }
+
+    pcie_aer_update_log(dev, err);
+    return 0;
+}
+
+typedef struct PCIEAERInject {
+    PCIDevice *dev;
+    uint8_t *aer_cap;
+    const PCIEAERErr *err;
+    uint16_t devctl;
+    uint16_t devsta;
+    uint32_t error_status;
+    bool unsupported_request;
+    bool log_overflow;
+    PCIEAERMsg msg;
+} PCIEAERInject;
+
+static bool pcie_aer_inject_cor_error(PCIEAERInject *inj,
+                                      uint32_t uncor_status,
+                                      bool is_advisory_nonfatal)
+{
+    PCIDevice *dev = inj->dev;
+
+    inj->devsta |= PCI_EXP_DEVSTA_CED;
+    if (inj->unsupported_request) {
+        inj->devsta |= PCI_EXP_DEVSTA_URD;
+    }
+    pci_set_word(dev->config + dev->exp.exp_cap + PCI_EXP_DEVSTA, inj->devsta);
+
+    if (inj->aer_cap) {
+        uint32_t mask;
+        pci_long_test_and_set_mask(inj->aer_cap + PCI_ERR_COR_STATUS,
+                                   inj->error_status);
+        mask = pci_get_long(inj->aer_cap + PCI_ERR_COR_MASK);
+        if (mask & inj->error_status) {
+            return false;
+        }
+        if (is_advisory_nonfatal) {
+            uint32_t uncor_mask =
+                pci_get_long(inj->aer_cap + PCI_ERR_UNCOR_MASK);
+            if (!(uncor_mask & uncor_status)) {
+                inj->log_overflow = !!pcie_aer_record_error(dev, inj->err);
+            }
+            pci_long_test_and_set_mask(inj->aer_cap + PCI_ERR_UNCOR_STATUS,
+                                       uncor_status);
+        }
+    }
+
+    if (inj->unsupported_request && !(inj->devctl & PCI_EXP_DEVCTL_URRE)) {
+        return false;
+    }
+    if (!(inj->devctl & PCI_EXP_DEVCTL_CERE)) {
+        return false;
+    }
+
+    inj->msg.severity = PCI_ERR_ROOT_CMD_COR_EN;
+    return true;
+}
+
+static bool pcie_aer_inject_uncor_error(PCIEAERInject *inj, bool is_fatal)
+{
+    PCIDevice *dev = inj->dev;
+    uint16_t cmd;
+
+    if (is_fatal) {
+        inj->devsta |= PCI_EXP_DEVSTA_FED;
+    } else {
+        inj->devsta |= PCI_EXP_DEVSTA_NFED;
+    }
+    if (inj->unsupported_request) {
+        inj->devsta |= PCI_EXP_DEVSTA_URD;
+    }
+    pci_set_long(dev->config + dev->exp.exp_cap + PCI_EXP_DEVSTA, inj->devsta);
+
+    if (inj->aer_cap) {
+        uint32_t mask = pci_get_long(inj->aer_cap + PCI_ERR_UNCOR_MASK);
+        if (mask & inj->error_status) {
+            pci_long_test_and_set_mask(inj->aer_cap + PCI_ERR_UNCOR_STATUS,
+                                       inj->error_status);
+            return false;
+        }
+
+        inj->log_overflow = !!pcie_aer_record_error(dev, inj->err);
+        pci_long_test_and_set_mask(inj->aer_cap + PCI_ERR_UNCOR_STATUS,
+                                   inj->error_status);
+    }
+
+    cmd = pci_get_word(dev->config + PCI_COMMAND);
+    if (inj->unsupported_request &&
+        !(inj->devctl & PCI_EXP_DEVCTL_URRE) && !(cmd & PCI_COMMAND_SERR)) {
+        return false;
+    }
+    if (is_fatal) {
+        if (!((cmd & PCI_COMMAND_SERR) ||
+              (inj->devctl & PCI_EXP_DEVCTL_FERE))) {
+            return false;
+        }
+        inj->msg.severity = PCI_ERR_ROOT_CMD_FATAL_EN;
+    } else {
+        if (!((cmd & PCI_COMMAND_SERR) ||
+              (inj->devctl & PCI_EXP_DEVCTL_NFERE))) {
+            return false;
+        }
+        inj->msg.severity = PCI_ERR_ROOT_CMD_NONFATAL_EN;
+    }
+    return true;
+}
+
+/*
+ * non-Function specific error must be recorded in all functions.
+ * It is the responsibility of the caller of this function.
+ * It is also caller's responsiblity to determine which function should
+ * report the rerror.
+ *
+ * 6.2.4 Error Logging
+ * 6.2.5 Sqeunce of Device Error Signaling and Logging Operations
+ * table 6-2: Flowchard Showing Sequence of Device Error Signaling and Logging
+ *            Operations
+ */
+int pcie_aer_inject_error(PCIDevice *dev, const PCIEAERErr *err)
+{
+    uint8_t *aer_cap = NULL;
+    uint16_t devctl = 0;
+    uint16_t devsta = 0;
+    uint32_t error_status = err->status;
+    PCIEAERInject inj;
+
+    if (!pci_is_express(dev)) {
+        return -ENOSYS;
+    }
+
+    if (err->flags & PCIE_AER_ERR_IS_CORRECTABLE) {
+        error_status &= PCI_ERR_COR_SUPPORTED;
+    } else {
+        error_status &= PCI_ERR_UNC_SUPPORTED;
+    }
+
+    /* invalid status bit. one and only one bit must be set */
+    if (!error_status || (error_status & (error_status - 1))) {
+        return -EINVAL;
+    }
+
+    if (dev->exp.aer_cap) {
+        uint8_t *exp_cap = dev->config + dev->exp.exp_cap;
+        aer_cap = dev->config + dev->exp.aer_cap;
+        devctl = pci_get_long(exp_cap + PCI_EXP_DEVCTL);
+        devsta = pci_get_long(exp_cap + PCI_EXP_DEVSTA);
+    }
+
+    inj.dev = dev;
+    inj.aer_cap = aer_cap;
+    inj.err = err;
+    inj.devctl = devctl;
+    inj.devsta = devsta;
+    inj.error_status = error_status;
+    inj.unsupported_request = !(err->flags & PCIE_AER_ERR_IS_CORRECTABLE) &&
+        err->status == PCI_ERR_UNC_UNSUP;
+    inj.log_overflow = false;
+
+    if (err->flags & PCIE_AER_ERR_IS_CORRECTABLE) {
+        if (!pcie_aer_inject_cor_error(&inj, 0, false)) {
+            return 0;
+        }
+    } else {
+        bool is_fatal =
+            pcie_aer_uncor_default_severity(error_status) ==
+            PCI_ERR_ROOT_CMD_FATAL_EN;
+        if (aer_cap) {
+            is_fatal =
+                error_status & pci_get_long(aer_cap + PCI_ERR_UNCOR_SEVER);
+        }
+        if (!is_fatal && (err->flags & PCIE_AER_ERR_MAYBE_ADVISORY)) {
+            inj.error_status = PCI_ERR_COR_ADV_NONFATAL;
+            if (!pcie_aer_inject_cor_error(&inj, error_status, true)) {
+                return 0;
+            }
+        } else {
+            if (!pcie_aer_inject_uncor_error(&inj, is_fatal)) {
+                return 0;
+            }
+        }
+    }
+
+    /* send up error message */
+    inj.msg.source_id = err->source_id;
+    pcie_aer_msg(dev, &inj.msg);
+
+    if (inj.log_overflow) {
+        PCIEAERErr header_log_overflow = {
+            .status = PCI_ERR_COR_HL_OVERFLOW,
+            .flags = PCIE_AER_ERR_IS_CORRECTABLE,
+        };
+        int ret = pcie_aer_inject_error(dev, &header_log_overflow);
+        assert(!ret);
+    }
+    return 0;
+}
+
+void pcie_aer_write_config(PCIDevice *dev,
+                           uint32_t addr, uint32_t val, int len)
+{
+    uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
+    uint32_t errcap = pci_get_long(aer_cap + PCI_ERR_CAP);
+    uint32_t first_error = 1U << PCI_ERR_CAP_FEP(errcap);
+    uint32_t uncorsta = pci_get_long(aer_cap + PCI_ERR_UNCOR_STATUS);
+
+    /* uncorrectable error */
+    if (!(uncorsta & first_error)) {
+        /* the bit that corresponds to the first error is cleared */
+        pcie_aer_clear_error(dev);
+    } else if (errcap & PCI_ERR_CAP_MHRE) {
+        /* When PCI_ERR_CAP_MHRE is enabled and the first error isn't cleared
+         * nothing should happen. So we have to revert the modification to
+         * the register.
+         */
+        pcie_aer_update_uncor_status(dev);
+    } else {
+        /* capability & control
+         * PCI_ERR_CAP_MHRE might be cleared, so clear of header log.
+         */
+        aer_log_clear_all_err(&dev->exp.aer_log);
+    }
+}
+
+void pcie_aer_root_init(PCIDevice *dev)
+{
+    uint16_t pos = dev->exp.aer_cap;
+
+    pci_set_long(dev->wmask + pos + PCI_ERR_ROOT_COMMAND,
+                 PCI_ERR_ROOT_CMD_EN_MASK);
+    pci_set_long(dev->w1cmask + pos + PCI_ERR_ROOT_STATUS,
+                 PCI_ERR_ROOT_STATUS_REPORT_MASK);
+}
+
+void pcie_aer_root_reset(PCIDevice *dev)
+{
+    uint8_t* aer_cap = dev->config + dev->exp.aer_cap;
+
+    pci_set_long(aer_cap + PCI_ERR_ROOT_COMMAND, 0);
+
+    /*
+     * Advanced Error Interrupt Message Number in Root Error Status Register
+     * must be updated by chip dependent code because it's chip dependent
+     * which number is used.
+     */
+}
+
+static bool pcie_aer_root_does_trigger(uint32_t cmd, uint32_t status)
+{
+    return
+        ((cmd & PCI_ERR_ROOT_CMD_COR_EN) && (status & PCI_ERR_ROOT_COR_RCV)) ||
+        ((cmd & PCI_ERR_ROOT_CMD_NONFATAL_EN) &&
+         (status & PCI_ERR_ROOT_NONFATAL_RCV)) ||
+        ((cmd & PCI_ERR_ROOT_CMD_FATAL_EN) &&
+         (status & PCI_ERR_ROOT_FATAL_RCV));
+}
+
+void pcie_aer_root_write_config(PCIDevice *dev,
+                                uint32_t addr, uint32_t val, int len,
+                                uint32_t root_cmd_prev)
+{
+    uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
+
+    /* root command register */
+    uint32_t root_cmd = pci_get_long(aer_cap + PCI_ERR_ROOT_COMMAND);
+    if (root_cmd & PCI_ERR_ROOT_CMD_EN_MASK) {
+        /* 6.2.4.1.2 Interrupt Generation */
+
+        /* 0 -> 1 */
+        uint32_t root_cmd_set = (root_cmd_prev ^ root_cmd) & root_cmd;
+        uint32_t root_status = pci_get_long(aer_cap + PCI_ERR_ROOT_STATUS);
+
+        if (pci_msi_enabled(dev)) {
+            if (pcie_aer_root_does_trigger(root_cmd_set, root_status)) {
+                pci_msi_notify(dev, pcie_aer_root_get_vector(dev));
+            }
+        } else {
+            int int_level = pcie_aer_root_does_trigger(root_cmd, root_status);
+            qemu_set_irq(dev->irq[dev->exp.aer_intx], int_level);
+        }
+    }
+}
+
+static const VMStateDescription vmstate_pcie_aer_err = {
+    .name = "PCIE_AER_ERROR",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields     = (VMStateField[]) {
+        VMSTATE_UINT32(status, PCIEAERErr),
+        VMSTATE_UINT16(source_id, PCIEAERErr),
+        VMSTATE_UINT16(flags, PCIEAERErr),
+        VMSTATE_UINT32_ARRAY(header, PCIEAERErr, 4),
+        VMSTATE_UINT32_ARRAY(prefix, PCIEAERErr, 4),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+#define VMSTATE_PCIE_AER_ERRS(_field, _state, _field_num, _vmsd, _type) { \
+    .name       = (stringify(_field)),                                    \
+    .version_id = 0,                                                      \
+    .num_offset = vmstate_offset_value(_state, _field_num, uint16_t),     \
+    .size       = sizeof(_type),                                          \
+    .vmsd       = &(_vmsd),                                               \
+    .flags      = VMS_POINTER | VMS_VARRAY_UINT16 | VMS_STRUCT,           \
+    .offset     = vmstate_offset_pointer(_state, _field, _type),          \
+}
+
+const VMStateDescription vmstate_pcie_aer_log = {
+    .name = "PCIE_AER_ERROR_LOG",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields     = (VMStateField[]) {
+        VMSTATE_UINT16(log_num, PCIEAERLog),
+        VMSTATE_UINT16(log_max, PCIEAERLog),
+        VMSTATE_PCIE_AER_ERRS(log, PCIEAERLog, log_num,
+                              vmstate_pcie_aer_err, PCIEAERErr),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
diff --git a/hw/pcie_aer.h b/hw/pcie_aer.h
new file mode 100644
index 0000000..7539500
--- /dev/null
+++ b/hw/pcie_aer.h
@@ -0,0 +1,106 @@
+/*
+ * pcie_aer.h
+ *
+ * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef QEMU_PCIE_AER_H
+#define QEMU_PCIE_AER_H
+
+#include "hw.h"
+
+/* definitions which PCIExpressDevice uses */
+
+/* AER log */
+struct PCIEAERLog {
+    /* This structure is saved/loaded.
+       So explicitly size them instead of unsigned int */
+
+    /* the number of currently recorded log in log member */
+    uint16_t log_num;
+
+    /*
+     * The maximum number of the log. Errors can be logged up to this.
+     *
+     * This is configurable property.
+     * The specified value will be clipped down to PCIE_AER_LOG_MAX_LIMIT
+     * to avoid unreasonable memory usage.
+     * I bet that 128 log size would be big enough, otherwise too many errors
+     * for system to function normaly. But could consecutive errors occur?
+     */
+#define PCIE_AER_LOG_MAX_DEFAULT        8
+#define PCIE_AER_LOG_MAX_LIMIT          128
+#define PCIE_AER_LOG_MAX_UNSET          0xffff
+    uint16_t log_max;
+
+    /* Error log. log_max-sized array */
+    PCIEAERErr *log;
+};
+
+/* aer error message: error signaling message has only error sevirity and
+   source id. See 2.2.8.3 error signaling messages */
+struct PCIEAERMsg {
+    /*
+     * PCI_ERR_ROOT_CMD_{COR, NONFATAL, FATAL}_EN
+     * = PCI_EXP_DEVCTL_{CERE, NFERE, FERE}
+     */
+    uint32_t severity;
+
+    uint16_t source_id; /* bdf */
+};
+
+static inline bool
+pcie_aer_msg_is_uncor(const PCIEAERMsg *msg)
+{
+    return msg->severity == PCI_ERR_ROOT_CMD_NONFATAL_EN ||
+        msg->severity == PCI_ERR_ROOT_CMD_FATAL_EN;
+}
+
+/* error */
+struct PCIEAERErr {
+    uint32_t status;    /* error status bits */
+    uint16_t source_id; /* bdf */
+
+#define PCIE_AER_ERR_IS_CORRECTABLE     0x1     /* correctable/uncorrectable */
+#define PCIE_AER_ERR_MAYBE_ADVISORY     0x2     /* maybe advisory non-fatal */
+#define PCIE_AER_ERR_HEADER_VALID       0x4     /* TLP header is logged */
+#define PCIE_AER_ERR_TLP_PREFIX_PRESENT 0x8     /* TLP Prefix is logged */
+    uint16_t flags;
+
+    uint32_t header[4]; /* TLP header */
+    uint32_t prefix[4]; /* TLP header prefix */
+};
+
+extern const VMStateDescription vmstate_pcie_aer_log;
+
+int pcie_aer_init(PCIDevice *dev, uint16_t offset);
+void pcie_aer_exit(PCIDevice *dev);
+void pcie_aer_write_config(PCIDevice *dev,
+                           uint32_t addr, uint32_t val, int len);
+
+/* aer root port */
+void pcie_aer_root_set_vector(PCIDevice *dev, unsigned int vector);
+void pcie_aer_root_init(PCIDevice *dev);
+void pcie_aer_root_reset(PCIDevice *dev);
+void pcie_aer_root_write_config(PCIDevice *dev,
+                                uint32_t addr, uint32_t val, int len,
+                                uint32_t root_cmd_prev);
+
+/* error injection */
+int pcie_aer_inject_error(PCIDevice *dev, const PCIEAERErr *err);
+
+#endif /* QEMU_PCIE_AER_H */
diff --git a/qemu-common.h b/qemu-common.h
index b3957f1..de82c2e 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -240,6 +240,9 @@ typedef struct PCIBus PCIBus;
 typedef struct PCIDevice PCIDevice;
 typedef struct PCIExpressDevice PCIExpressDevice;
 typedef struct PCIBridge PCIBridge;
+typedef struct PCIEAERMsg PCIEAERMsg;
+typedef struct PCIEAERLog PCIEAERLog;
+typedef struct PCIEAERErr PCIEAERErr;
 typedef struct PCIEPort PCIEPort;
 typedef struct PCIESlot PCIESlot;
 typedef struct SerialState SerialState;
commit 1a1ea6f093eb8cf7c01788bc3708ba7003815563
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Tue Nov 16 17:26:08 2010 +0900

    pcie_regs.h: more constants
    
    Add constants for PCI AER log.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pcie_regs.h b/hw/pcie_regs.h
index 3461a1b..4d123d9 100644
--- a/hw/pcie_regs.h
+++ b/hw/pcie_regs.h
@@ -94,7 +94,9 @@
 #define PCI_ERR_CAP_MHRE                0x00000400
 #define PCI_ERR_CAP_TLP                 0x00000800
 
+#define PCI_ERR_HEADER_LOG_SIZE         16
 #define PCI_ERR_TLP_PREFIX_LOG          0x38
+#define PCI_ERR_TLP_PREFIX_LOG_SIZE     16
 
 #define PCI_SEC_STATUS_RCV_SYSTEM_ERROR         0x4000
 
commit 89d437df5e68e8b289e501dde570917677fd6dfc
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Tue Nov 16 17:26:07 2010 +0900

    pci: add W1C bits to pci status register
    
    This patch adds W1C bit support in the initialization/reset of pci
    status registers.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci.c b/hw/pci.c
index 438c0d1..00ec8ea 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -143,6 +143,9 @@ static void pci_device_reset(PCIDevice *dev)
     pci_word_test_and_clear_mask(dev->config + PCI_COMMAND,
                                  pci_get_word(dev->wmask + PCI_COMMAND) |
                                  pci_get_word(dev->w1cmask + PCI_COMMAND));
+    pci_word_test_and_clear_mask(dev->config + PCI_STATUS,
+                                 pci_get_word(dev->wmask + PCI_STATUS) |
+                                 pci_get_word(dev->w1cmask + PCI_STATUS));
     dev->config[PCI_CACHE_LINE_SIZE] = 0x0;
     dev->config[PCI_INTERRUPT_LINE] = 0x0;
     for (r = 0; r < PCI_NUM_REGIONS; ++r) {
@@ -552,6 +555,18 @@ static void pci_init_wmask(PCIDevice *dev)
            config_size - PCI_CONFIG_HEADER_SIZE);
 }
 
+static void pci_init_w1cmask(PCIDevice *dev)
+{
+    /*
+     * Note: It's okay to set w1mask even for readonly bits as
+     * long as their value is hardwired to 0.
+     */
+    pci_set_word(dev->w1cmask + PCI_STATUS,
+                 PCI_STATUS_PARITY | PCI_STATUS_SIG_TARGET_ABORT |
+                 PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_REC_MASTER_ABORT |
+                 PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY);
+}
+
 static void pci_init_wmask_bridge(PCIDevice *d)
 {
     /* PCI_PRIMARY_BUS, PCI_SECONDARY_BUS, PCI_SUBORDINATE_BUS and
@@ -676,6 +691,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
     }
     pci_init_cmask(pci_dev);
     pci_init_wmask(pci_dev);
+    pci_init_w1cmask(pci_dev);
     if (is_bridge) {
         pci_init_wmask_bridge(pci_dev);
     }
commit a6f9dd02f75685934ca52f038b6fcb38b661c283
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Wed Nov 10 15:59:57 2010 -0200

    Makefile: Fix check dependency breakage
    
    Commit b152aa84d52882bb1846485a89baf13aa07c86bc broke the unit-tests
    build, fix it.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/Makefile b/Makefile
index 747e47c..4e120a2 100644
--- a/Makefile
+++ b/Makefile
@@ -163,12 +163,14 @@ qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
 
 check-qint.o check-qstring.o check-qdict.o check-qlist.o check-qfloat.o check-qjson.o: $(GENERATED_HEADERS)
 
-check-qint: check-qint.o qint.o qemu-malloc.o $(trace-obj-y)
-check-qstring: check-qstring.o qstring.o qemu-malloc.o $(trace-obj-y)
-check-qdict: check-qdict.o qdict.o qfloat.o qint.o qstring.o qbool.o qemu-malloc.o qlist.o $(trace-obj-y)
-check-qlist: check-qlist.o qlist.o qint.o qemu-malloc.o $(trace-obj-y)
-check-qfloat: check-qfloat.o qfloat.o qemu-malloc.o $(trace-obj-y)
-check-qjson: check-qjson.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o qjson.o json-streamer.o json-lexer.o json-parser.o qemu-malloc.o $(trace-obj-y)
+CHECK_PROG_DEPS = qemu-malloc.o $(oslib-obj-y) $(trace-obj-y)
+
+check-qint: check-qint.o qint.o $(CHECK_PROG_DEPS)
+check-qstring: check-qstring.o qstring.o $(CHECK_PROG_DEPS)
+check-qdict: check-qdict.o qdict.o qfloat.o qint.o qstring.o qbool.o qlist.o $(CHECK_PROG_DEPS)
+check-qlist: check-qlist.o qlist.o qint.o $(CHECK_PROG_DEPS)
+check-qfloat: check-qfloat.o qfloat.o $(CHECK_PROG_DEPS)
+check-qjson: check-qjson.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o qjson.o json-streamer.o json-lexer.o json-parser.o $(CHECK_PROG_DEPS)
 
 clean:
 # avoid old build problems by removing potentially incorrect old files
commit 11217a757e7dda66fd2e78b10ea0cd8d6b290e42
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Thu Oct 28 13:28:37 2010 -0200

    QMP/qmp-shell: Introduce HMP mode
    
    In which qmp-shell will exclusively use the HMP passthrough feature,
    this is useful for testing.
    
    Example:
    
        # ./qmp-shell -H qmp-sock
        Welcome to the HMP shell!
        Connected to QEMU 0.13.50
    
        (QEMU) info network
        VLAN 0 devices:
          user.0: net=10.0.2.0, restricted=n
            e1000.0: model=e1000,macaddr=52:54:00:12:34:56
            Devices not on any VLAN:
        (QEMU)
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/QMP/qmp-shell b/QMP/qmp-shell
index 1fb7e76..42dabc8 100755
--- a/QMP/qmp-shell
+++ b/QMP/qmp-shell
@@ -145,6 +145,76 @@ class QMPShell(qmp.QEMUMonitorProtocol):
         else:
             return self._execute_cmd(cmdline)
 
+class HMPShell(QMPShell):
+    def __init__(self, address):
+        QMPShell.__init__(self, address)
+        self.__cpu_index = 0
+
+    def __cmd_completion(self):
+        for cmd in self.__cmd_passthrough('help')['return'].split('\r\n'):
+            if cmd and cmd[0] != '[' and cmd[0] != '\t':
+                name = cmd.split()[0] # drop help text
+                if name == 'info':
+                    continue
+                if name.find('|') != -1:
+                    # Command in the form 'foobar|f' or 'f|foobar', take the
+                    # full name
+                    opt = name.split('|')
+                    if len(opt[0]) == 1:
+                        name = opt[1]
+                    else:
+                        name = opt[0]
+                self._completer.append(name)
+                self._completer.append('help ' + name) # help completion
+
+    def __info_completion(self):
+        for cmd in self.__cmd_passthrough('info')['return'].split('\r\n'):
+            if cmd:
+                self._completer.append('info ' + cmd.split()[1])
+
+    def __other_completion(self):
+        # special cases
+        self._completer.append('help info')
+
+    def _fill_completion(self):
+        self.__cmd_completion()
+        self.__info_completion()
+        self.__other_completion()
+
+    def __cmd_passthrough(self, cmdline, cpu_index = 0):
+        return self.cmd_obj({ 'execute': 'human-monitor-command', 'arguments':
+                              { 'command-line': cmdline,
+                                'cpu-index': cpu_index } })
+
+    def _execute_cmd(self, cmdline):
+        if cmdline.split()[0] == "cpu":
+            # trap the cpu command, it requires special setting
+            try:
+                idx = int(cmdline.split()[1])
+                if not 'return' in self.__cmd_passthrough('info version', idx):
+                    print 'bad CPU index'
+                    return True
+                self.__cpu_index = idx
+            except ValueError:
+                print 'cpu command takes an integer argument'
+                return True
+        resp = self.__cmd_passthrough(cmdline, self.__cpu_index)
+        if resp is None:
+            print 'Disconnected'
+            return False
+        assert 'return' in resp or 'error' in resp
+        if 'return' in resp:
+            # Success
+            if len(resp['return']) > 0:
+                print resp['return'],
+        else:
+            # Error
+            print '%s: %s' % (resp['error']['class'], resp['error']['desc'])
+        return True
+
+    def show_banner(self):
+        QMPShell.show_banner(self, msg='Welcome to the HMP shell!')
+
 def die(msg):
     sys.stderr.write('ERROR: %s\n' % msg)
     sys.exit(1)
@@ -156,9 +226,16 @@ def fail_cmdline(option=None):
     sys.exit(1)
 
 def main():
+    addr = ''
     try:
         if len(sys.argv) == 2:
             qemu = QMPShell(sys.argv[1])
+            addr = sys.argv[1]
+        elif len(sys.argv) == 3:
+            if sys.argv[1] != '-H':
+                fail_cmdline(sys.argv[1])
+            qemu = HMPShell(sys.argv[2])
+            addr = sys.argv[2]
         else:
                 fail_cmdline()
     except QMPShellBadPort:
@@ -171,7 +248,7 @@ def main():
     except qmp.QMPCapabilitiesError:
         die('Could not negotiate capabilities')
     except qemu.error:
-        die('Could not connect to %s' % sys.argv[1])
+        die('Could not connect to %s' % addr)
 
     qemu.show_banner()
     while qemu.read_exec_command('(QEMU) '):
commit 0268d97c51207f35a5a01239ad92ef2c35dcd5ba
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Fri Oct 22 10:08:02 2010 -0200

    QMP: Introduce Human Monitor passthrough command
    
    This command allows QMP clients to execute HMP commands.
    
    Please, check the documentation added to the qmp-commands.hx file
    for additional details about the interface and its limitations.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/monitor.c b/monitor.c
index 8cee35d..ec31eac 100644
--- a/monitor.c
+++ b/monitor.c
@@ -491,6 +491,44 @@ static int do_qmp_capabilities(Monitor *mon, const QDict *params,
     return 0;
 }
 
+static int mon_set_cpu(int cpu_index);
+static void handle_user_command(Monitor *mon, const char *cmdline);
+
+static int do_hmp_passthrough(Monitor *mon, const QDict *params,
+                              QObject **ret_data)
+{
+    int ret = 0;
+    Monitor *old_mon, hmp;
+    CharDriverState mchar;
+
+    memset(&hmp, 0, sizeof(hmp));
+    qemu_chr_init_mem(&mchar);
+    hmp.chr = &mchar;
+
+    old_mon = cur_mon;
+    cur_mon = &hmp;
+
+    if (qdict_haskey(params, "cpu-index")) {
+        ret = mon_set_cpu(qdict_get_int(params, "cpu-index"));
+        if (ret < 0) {
+            cur_mon = old_mon;
+            qerror_report(QERR_INVALID_PARAMETER_VALUE, "cpu-index", "a CPU number");
+            goto out;
+        }
+    }
+
+    handle_user_command(&hmp, qdict_get_str(params, "command-line"));
+    cur_mon = old_mon;
+
+    if (qemu_chr_mem_osize(hmp.chr) > 0) {
+        *ret_data = QOBJECT(qemu_chr_mem_to_qs(hmp.chr));
+    }
+
+out:
+    qemu_chr_close_mem(hmp.chr);
+    return ret;
+}
+
 static int compare_cmd(const char *name, const char *list)
 {
     const char *p, *pstart;
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 793cf1c..e5f157f 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -761,6 +761,51 @@ Example:
 
 Note: This command must be issued before issuing any other command.
 
+EQMP
+
+    {
+        .name       = "human-monitor-command",
+        .args_type  = "command-line:s,cpu-index:i?",
+        .params     = "",
+        .help       = "",
+        .user_print = monitor_user_noop,
+        .mhandler.cmd_new = do_hmp_passthrough,
+    },
+
+SQMP
+human-monitor-command
+---------------------
+
+Execute a Human Monitor command.
+
+Arguments: 
+
+- command-line: the command name and its arguments, just like the
+                Human Monitor's shell (json-string)
+- cpu-index: select the CPU number to be used by commands which access CPU
+             data, like 'info registers'. The Monitor selects CPU 0 if this
+             argument is not provided (json-int, optional)
+
+Example:
+
+-> { "execute": "human-monitor-command", "arguments": { "command-line": "info kvm" } }
+<- { "return": "kvm support: enabled\r\n" }
+
+Notes:
+
+(1) The Human Monitor is NOT an stable interface, this means that command
+    names, arguments and responses can change or be removed at ANY time.
+    Applications that rely on long term stability guarantees should NOT
+    use this command
+
+(2) Limitations:
+
+    o This command is stateless, this means that commands that depend
+      on state information (such as getfd) might not work
+
+    o Commands that prompt the user for data (eg. 'cont' when the block
+      device is encrypted) don't currently work
+
 3. Query Commands
 =================
 
commit 999bd67c879cbd8bf0fe2b4ff0fb308a9a48ec72
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Fri Oct 22 16:09:05 2010 -0200

    qemu-char: Introduce Memory driver
    
    This driver handles in-memory chardev operations. That's, all writes
    to this driver are stored in an internal buffer and it doesn't talk
    to the external world in any way.
    
    Right now it's very simple: it supports only writes. But it can be
    easily extended to support more operations.
    
    This is going to be used by the monitor's "HMP passthrough via QMP"
    feature, which needs to run monitor handlers without a backing
    device.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/qemu-char.c b/qemu-char.c
index 88997f9..edc9ad6 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2275,6 +2275,70 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
     return NULL;
 }
 
+/***********************************************************/
+/* Memory chardev */
+typedef struct {
+    size_t outbuf_size;
+    size_t outbuf_capacity;
+    uint8_t *outbuf;
+} MemoryDriver;
+
+static int mem_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+{
+    MemoryDriver *d = chr->opaque;
+
+    /* TODO: the QString implementation has the same code, we should
+     * introduce a generic way to do this in cutils.c */
+    if (d->outbuf_capacity < d->outbuf_size + len) {
+        /* grow outbuf */
+        d->outbuf_capacity += len;
+        d->outbuf_capacity *= 2;
+        d->outbuf = qemu_realloc(d->outbuf, d->outbuf_capacity);
+    }
+
+    memcpy(d->outbuf + d->outbuf_size, buf, len);
+    d->outbuf_size += len;
+
+    return len;
+}
+
+void qemu_chr_init_mem(CharDriverState *chr)
+{
+    MemoryDriver *d;
+
+    d = qemu_malloc(sizeof(*d));
+    d->outbuf_size = 0;
+    d->outbuf_capacity = 4096;
+    d->outbuf = qemu_mallocz(d->outbuf_capacity);
+
+    memset(chr, 0, sizeof(*chr));
+    chr->opaque = d;
+    chr->chr_write = mem_chr_write;
+}
+
+QString *qemu_chr_mem_to_qs(CharDriverState *chr)
+{
+    MemoryDriver *d = chr->opaque;
+    return qstring_from_substr((char *) d->outbuf, 0, d->outbuf_size - 1);
+}
+
+/* NOTE: this driver can not be closed with qemu_chr_close()! */
+void qemu_chr_close_mem(CharDriverState *chr)
+{
+    MemoryDriver *d = chr->opaque;
+
+    qemu_free(d->outbuf);
+    qemu_free(chr->opaque);
+    chr->opaque = NULL;
+    chr->chr_write = NULL;
+}
+
+size_t qemu_chr_mem_osize(const CharDriverState *chr)
+{
+    const MemoryDriver *d = chr->opaque;
+    return d->outbuf_size;
+}
+
 QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
 {
     char host[65], port[33], width[8], height[8];
diff --git a/qemu-char.h b/qemu-char.h
index 18ad12b..e6ee6c4 100644
--- a/qemu-char.h
+++ b/qemu-char.h
@@ -6,6 +6,7 @@
 #include "qemu-option.h"
 #include "qemu-config.h"
 #include "qobject.h"
+#include "qstring.h"
 
 /* character device */
 
@@ -100,6 +101,12 @@ CharDriverState *qemu_chr_open_eventfd(int eventfd);
 
 extern int term_escape_char;
 
+/* memory chardev */
+void qemu_chr_init_mem(CharDriverState *chr);
+void qemu_chr_close_mem(CharDriverState *chr);
+QString *qemu_chr_mem_to_qs(CharDriverState *chr);
+size_t qemu_chr_mem_osize(const CharDriverState *chr);
+
 /* async I/O support */
 
 int qemu_set_fd_handler2(int fd,
commit 4cdbc094ca3865696c1456f1586818766bf9aae6
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Wed Oct 27 18:03:01 2010 -0200

    QMP: Drop vm-info example script
    
    It's broken and not really useful, let's just drop it.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/QMP/README b/QMP/README
index 80503f2..c95a08c 100644
--- a/QMP/README
+++ b/QMP/README
@@ -19,10 +19,7 @@ o qmp-spec.txt      QEMU Monitor Protocol current specification
 o qmp-commands.txt  QMP supported commands (auto-generated at build-time)
 o qmp-events.txt    List of available asynchronous events
 
-There are also two simple Python scripts available:
-
-o qmp-shell  A shell
-o vm-info    Show some information about the Virtual Machine
+There is also a simple Python script called 'qmp-shell' available.
 
 IMPORTANT: It's strongly recommended to read the 'Stability Considerations'
 section in the qmp-commands.txt file before making any serious use of QMP.
diff --git a/QMP/vm-info b/QMP/vm-info
deleted file mode 100755
index be5b038..0000000
--- a/QMP/vm-info
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/usr/bin/python
-#
-# Print Virtual Machine information
-#
-# Usage:
-#
-# Start QEMU with:
-#
-# $ qemu [...] -monitor control,unix:./qmp,server
-#
-# Run vm-info:
-#
-# $ vm-info ./qmp
-#
-# Luiz Capitulino <lcapitulino at redhat.com>
-
-import qmp
-from sys import argv,exit
-
-def main():
-    if len(argv) != 2:
-        print 'vm-info <unix-socket>'
-        exit(1)
-
-    qemu = qmp.QEMUMonitorProtocol(argv[1])
-    qemu.connect()
-    qemu.send("qmp_capabilities")
-
-    for cmd in [ 'version', 'kvm', 'status', 'uuid', 'balloon' ]:
-        print cmd + ': ' + str(qemu.send('query-' + cmd))
-
-if __name__ == '__main__':
-    main()
commit 9bed0d0d1c5667a2e1124c8e44d31ac254ca2efb
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Wed Oct 27 17:57:51 2010 -0200

    QMP: Revamp the qmp-shell script
    
    This commit updates the qmp-shell script to use the new interface
    introduced by the last commit.
    
    Additionally, the following fixes/features are also introduced:
    
     o TCP sockets support
     o Update/add documentation
     o Simple command-line completion
     o Fix a number of unhandled errors
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/QMP/qmp-shell b/QMP/qmp-shell
index a5b72d1..1fb7e76 100755
--- a/QMP/qmp-shell
+++ b/QMP/qmp-shell
@@ -1,8 +1,8 @@
 #!/usr/bin/python
 #
-# Simple QEMU shell on top of QMP
+# Low-level QEMU shell on top of QMP.
 #
-# Copyright (C) 2009 Red Hat Inc.
+# Copyright (C) 2009, 2010 Red Hat Inc.
 #
 # Authors:
 #  Luiz Capitulino <lcapitulino at redhat.com>
@@ -14,60 +14,169 @@
 #
 # Start QEMU with:
 #
-# $ qemu [...] -monitor control,unix:./qmp,server
+# # qemu [...] -qmp unix:./qmp-sock,server
 #
 # Run the shell:
 #
-# $ qmp-shell ./qmp
+# $ qmp-shell ./qmp-sock
 #
 # Commands have the following format:
 #
-# < command-name > [ arg-name1=arg1 ] ... [ arg-nameN=argN ]
+#    < command-name > [ arg-name1=arg1 ] ... [ arg-nameN=argN ]
 #
 # For example:
 #
-# (QEMU) info item=network
+# (QEMU) device_add driver=e1000 id=net1
+# {u'return': {}}
+# (QEMU)
 
 import qmp
 import readline
-from sys import argv,exit
+import sys
 
-def shell_help():
-    print 'bye  exit from the shell'
+class QMPCompleter(list):
+    def complete(self, text, state):
+        for cmd in self:
+            if cmd.startswith(text):
+                if not state:
+                    return cmd
+                else:
+                    state -= 1
 
-def main():
-    if len(argv) != 2:
-        print 'qemu-shell <unix-socket>'
-        exit(1)
+class QMPShellError(Exception):
+    pass
+
+class QMPShellBadPort(QMPShellError):
+    pass
+
+# TODO: QMPShell's interface is a bit ugly (eg. _fill_completion() and
+#       _execute_cmd()). Let's design a better one.
+class QMPShell(qmp.QEMUMonitorProtocol):
+    def __init__(self, address):
+        qmp.QEMUMonitorProtocol.__init__(self, self.__get_address(address))
+        self._greeting = None
+        self._completer = None
+
+    def __get_address(self, arg):
+        """
+        Figure out if the argument is in the port:host form, if it's not it's
+        probably a file path.
+        """
+        addr = arg.split(':')
+        if len(addr) == 2:
+            try:
+                port = int(addr[1])
+            except ValueError:
+                raise QMPShellBadPort
+            return ( addr[0], port )
+        # socket path
+        return arg
+
+    def _fill_completion(self):
+        for cmd in self.cmd('query-commands')['return']:
+            self._completer.append(cmd['name'])
+
+    def __completer_setup(self):
+        self._completer = QMPCompleter()
+        self._fill_completion()
+        readline.set_completer(self._completer.complete)
+        readline.parse_and_bind("tab: complete")
+        # XXX: default delimiters conflict with some command names (eg. query-),
+        # clearing everything as it doesn't seem to matter
+        readline.set_completer_delims('')
+
+    def __build_cmd(self, cmdline):
+        """
+        Build a QMP input object from a user provided command-line in the
+        following format:
+    
+            < command-name > [ arg-name1=arg1 ] ... [ arg-nameN=argN ]
+        """
+        cmdargs = cmdline.split()
+        qmpcmd = { 'execute': cmdargs[0], 'arguments': {} }
+        for arg in cmdargs[1:]:
+            opt = arg.split('=')
+            try:
+                value = int(opt[1])
+            except ValueError:
+                value = opt[1]
+            qmpcmd['arguments'][opt[0]] = value
+        return qmpcmd
+
+    def _execute_cmd(self, cmdline):
+        try:
+            qmpcmd = self.__build_cmd(cmdline)
+        except:
+            print 'command format: <command-name> ',
+            print '[arg-name1=arg1] ... [arg-nameN=argN]'
+            return True
+        resp = self.cmd_obj(qmpcmd)
+        if resp is None:
+            print 'Disconnected'
+            return False
+        print resp
+        return True
+
+    def connect(self):
+        self._greeting = qmp.QEMUMonitorProtocol.connect(self)
+        self.__completer_setup()
 
-    qemu = qmp.QEMUMonitorProtocol(argv[1])
-    qemu.connect()
-    qemu.send("qmp_capabilities")
+    def show_banner(self, msg='Welcome to the QMP low-level shell!'):
+        print msg
+        version = self._greeting['QMP']['version']['qemu']
+        print 'Connected to QEMU %d.%d.%d\n' % (version['major'],version['minor'],version['micro'])
 
-    print 'Connected!'
+    def read_exec_command(self, prompt):
+        """
+        Read and execute a command.
 
-    while True:
+        @return True if execution was ok, return False if disconnected.
+        """
         try:
-            cmd = raw_input('(QEMU) ')
+            cmdline = raw_input(prompt)
         except EOFError:
             print
-            break
-        if cmd == '':
-            continue
-        elif cmd == 'bye':
-            break
-        elif cmd == 'help':
-            shell_help()
+            return False
+        if cmdline == '':
+            for ev in self.get_events():
+                print ev
+            self.clear_events()
+            return True
         else:
-            try:
-                resp = qemu.send(cmd)
-                if resp == None:
-                    print 'Disconnected'
-                    break
-                print resp
-            except IndexError:
-                print '-> command format: <command-name> ',
-                print '[arg-name1=arg1] ... [arg-nameN=argN]'
+            return self._execute_cmd(cmdline)
+
+def die(msg):
+    sys.stderr.write('ERROR: %s\n' % msg)
+    sys.exit(1)
+
+def fail_cmdline(option=None):
+    if option:
+        sys.stderr.write('ERROR: bad command-line option \'%s\'\n' % option)
+    sys.stderr.write('qemu-shell [ -H ] < UNIX socket path> | < TCP address:port >\n')
+    sys.exit(1)
+
+def main():
+    try:
+        if len(sys.argv) == 2:
+            qemu = QMPShell(sys.argv[1])
+        else:
+                fail_cmdline()
+    except QMPShellBadPort:
+        die('bad port number in command-line')
+
+    try:
+        qemu.connect()
+    except qmp.QMPConnectError:
+        die('Didn\'t get QMP greeting message')
+    except qmp.QMPCapabilitiesError:
+        die('Could not negotiate capabilities')
+    except qemu.error:
+        die('Could not connect to %s' % sys.argv[1])
+
+    qemu.show_banner()
+    while qemu.read_exec_command('(QEMU) '):
+        pass
+    qemu.close()
 
 if __name__ == '__main__':
     main()
commit 1d00a07de980ecf643c7d7699dfc48e94bec15ae
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Wed Oct 27 17:43:34 2010 -0200

    QMP: Revamp the Python class example
    
    This commit simplifies and fixes a number of problems in the Python
    QEMUMonitorProtocol example class.
    
    It's almost a rewrite and it DOES BREAK the qmp-shell script (which
    is going to be fixed in the next commit).
    
    However, I'm not going to split this in different commits because it
    could get up to 10 commits, it's really not worth it for a simple
    demo class.
    
    Highlights:
    
     o TCP sockets support
     o QMP events support
     o Add documentation
     o Fix a number of unhandled errors
     o Simplify methods that send commands to the Monitor
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/QMP/qmp.py b/QMP/qmp.py
index 4062f84..14ce8b0 100644
--- a/QMP/qmp.py
+++ b/QMP/qmp.py
@@ -1,6 +1,6 @@
 # QEMU Monitor Protocol Python class
 # 
-# Copyright (C) 2009 Red Hat Inc.
+# Copyright (C) 2009, 2010 Red Hat Inc.
 #
 # Authors:
 #  Luiz Capitulino <lcapitulino at redhat.com>
@@ -8,7 +8,9 @@
 # This work is licensed under the terms of the GNU GPL, version 2.  See
 # the COPYING file in the top-level directory.
 
-import socket, json
+import json
+import errno
+import socket
 
 class QMPError(Exception):
     pass
@@ -16,61 +18,114 @@ class QMPError(Exception):
 class QMPConnectError(QMPError):
     pass
 
+class QMPCapabilitiesError(QMPError):
+    pass
+
 class QEMUMonitorProtocol:
+    def __init__(self, address):
+        """
+        Create a QEMUMonitorProtocol class.
+
+        @param address: QEMU address, can be either a unix socket path (string)
+                        or a tuple in the form ( address, port ) for a TCP
+                        connection
+        @note No connection is established, this is done by the connect() method
+        """
+        self.__events = []
+        self.__address = address
+        self.__sock = self.__get_sock()
+        self.__sockfile = self.__sock.makefile()
+
+    def __get_sock(self):
+        if isinstance(self.__address, tuple):
+            family = socket.AF_INET
+        else:
+            family = socket.AF_UNIX
+        return socket.socket(family, socket.SOCK_STREAM)
+
+    def __json_read(self):
+        while True:
+            data = self.__sockfile.readline()
+            if not data:
+                return
+            resp = json.loads(data)
+            if 'event' in resp:
+                self.__events.append(resp)
+                continue
+            return resp
+
+    error = socket.error
+
     def connect(self):
-        self.sock.connect(self.filename)
-        data = self.__json_read()
-        if data == None:
-            raise QMPConnectError
-        if not data.has_key('QMP'):
+        """
+        Connect to the QMP Monitor and perform capabilities negotiation.
+
+        @return QMP greeting dict
+        @raise socket.error on socket connection errors
+        @raise QMPConnectError if the greeting is not received
+        @raise QMPCapabilitiesError if fails to negotiate capabilities
+        """
+        self.__sock.connect(self.__address)
+        greeting = self.__json_read()
+        if greeting is None or not greeting.has_key('QMP'):
             raise QMPConnectError
-        return data['QMP']['capabilities']
+        # Greeting seems ok, negotiate capabilities
+        resp = self.cmd('qmp_capabilities')
+        if "return" in resp:
+            return greeting
+        raise QMPCapabilitiesError
 
-    def close(self):
-        self.sock.close()
+    def cmd_obj(self, qmp_cmd):
+        """
+        Send a QMP command to the QMP Monitor.
 
-    def send_raw(self, line):
-        self.sock.send(str(line))
+        @param qmp_cmd: QMP command to be sent as a Python dict
+        @return QMP response as a Python dict or None if the connection has
+                been closed
+        """
+        try:
+            self.__sock.sendall(json.dumps(qmp_cmd))
+        except socket.error, err:
+            if err[0] == errno.EPIPE:
+                return
+            raise socket.error(err)
         return self.__json_read()
 
-    def send(self, cmdline):
-        cmd = self.__build_cmd(cmdline)
-        self.__json_send(cmd)
-        resp = self.__json_read()
-        if resp == None:
-            return
-        elif resp.has_key('error'):
-            return resp['error']
-        else:
-            return resp['return']
-
-    def __build_cmd(self, cmdline):
-        cmdargs = cmdline.split()
-        qmpcmd = { 'execute': cmdargs[0], 'arguments': {} }
-        for arg in cmdargs[1:]:
-            opt = arg.split('=')
-            try:
-                value = int(opt[1])
-            except ValueError:
-                value = opt[1]
-            qmpcmd['arguments'][opt[0]] = value
-        return qmpcmd
-
-    def __json_send(self, cmd):
-        # XXX: We have to send any additional char, otherwise
-        # the Server won't read our input
-        self.sock.send(json.dumps(cmd) + ' ')
+    def cmd(self, name, args=None, id=None):
+        """
+        Build a QMP command and send it to the QMP Monitor.
 
-    def __json_read(self):
+        @param name: command name (string)
+        @param args: command arguments (dict)
+        @param id: command id (dict, list, string or int)
+        """
+        qmp_cmd = { 'execute': name }
+        if args:
+            qmp_cmd['arguments'] = args
+        if id:
+            qmp_cmd['id'] = id
+        return self.cmd_obj(qmp_cmd)
+
+    def get_events(self):
+        """
+        Get a list of available QMP events.
+        """
+        self.__sock.setblocking(0)
         try:
-            while True:
-                line = json.loads(self.sockfile.readline())
-                if not 'event' in line:
-                    return line
-        except ValueError:
-            return
-
-    def __init__(self, filename):
-        self.filename = filename
-        self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
-        self.sockfile = self.sock.makefile()
+            self.__json_read()
+        except socket.error, err:
+            if err[0] == errno.EAGAIN:
+                # No data available
+                pass
+        self.__sock.setblocking(1)
+        return self.__events
+
+    def clear_events(self):
+        """
+        Clear current list of pending events.
+        """
+        self.__events = []
+
+    def close(self):
+        self.__sock.close()
+        self.__sockfile.close()
commit e927d48722fdcba50f82d653c5a1927752483054
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Fri Nov 12 16:21:35 2010 +0900

    pci: allow hotplug removal of cold-plugged devices
    
    This patch fixes hot unplug of cold plugged devices
    (those present at system start), which got broken by
    5beb8ad503c88a76f2b8106c3b74b4ce485a60e1 .
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    Acked-by: Cam Macdonell <cam at cs.ualberta.ca>
    Tested-by: Cam Macdonell <cam at cs.ualberta.ca>
    Reported-by: Cam Macdonell <cam at cs.ualberta.ca>.

diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 66c7885..f549089 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -585,7 +585,8 @@ static void pciej_write(void *opaque, uint32_t addr, uint32_t val)
     PIIX4_DPRINTF("pciej write %x <== %d\n", addr, val);
 }
 
-static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev, int state);
+static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
+                                PCIHotplugState state);
 
 static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s)
 {
@@ -615,18 +616,23 @@ static void disable_device(PIIX4PMState *s, int slot)
     s->pci0_status.down |= (1 << slot);
 }
 
-static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev, int state)
+static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
+				PCIHotplugState state)
 {
     int slot = PCI_SLOT(dev->devfn);
     PIIX4PMState *s = DO_UPCAST(PIIX4PMState, dev,
                                 DO_UPCAST(PCIDevice, qdev, qdev));
 
-    if (!dev->qdev.hotplugged)
+    /* Don't send event when device is enabled during qemu machine creation:
+     * it is present on boot, no hotplug event is necessary. We do send an
+     * event when the device is disabled later. */
+    if (state == PCI_COLDPLUG_ENABLED) {
         return 0;
+    }
 
     s->pci0_status.up = 0;
     s->pci0_status.down = 0;
-    if (state) {
+    if (state == PCI_HOTPLUG_ENABLED) {
         enable_device(s, slot);
     } else {
         disable_device(s, slot);
diff --git a/hw/pci.c b/hw/pci.c
index 8f6fcf8..438c0d1 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -1558,8 +1558,11 @@ static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
     pci_add_option_rom(pci_dev);
 
     if (bus->hotplug) {
-        /* lower layer must check qdev->hotplugged */
-        rc = bus->hotplug(bus->hotplug_qdev, pci_dev, 1);
+        /* Let buses differentiate between hotplug and when device is
+         * enabled during qemu machine creation. */
+        rc = bus->hotplug(bus->hotplug_qdev, pci_dev,
+                          qdev->hotplugged ? PCI_HOTPLUG_ENABLED:
+                          PCI_COLDPLUG_ENABLED);
         if (rc != 0) {
             int r = pci_unregister_device(&pci_dev->qdev);
             assert(!r);
@@ -1573,7 +1576,8 @@ static int pci_unplug_device(DeviceState *qdev)
 {
     PCIDevice *dev = DO_UPCAST(PCIDevice, qdev, qdev);
 
-    return dev->bus->hotplug(dev->bus->hotplug_qdev, dev, 0);
+    return dev->bus->hotplug(dev->bus->hotplug_qdev, dev,
+                             PCI_HOTPLUG_DISABLED);
 }
 
 void pci_qdev_register(PCIDeviceInfo *info)
diff --git a/hw/pci.h b/hw/pci.h
index 7100804..09b3e4c 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -214,7 +214,15 @@ 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)(DeviceState *qdev, PCIDevice *pci_dev, int state);
+
+typedef enum {
+    PCI_HOTPLUG_DISABLED,
+    PCI_HOTPLUG_ENABLED,
+    PCI_COLDPLUG_ENABLED,
+} PCIHotplugState;
+
+typedef int (*pci_hotplug_fn)(DeviceState *qdev, PCIDevice *pci_dev,
+                              PCIHotplugState state);
 void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
                          const char *name, int devfn_min);
 PCIBus *pci_bus_new(DeviceState *parent, const char *name, int devfn_min);
diff --git a/hw/pcie.c b/hw/pcie.c
index 35918f7..f461c1c 100644
--- a/hw/pcie.c
+++ b/hw/pcie.c
@@ -192,14 +192,16 @@ static void pcie_cap_slot_event(PCIDevice *dev, PCIExpressHotPlugEvent event)
 }
 
 static int pcie_cap_slot_hotplug(DeviceState *qdev,
-                                 PCIDevice *pci_dev, int state)
+                                 PCIDevice *pci_dev, PCIHotplugState state)
 {
     PCIDevice *d = DO_UPCAST(PCIDevice, qdev, qdev);
     uint8_t *exp_cap = d->config + d->exp.exp_cap;
     uint16_t sltsta = pci_get_word(exp_cap + PCI_EXP_SLTSTA);
 
-    if (!pci_dev->qdev.hotplugged) {
-        assert(state); /* this case only happens at machine creation. */
+    /* Don't send event when device is enabled during qemu machine creation:
+     * it is present on boot, no hotplug event is necessary. We do send an
+     * event when the device is disabled later. */
+    if (state == PCI_COLDPLUG_ENABLED) {
         pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA,
                                    PCI_EXP_SLTSTA_PDS);
         return 0;
@@ -219,7 +221,7 @@ static int pcie_cap_slot_hotplug(DeviceState *qdev,
      */
     assert(PCI_FUNC(pci_dev->devfn) == 0);
 
-    if (state) {
+    if (state == PCI_HOTPLUG_ENABLED) {
         pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA,
                                    PCI_EXP_SLTSTA_PDS);
         pcie_cap_slot_event(d, PCI_EXP_HP_EV_PDC);
commit 7f5feab4dda39b39dce24113313587587aa2d0ab
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Mon Oct 4 15:53:11 2010 -0600

    PCI: Bus number from the bridge, not the device
    
    pcibus_dev_print() was erroneously retrieving the device bus
    number from the secondary bus number offset of the device
    instead of the bridge above the device.  This ends of landing
    in the 2nd byte of the 3rd BAR for devices, which thankfully
    is usually zero.
    
    Note: pcibus_get_dev_path() copied this code,
    inheriting the same bug.  pcibus_get_dev_path() is used for
    ramblock naming, so changing it can effect migration.  However,
    I've only seen this byte be non-zero for an assigned device,
    which can't migrate anyway, so hopefully we won't run into
    any issues.
    
    This patch does not touch pcibus_get_dev_path, as
    bus number is guest assigned for nested buses,
    so using it for migration is broken anyway.
    Fix it properly later.
    
    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 962886e..8f6fcf8 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -1806,8 +1806,7 @@ static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent)
 
     monitor_printf(mon, "%*sclass %s, addr %02x:%02x.%x, "
                    "pci id %04x:%04x (sub %04x:%04x)\n",
-                   indent, "", ctxt,
-                   d->config[PCI_SECONDARY_BUS],
+                   indent, "", ctxt, pci_bus_num(d->bus),
                    PCI_SLOT(d->devfn), PCI_FUNC(d->devfn),
                    pci_get_word(d->config + PCI_VENDOR_ID),
                    pci_get_word(d->config + PCI_DEVICE_ID),
commit e685b4eb649cbddd26f203b611eabeb714648f4d
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Fri Nov 5 14:52:08 2010 -0600

    e1000: Fix TCP checksum overflow with TSO
    
    When adding the length to the pseudo header, we're not properly
    accounting for overflow.
    
    From: Mark Wu <dwu at redhat.com>
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/e1000.c b/hw/e1000.c
index 532efdc..677165f 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -384,9 +384,12 @@ xmit_seg(E1000State *s)
         } else	// UDP
             cpu_to_be16wu((uint16_t *)(tp->data+css+4), len);
         if (tp->sum_needed & E1000_TXD_POPTS_TXSM) {
+            unsigned int phsum;
             // add pseudo-header length before checksum calculation
             sp = (uint16_t *)(tp->data + tp->tucso);
-            cpu_to_be16wu(sp, be16_to_cpup(sp) + len);
+            phsum = be16_to_cpup(sp) + len;
+            phsum = (phsum >> 16) + (phsum & 0xffff);
+            cpu_to_be16wu(sp, phsum);
         }
         tp->tso_frames++;
     }
commit a5fd2c345f7a616e48e7f2be8b3060d23252180c
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Sun Oct 31 19:06:47 2010 +0200

    tap: make set_offload a nop after netdev cleanup
    
    virtio-net expects set_offload to succeed after
    peer cleanup.
    Since we don't have an open fd anymore, make it so.
    Fixes warning about the failure of offload setting.
    
    Reported-by: Jason Wang <jasowang at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/net/tap.c b/net/tap.c
index 937d942..eada34a 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -269,8 +269,11 @@ void tap_set_offload(VLANClientState *nc, int csum, int tso4,
                      int tso6, int ecn, int ufo)
 {
     TAPState *s = DO_UPCAST(TAPState, nc, nc);
+    if (s->fd < 0) {
+        return;
+    }
 
-    return tap_fd_set_offload(s->fd, csum, tso4, tso6, ecn, ufo);
+    tap_fd_set_offload(s->fd, csum, tso4, tso6, ecn, ufo);
 }
 
 static void tap_cleanup(VLANClientState *nc)
@@ -290,6 +293,7 @@ static void tap_cleanup(VLANClientState *nc)
     tap_read_poll(s, 0);
     tap_write_poll(s, 0);
     close(s->fd);
+    s->fd = -1;
 }
 
 static void tap_poll(VLANClientState *nc, bool enable)
commit 54cdaa1bad3885448ef39faad93d40be3b223519
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Wed Oct 27 20:03:43 2010 +0200

    tap: clear vhost_net backend on cleanup
    
    Frontends calling tap_get_vhost_net get an invalid pointer after the
    peer backend has been deleted. Jason Wang <jasowang at redhat.com> reports
    this leading to a crash in ack_features when we remove the vhost-net
    bakend of a virtio nic.
    
    The fix is simply to clear the backend pointer.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/net/tap.c b/net/tap.c
index 4afb314..937d942 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -279,6 +279,7 @@ static void tap_cleanup(VLANClientState *nc)
 
     if (s->vhost_net) {
         vhost_net_cleanup(s->vhost_net);
+        s->vhost_net = NULL;
     }
 
     qemu_purge_queued_packets(nc);


More information about the Spice-commits mailing list