[Spice-commits] 112 commits - Makefile.objs Makefile.target arm-semi.c block/raw-posix.c blockdev.c configure cpu-common.h cpu-exec.c cpus.c docs/ich9-ehci-uhci.cfg docs/usb2.txt exec-all.h exec.c hw/arm-misc.h hw/arm_boot.c hw/esp.c hw/framebuffer.c hw/hpet.c hw/ide hw/intel-hda.c hw/milkymist-softusb.c hw/msi.c hw/msix.c hw/nseries.c hw/pci_ids.h hw/piix_pci.c hw/pl080.c hw/ppc405_uc.c hw/pxa2xx_lcd.c hw/qxl-logger.c hw/qxl.c hw/s390-virtio-bus.c hw/s390-virtio-bus.h hw/s390-virtio.c hw/spapr.h hw/spapr_hcall.c hw/usb-bt.c hw/usb-bus.c hw/usb-ehci.c hw/usb-hub.c hw/usb-musb.c hw/usb-ohci.c hw/usb-uhci.c hw/usb.c hw/usb.h hw/vhost.c hw/virtio-blk.c hw/virtio-blk.h hw/virtio-console.c hw/virtio-pci.c hw/virtio-pci.h hw/virtio-serial-bus.c hw/virtio.c hw/virtio.h hw/xen.h hw/xen_common.h hw/xen_console.c hw/xen_disk.c hw/xen_platform.c hw/xenfb.c input.c linux-user/alpha linux-user/arm linux-user/cris linux-user/elfload.c linux-user/i386 linux-user/ioctls.h linux-user/m68k linux-user /main.c linux-user/microblaze linux-user/mips linux-user/mips64 linux-user/mipsn32 linux-user/ppc linux-user/s390x linux-user/sh4 linux-user/signal.c linux-user/sparc linux-user/sparc64 linux-user/syscall.c linux-user/syscall_defs.h linux-user/syscall_types.h linux-user/x86_64 os-posix.c qemu-common.h qemu-img-cmds.hx qemu-img.c qemu-img.texi qemu-options.hx scripts/checkpatch.pl target-alpha/cpu.h target-arm/cpu.h target-ppc/cpu.h target-sparc/cpu.h target-sparc/op_helper.c target-sparc/translate.c tcg/README trace-events ui/spice-core.c ui/spice-display.c vl.c xen-all.c xen-mapcache-stub.c xen-mapcache.c xen-mapcache.h xen-stub.c

Gerd Hoffmann kraxel at kemper.freedesktop.org
Wed Jul 20 03:23:00 PDT 2011


 Makefile.objs                      |    4 
 Makefile.target                    |   14 -
 arm-semi.c                         |  113 +++++++++------
 block/raw-posix.c                  |   14 +
 blockdev.c                         |   14 -
 configure                          |    2 
 cpu-common.h                       |   14 +
 cpu-exec.c                         |    4 
 cpus.c                             |   12 +
 docs/ich9-ehci-uhci.cfg            |   37 +++++
 docs/usb2.txt                      |   33 +++-
 exec-all.h                         |    6 
 exec.c                             |  260 ++++++++++++++++++++++++++++++-----
 hw/arm-misc.h                      |    2 
 hw/arm_boot.c                      |    6 
 hw/esp.c                           |    2 
 hw/framebuffer.c                   |    3 
 hw/hpet.c                          |    2 
 hw/ide/core.c                      |   50 +++++-
 hw/intel-hda.c                     |   21 --
 hw/milkymist-softusb.c             |    9 -
 hw/msi.c                           |    2 
 hw/msix.c                          |    2 
 hw/nseries.c                       |    4 
 hw/pci_ids.h                       |   13 +
 hw/piix_pci.c                      |    3 
 hw/pl080.c                         |    8 -
 hw/ppc405_uc.c                     |   43 +++--
 hw/pxa2xx_lcd.c                    |  109 +++++++++++++-
 hw/qxl-logger.c                    |    4 
 hw/qxl.c                           |   50 ++++--
 hw/s390-virtio-bus.c               |   14 +
 hw/s390-virtio-bus.h               |    1 
 hw/s390-virtio.c                   |    6 
 hw/spapr.h                         |    4 
 hw/spapr_hcall.c                   |   12 -
 hw/usb-bt.c                        |   24 +--
 hw/usb-bus.c                       |   46 +++++-
 hw/usb-ehci.c                      |  270 ++++++++++++++++++++++++++-----------
 hw/usb-hub.c                       |   90 ++----------
 hw/usb-musb.c                      |   24 ++-
 hw/usb-ohci.c                      |   89 ++++++++----
 hw/usb-uhci.c                      |   95 ++++++++++---
 hw/usb.c                           |   13 -
 hw/usb.h                           |   20 ++
 hw/vhost.c                         |    1 
 hw/virtio-blk.c                    |   29 ++-
 hw/virtio-blk.h                    |    2 
 hw/virtio-console.c                |   25 +++
 hw/virtio-pci.c                    |    4 
 hw/virtio-pci.h                    |    1 
 hw/virtio-serial-bus.c             |    9 +
 hw/virtio.c                        |    8 +
 hw/virtio.h                        |    3 
 hw/xen.h                           |   10 -
 hw/xen_common.h                    |   12 +
 hw/xen_console.c                   |   25 ++-
 hw/xen_disk.c                      |   37 ++++-
 hw/xen_platform.c                  |   15 --
 hw/xenfb.c                         |   19 +-
 input.c                            |   34 +++-
 linux-user/alpha/syscall_nr.h      |   23 +++
 linux-user/arm/syscall_nr.h        |   13 +
 linux-user/cris/syscall_nr.h       |    2 
 linux-user/elfload.c               |    6 
 linux-user/i386/syscall_nr.h       |   12 +
 linux-user/ioctls.h                |   13 +
 linux-user/m68k/syscall_nr.h       |   16 ++
 linux-user/main.c                  |   33 ++++
 linux-user/microblaze/syscall_nr.h |   14 +
 linux-user/mips/syscall_nr.h       |   13 +
 linux-user/mips64/syscall_nr.h     |   13 +
 linux-user/mipsn32/syscall_nr.h    |   14 +
 linux-user/ppc/syscall_nr.h        |   30 ++++
 linux-user/s390x/syscall_nr.h      |   13 +
 linux-user/sh4/syscall_nr.h        |   34 ++++
 linux-user/signal.c                |   30 ++--
 linux-user/sparc/syscall_nr.h      |   12 +
 linux-user/sparc64/syscall_nr.h    |   12 +
 linux-user/syscall.c               |  153 +++++++++++++++++---
 linux-user/syscall_defs.h          |   51 ++++++
 linux-user/syscall_types.h         |   20 ++
 linux-user/x86_64/syscall_nr.h     |   12 +
 os-posix.c                         |    6 
 qemu-common.h                      |    1 
 qemu-img-cmds.hx                   |    6 
 qemu-img.c                         |   80 +++++++++-
 qemu-img.texi                      |    6 
 qemu-options.hx                    |    9 +
 scripts/checkpatch.pl              |    4 
 target-alpha/cpu.h                 |    2 
 target-arm/cpu.h                   |    2 
 target-ppc/cpu.h                   |    2 
 target-sparc/cpu.h                 |   49 ++++--
 target-sparc/op_helper.c           |   75 ++++++----
 target-sparc/translate.c           |   29 ++-
 tcg/README                         |   10 +
 trace-events                       |   17 +-
 ui/spice-core.c                    |    5 
 ui/spice-display.c                 |    5 
 vl.c                               |   11 +
 xen-all.c                          |   73 +++++++++-
 xen-mapcache-stub.c                |   36 ----
 xen-mapcache.c                     |   41 +++--
 xen-mapcache.h                     |   14 -
 xen-stub.c                         |    4 
 106 files changed, 2108 insertions(+), 720 deletions(-)

New commits:
commit 03ff09580ef6cbc4a893b6e3e6bbff33180ec70a
Merge: b4dabf9... 25a1181...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Jul 19 08:04:35 2011 -0500

    Merge remote-tracking branch 'agraf/xen-next' into staging

commit b4dabf9587d8e1d5d5edc6d3326021e390b9a532
Merge: de20fbc... 3dc345d...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Jul 19 08:03:20 2011 -0500

    Merge remote-tracking branch 'kraxel/usb.19' into staging

diff --cc hw/pci_ids.h
index b49c602,927f2b0..83f3893
--- a/hw/pci_ids.h
+++ b/hw/pci_ids.h
@@@ -109,6 -109,13 +109,14 @@@
  #define PCI_DEVICE_ID_INTEL_82371AB      0x7111
  #define PCI_DEVICE_ID_INTEL_82371AB_2    0x7112
  #define PCI_DEVICE_ID_INTEL_82371AB_3    0x7113
+ #define PCI_DEVICE_ID_INTEL_82801I_UHCI1 0x2934
+ #define PCI_DEVICE_ID_INTEL_82801I_UHCI2 0x2935
+ #define PCI_DEVICE_ID_INTEL_82801I_UHCI3 0x2936
+ #define PCI_DEVICE_ID_INTEL_82801I_UHCI4 0x2937
+ #define PCI_DEVICE_ID_INTEL_82801I_UHCI5 0x2938
+ #define PCI_DEVICE_ID_INTEL_82801I_UHCI6 0x2939
+ #define PCI_DEVICE_ID_INTEL_82801I_EHCI1 0x293a
+ #define PCI_DEVICE_ID_INTEL_82801I_EHCI2 0x293c
  
 -#define PCI_VENDOR_ID_XENSOURCE          0x5853
 +#define PCI_VENDOR_ID_XEN               0x5853
 +#define PCI_DEVICE_ID_XEN_PLATFORM      0x0001
commit de20fbcac9d71fc91635919bfbe0883a7df71887
Merge: 6734529... a3d1405...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Jul 19 08:02:35 2011 -0500

    Merge remote-tracking branch 'spice/spice.v38' into staging

commit 6734529435bafb0c59c951b3e16f4600c685ee39
Merge: 81773a5... c8eac1c...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Jul 19 07:43:54 2011 -0500

    Merge remote-tracking branch 'mst/for_anthony' into staging

commit 81773a505554dfbe3f3f48653ab1a02455e9e5ff
Merge: 0219d73... 6fea2ea...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Jul 19 07:43:51 2011 -0500

    Merge remote-tracking branch 'riku/linux-user-for-upstream' into staging

commit 0219d73283b6399a737ef5a098f849b956618eaa
Author: Amit Shah <amit.shah at redhat.com>
Date:   Thu Jul 7 17:35:27 2011 +0530

    virtio-console: Prevent abort()s in case of host chardev close
    
    A host chardev could close just before the guest sends some data to be
    written.  This will cause an -EPIPE error.  This shouldn't be propagated
    to virtio-serial-bus.
    
    Ideally we should close the port once -EPIPE is received, but since the
    chardev interface doesn't return such meaningful values to its users,
    all we get is -1 for any kind of error.  Just return 0 for now and wait
    for chardevs to return better error messages to act better on the return
    messages.
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>

diff --git a/hw/virtio-console.c b/hw/virtio-console.c
index 713a761..7ebfa26 100644
--- a/hw/virtio-console.c
+++ b/hw/virtio-console.c
@@ -28,8 +28,22 @@ static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
     ssize_t ret;
 
     ret = qemu_chr_write(vcon->chr, buf, len);
-
     trace_virtio_console_flush_buf(port->id, len, ret);
+
+    if (ret < 0) {
+        /*
+         * Ideally we'd get a better error code than just -1, but
+         * that's what the chardev interface gives us right now.  If
+         * we had a finer-grained message, like -EPIPE, we could close
+         * this connection.  Absent such error messages, the most we
+         * can do is to return 0 here.
+         *
+         * This will prevent stray -1 values to go to
+         * virtio-serial-bus.c and cause abort()s in
+         * do_flush_queued_data().
+         */
+        ret = 0;
+    }
     return ret;
 }
 
commit 95c9cde2dff9de9f4afa0450697bd70f56715be1
Author: Amit Shah <amit.shah at redhat.com>
Date:   Thu Jul 7 18:16:13 2011 +0530

    virtio-serial-bus: Fix trailing \n in error_report string
    
    Markus fixed offenders in the file but one instance sneaked in via
    another patch.  Fix it.
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>

diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index 9859f9f..6d73386 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -351,7 +351,7 @@ static void handle_control_message(VirtIOSerial *vser, void *buf, size_t len)
 
     port = find_port_by_id(vser, ldl_p(&gcpkt->id));
     if (!port) {
-        error_report("virtio-serial-bus: Unexpected port id %u for device %s\n",
+        error_report("virtio-serial-bus: Unexpected port id %u for device %s",
                      ldl_p(&gcpkt->id), vser->bus.qbus.name);
         return;
     }
commit d02e4fa4a8e180c0a312b7c520a167894a0c8a83
Author: Amit Shah <amit.shah at redhat.com>
Date:   Tue Jul 5 16:37:49 2011 +0530

    virtio-console: Add some trace events
    
    Add some trace events for messages passed between the char layer and the
    virtio-serial bus.
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>

diff --git a/hw/virtio-console.c b/hw/virtio-console.c
index b076331..713a761 100644
--- a/hw/virtio-console.c
+++ b/hw/virtio-console.c
@@ -12,6 +12,7 @@
 
 #include "qemu-char.h"
 #include "qemu-error.h"
+#include "trace.h"
 #include "virtio-serial.h"
 
 typedef struct VirtConsole {
@@ -24,8 +25,12 @@ typedef struct VirtConsole {
 static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
 {
     VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
+    ssize_t ret;
 
-    return qemu_chr_write(vcon->chr, buf, len);
+    ret = qemu_chr_write(vcon->chr, buf, len);
+
+    trace_virtio_console_flush_buf(port->id, len, ret);
+    return ret;
 }
 
 /* Callback function that's called when the guest opens the port */
@@ -57,6 +62,7 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
 {
     VirtConsole *vcon = opaque;
 
+    trace_virtio_console_chr_read(vcon->port.id, size);
     virtio_serial_write(&vcon->port, buf, size);
 }
 
@@ -64,6 +70,7 @@ static void chr_event(void *opaque, int event)
 {
     VirtConsole *vcon = opaque;
 
+    trace_virtio_console_chr_event(vcon->port.id, event);
     switch (event) {
     case CHR_EVENT_OPENED:
         virtio_serial_open(&vcon->port);
diff --git a/trace-events b/trace-events
index 59420e8..765a15e 100644
--- a/trace-events
+++ b/trace-events
@@ -52,6 +52,11 @@ disable virtio_serial_throttle_port(unsigned int port, bool throttle) "port %u,
 disable virtio_serial_handle_control_message(uint16_t event, uint16_t value) "event %u, value %u"
 disable virtio_serial_handle_control_message_port(unsigned int port) "port %u"
 
+# hw/virtio-console.c
+disable virtio_console_flush_buf(unsigned int port, size_t len, ssize_t ret) "port %u, in_len %zu, out_len %zd"
+disable virtio_console_chr_read(unsigned int port, int size) "port %u, size %d"
+disable virtio_console_chr_event(unsigned int port, int event) "port %u, event %d"
+
 # block.c
 disable multiwrite_cb(void *mcb, int ret) "mcb %p ret %d"
 disable bdrv_aio_multiwrite(void *mcb, int num_callbacks, int num_reqs) "mcb %p num_callbacks %d num_reqs %d"
commit 49e3fdd7f2f3ecccc6f75d976246124d0edaec3f
Author: Amit Shah <amit.shah at redhat.com>
Date:   Tue Jul 5 16:36:39 2011 +0530

    virtio-serial-bus: Add trace events
    
    Add some trace events for messages passed between the guest and host.
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>

diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index 7f6db7b..9859f9f 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -19,6 +19,7 @@
 #include "monitor.h"
 #include "qemu-queue.h"
 #include "sysbus.h"
+#include "trace.h"
 #include "virtio-serial.h"
 
 /* The virtio-serial bus on top of which the ports will ride as devices */
@@ -221,6 +222,7 @@ static size_t send_control_event(VirtIOSerialPort *port, uint16_t event,
     stw_p(&cpkt.event, event);
     stw_p(&cpkt.value, value);
 
+    trace_virtio_serial_send_control_event(port->id, event, value);
     return send_control_msg(port, &cpkt, sizeof(cpkt));
 }
 
@@ -302,6 +304,7 @@ void virtio_serial_throttle_port(VirtIOSerialPort *port, bool throttle)
         return;
     }
 
+    trace_virtio_serial_throttle_port(port->id, throttle);
     port->throttled = throttle;
     if (throttle) {
         return;
@@ -328,6 +331,8 @@ static void handle_control_message(VirtIOSerial *vser, void *buf, size_t len)
     cpkt.event = lduw_p(&gcpkt->event);
     cpkt.value = lduw_p(&gcpkt->value);
 
+    trace_virtio_serial_handle_control_message(cpkt.event, cpkt.value);
+
     if (cpkt.event == VIRTIO_CONSOLE_DEVICE_READY) {
         if (!cpkt.value) {
             error_report("virtio-serial-bus: Guest failure in adding device %s",
@@ -351,6 +356,8 @@ static void handle_control_message(VirtIOSerial *vser, void *buf, size_t len)
         return;
     }
 
+    trace_virtio_serial_handle_control_message_port(port->id);
+
     info = DO_UPCAST(VirtIOSerialPortInfo, qdev, port->dev.info);
 
     switch(cpkt.event) {
diff --git a/trace-events b/trace-events
index bebf612..59420e8 100644
--- a/trace-events
+++ b/trace-events
@@ -46,6 +46,12 @@ disable virtio_queue_notify(void *vdev, int n, void *vq) "vdev %p n %d vq %p"
 disable virtio_irq(void *vq) "vq %p"
 disable virtio_notify(void *vdev, void *vq) "vdev %p vq %p"
 
+# hw/virtio-serial-bus.c
+disable virtio_serial_send_control_event(unsigned int port, uint16_t event, uint16_t value) "port %u, event %u, value %u"
+disable virtio_serial_throttle_port(unsigned int port, bool throttle) "port %u, throttle %d"
+disable virtio_serial_handle_control_message(uint16_t event, uint16_t value) "event %u, value %u"
+disable virtio_serial_handle_control_message_port(unsigned int port) "port %u"
+
 # block.c
 disable multiwrite_cb(void *mcb, int ret) "mcb %p ret %d"
 disable bdrv_aio_multiwrite(void *mcb, int num_callbacks, int num_reqs) "mcb %p num_callbacks %d num_reqs %d"
commit c8eac1cfa1e9104a658b4614ada758861b8d823a
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Mon Jun 20 13:42:27 2011 +0300

    virtio: fix indirect descriptor buffer overflow
    
    We were previously allowing arbitrarily-long indirect descriptors, which
    could lead to a buffer overflow in qemu-kvm process.
    
    CVE-2011-2212
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/virtio.c b/hw/virtio.c
index cc47a06..a8f4940 100644
--- a/hw/virtio.c
+++ b/hw/virtio.c
@@ -449,9 +449,17 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
         struct iovec *sg;
 
         if (vring_desc_flags(desc_pa, i) & VRING_DESC_F_WRITE) {
+            if (elem->in_num >= ARRAY_SIZE(elem->in_sg)) {
+                error_report("Too many write descriptors in indirect table");
+                exit(1);
+            }
             elem->in_addr[elem->in_num] = vring_desc_addr(desc_pa, i);
             sg = &elem->in_sg[elem->in_num++];
         } else {
+            if (elem->out_num >= ARRAY_SIZE(elem->out_sg)) {
+                error_report("Too many read descriptors in indirect table");
+                exit(1);
+            }
             elem->out_addr[elem->out_num] = vring_desc_addr(desc_pa, i);
             sg = &elem->out_sg[elem->out_num++];
         }
commit 0d2b962d16feaf1eb1a4658a4c1b85642418cd07
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Sun Jun 26 16:30:45 2011 +0300

    xen: move to new pci initializers
    
    move ids to pci info structure
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/xen_platform.c b/hw/xen_platform.c
index 9a01735..f43e175 100644
--- a/hw/xen_platform.c
+++ b/hw/xen_platform.c
@@ -290,18 +290,10 @@ static int xen_platform_initfn(PCIDevice *dev)
 
     pci_conf = d->pci_dev.config;
 
-    pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_XEN);
-    pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_XEN_PLATFORM);
-    pci_set_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID, PCI_VENDOR_ID_XEN);
-    pci_set_word(pci_conf + PCI_SUBSYSTEM_ID, PCI_DEVICE_ID_XEN_PLATFORM);
-
     pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
 
-    pci_config_set_revision(pci_conf, 1);
     pci_config_set_prog_interface(pci_conf, 0);
 
-    pci_config_set_class(pci_conf, PCI_CLASS_OTHERS << 8 | 0x80);
-
     pci_conf[PCI_INTERRUPT_PIN] = 1;
 
     pci_register_bar(&d->pci_dev, 0, 0x100,
@@ -330,6 +322,13 @@ static PCIDeviceInfo xen_platform_info = {
     .qdev.size = sizeof(PCIXenPlatformState),
     .qdev.vmsd = &vmstate_xen_platform,
     .qdev.reset = platform_reset,
+
+    .vendor_id    =  PCI_VENDOR_ID_XEN,
+    .device_id    = PCI_DEVICE_ID_XEN_PLATFORM,
+    .class_id     = PCI_CLASS_OTHERS << 8 | 0x80,
+    .subsystem_vendor_id = PCI_VENDOR_ID_XEN,
+    .subsystem_id = PCI_DEVICE_ID_XEN_PLATFORM,
+    .revision = 1,
 };
 
 static void xen_platform_register(void)
commit ce4fd422a6c5119baf4a2c3115c7ea63efb0f68e
Author: Anthony PERARD <anthony.perard at citrix.com>
Date:   Wed Jun 22 16:58:31 2011 +0100

    hw/piix_pci.c: Fix PIIX3-xen to initialize ids
    
    Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index 26ce904..d08b31a 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -478,6 +478,9 @@ static PCIDeviceInfo i440fx_info[] = {
         .no_hotplug   = 1,
         .init         = piix3_initfn,
         .config_write = piix3_write_config_xen,
+        .vendor_id    = PCI_VENDOR_ID_INTEL,
+        .device_id    = PCI_DEVICE_ID_INTEL_82371SB_0, // 82371SB PIIX3 PCI-to-ISA bridge (Step A1)
+        .class_id     = PCI_CLASS_BRIDGE_ISA,
     },{
         /* end of list */
     }
commit 33d5ad53c1039989c4ecf583ed52a584d3888495
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Sun Jun 26 16:17:27 2011 +0300

    pci_ids: tweak names to match linux/pci_ids.h
    
    Sync xen names to ones used by linux. Add
    xen platform device id as well.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci_ids.h b/hw/pci_ids.h
index d94578c..b49c602 100644
--- a/hw/pci_ids.h
+++ b/hw/pci_ids.h
@@ -110,4 +110,5 @@
 #define PCI_DEVICE_ID_INTEL_82371AB_2    0x7112
 #define PCI_DEVICE_ID_INTEL_82371AB_3    0x7113
 
-#define PCI_VENDOR_ID_XENSOURCE          0x5853
+#define PCI_VENDOR_ID_XEN               0x5853
+#define PCI_DEVICE_ID_XEN_PLATFORM      0x0001
diff --git a/hw/xen_platform.c b/hw/xen_platform.c
index b167eee..9a01735 100644
--- a/hw/xen_platform.c
+++ b/hw/xen_platform.c
@@ -290,10 +290,10 @@ static int xen_platform_initfn(PCIDevice *dev)
 
     pci_conf = d->pci_dev.config;
 
-    pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_XENSOURCE);
-    pci_config_set_device_id(pci_conf, 0x0001);
-    pci_set_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID, PCI_VENDOR_ID_XENSOURCE);
-    pci_set_word(pci_conf + PCI_SUBSYSTEM_ID, 0x0001);
+    pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_XEN);
+    pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_XEN_PLATFORM);
+    pci_set_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID, PCI_VENDOR_ID_XEN);
+    pci_set_word(pci_conf + PCI_SUBSYSTEM_ID, PCI_DEVICE_ID_XEN_PLATFORM);
 
     pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
 
commit c1be973ae1135588ed77b365bfd3bf063bac78ae
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Tue Jun 21 20:34:17 2011 +0300

    vhost: fix double free on device stop
    
    vhost dev stop failed to clear the log field.
    Typically not an issue as dev start overwrites this field,
    but if logging gets disabled before the following start,
    it doesn't so this causes a double free.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/vhost.c b/hw/vhost.c
index 80f771e..c3d8821 100644
--- a/hw/vhost.c
+++ b/hw/vhost.c
@@ -784,5 +784,6 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev)
 
     hdev->started = false;
     qemu_free(hdev->log);
+    hdev->log = NULL;
     hdev->log_size = 0;
 }
commit 25a118130fde0d20b0f5a223642849b392b2f2ee
Author: Alexander Graf <agraf at suse.de>
Date:   Sun Jul 3 09:44:48 2011 +0200

    xen_console: fall back to qemu serial device
    
    The new xen_console protocol changed the default xen_console output device
    from whatever Qemu chose to whatever xenstore choses and "pty" as fallback.
    
    This is not how Qemu works. It has its own serial redirection semantics. So
    it xenstore doesn't contain information on what to do, Qemu is the place to
    ask.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/xen_console.c b/hw/xen_console.c
index bdb8540..8ef104c 100644
--- a/hw/xen_console.c
+++ b/hw/xen_console.c
@@ -196,12 +196,15 @@ static int con_init(struct XenDevice *xendev)
     }
 
     output = xenstore_read_str(con->console, "output");
-    /* output is a pty by default */
+
+    /* no Xen override, use qemu output device */
     if (output == NULL) {
-        output = "pty";
+        con->chr = serial_hds[con->xendev.dev];
+    } else {
+        snprintf(label, sizeof(label), "xencons%d", con->xendev.dev);
+        con->chr = qemu_chr_open(label, output, NULL);
     }
-    snprintf(label, sizeof(label), "xencons%d", con->xendev.dev);
-    con->chr = qemu_chr_open(label, output, NULL);
+
     xenstore_store_pv_console_info(con->xendev.dev, con->chr);
 
 out:
commit 0f51726adcdb620214405a88b2601d9edd059db4
Author: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
Date:   Thu Jun 30 18:26:29 2011 +0100

    xen_console: support the new extended xenstore protocol
    
    Since CS 21994 on xen-unstable.hg and CS
    466608f3a32e1f9808acdf832a5843af37e5fcec on qemu-xen-unstable.git, few
    changes have been introduced to the PV console xenstore protocol, as
    described by the document docs/misc/console.txt under xen-unstable.hg.
    
    From the Qemu point of view, very few modifications are needed to
    correctly support the protocol: read from xenstore the "output" node
    that tell us what the output of the PV console is going to be.
    In case the output is a tty, write to xenstore the device name.
    
    Changes in v2:
    
    - fix error paths: free malloc'ed strings and close the xenstore
    connection before returning;
    
    - remove useless snprintf in xenstore_store_pv_console_info if i == 0.
    
    Changes in v3:
    
    - replace xs_daemon_open/xs_daemon_close with xs_open/xs_close.
    
    Changes in v4:
    
    - add a compatibility implementation of xs_open/xs_close.
    
    Changes in v5:
    
    - fix code style.
    
    [agraf] fix build error due to missing stub
    
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/xen.h b/hw/xen.h
index 95029bb..e432705 100644
--- a/hw/xen.h
+++ b/hw/xen.h
@@ -41,6 +41,7 @@ qemu_irq *xen_interrupt_controller_init(void);
 int xen_init(void);
 int xen_hvm_init(void);
 void xen_vcpu_init(void);
+void xenstore_store_pv_console_info(int i, struct CharDriverState *chr);
 
 #if defined(NEED_CPU_H) && !defined(CONFIG_USER_ONLY)
 void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size);
diff --git a/hw/xen_common.h b/hw/xen_common.h
index 2c79af6..0409ac7 100644
--- a/hw/xen_common.h
+++ b/hw/xen_common.h
@@ -85,6 +85,18 @@ static inline int xc_domain_add_to_physmap(int xc_handle, uint32_t domid,
     return xc_memory_op(xc_handle, XENMEM_add_to_physmap, &xatp);
 }
 
+static inline struct xs_handle *xs_open(unsigned long flags)
+{
+    return xs_daemon_open();
+}
+
+static inline void xs_close(struct xs_handle *xsh)
+{
+    if (xsh != NULL) {
+        xs_daemon_close(xsh);
+    }
+}
+
 
 /* Xen 4.1 */
 #else
diff --git a/hw/xen_console.c b/hw/xen_console.c
index 2d613ee..bdb8540 100644
--- a/hw/xen_console.c
+++ b/hw/xen_console.c
@@ -179,8 +179,9 @@ static void xencons_send(struct XenConsole *con)
 static int con_init(struct XenDevice *xendev)
 {
     struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
-    char *type, *dom;
+    char *type, *dom, label[32];
     int ret = 0;
+    const char *output;
 
     /* setup */
     dom = xs_get_domain_path(xenstore, con->xendev.dom);
@@ -194,11 +195,14 @@ static int con_init(struct XenDevice *xendev)
         goto out;
     }
 
-    if (!serial_hds[con->xendev.dev])
-	xen_be_printf(xendev, 1, "WARNING: serial line %d not configured\n",
-                      con->xendev.dev);
-    else
-        con->chr = serial_hds[con->xendev.dev];
+    output = xenstore_read_str(con->console, "output");
+    /* output is a pty by default */
+    if (output == NULL) {
+        output = "pty";
+    }
+    snprintf(label, sizeof(label), "xencons%d", con->xendev.dev);
+    con->chr = qemu_chr_open(label, output, NULL);
+    xenstore_store_pv_console_info(con->xendev.dev, con->chr);
 
 out:
     qemu_free(type);
diff --git a/xen-all.c b/xen-all.c
index fb9bcc8..8105c83 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -737,6 +737,66 @@ static void cpu_handle_ioreq(void *opaque)
     }
 }
 
+static int store_dev_info(int domid, CharDriverState *cs, const char *string)
+{
+    struct xs_handle *xs = NULL;
+    char *path = NULL;
+    char *newpath = NULL;
+    char *pts = NULL;
+    int ret = -1;
+
+    /* Only continue if we're talking to a pty. */
+    if (strncmp(cs->filename, "pty:", 4)) {
+        return 0;
+    }
+    pts = cs->filename + 4;
+
+    /* We now have everything we need to set the xenstore entry. */
+    xs = xs_open(0);
+    if (xs == NULL) {
+        fprintf(stderr, "Could not contact XenStore\n");
+        goto out;
+    }
+
+    path = xs_get_domain_path(xs, domid);
+    if (path == NULL) {
+        fprintf(stderr, "xs_get_domain_path() error\n");
+        goto out;
+    }
+    newpath = realloc(path, (strlen(path) + strlen(string) +
+                strlen("/tty") + 1));
+    if (newpath == NULL) {
+        fprintf(stderr, "realloc error\n");
+        goto out;
+    }
+    path = newpath;
+
+    strcat(path, string);
+    strcat(path, "/tty");
+    if (!xs_write(xs, XBT_NULL, path, pts, strlen(pts))) {
+        fprintf(stderr, "xs_write for '%s' fail", string);
+        goto out;
+    }
+    ret = 0;
+
+out:
+    free(path);
+    xs_close(xs);
+
+    return ret;
+}
+
+void xenstore_store_pv_console_info(int i, CharDriverState *chr)
+{
+    if (i == 0) {
+        store_dev_info(xen_domid, chr, "/console");
+    } else {
+        char buf[32];
+        snprintf(buf, sizeof(buf), "/device/console/%d", i);
+        store_dev_info(xen_domid, chr, buf);
+    }
+}
+
 static void xenstore_record_dm_state(XenIOState *s, const char *state)
 {
     char path[50];
diff --git a/xen-stub.c b/xen-stub.c
index a4f35a1..efe2ab5 100644
--- a/xen-stub.c
+++ b/xen-stub.c
@@ -9,6 +9,10 @@
 #include "qemu-common.h"
 #include "hw/xen.h"
 
+void xenstore_store_pv_console_info(int i, CharDriverState *chr)
+{
+}
+
 int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
 {
     return -1;
commit 9fbe4784449f6248224ac95e0aa9e56a0bfdd155
Author: Alexander Graf <agraf at suse.de>
Date:   Wed Jun 29 08:04:27 2011 +0200

    checkpatch: don't error out on },{ lines
    
    When having code like this:
    
        static PCIDeviceInfo piix_ide_info[] = {
            {
                .qdev.name    = "piix3-ide",
                .qdev.size    = sizeof(PCIIDEState),
                .qdev.no_user = 1,
                .no_hotplug   = 1,
                .init         = pci_piix_ide_initfn,
                .vendor_id    = PCI_VENDOR_ID_INTEL,
                .device_id    = PCI_DEVICE_ID_INTEL_82371SB_1,
                .class_id     = PCI_CLASS_STORAGE_IDE,
            },{
                .qdev.name    = "piix4-ide",
                .qdev.size    = sizeof(PCIIDEState),
                .qdev.no_user = 1,
                .no_hotplug   = 1,
                .init         = pci_piix_ide_initfn,
                .vendor_id    = PCI_VENDOR_ID_INTEL,
                .device_id    = PCI_DEVICE_ID_INTEL_82371AB,
                .class_id     = PCI_CLASS_STORAGE_IDE,
            },{
                /* end of list */
            }
        };
    
    checkpatch currently errors out, claiming that spaces need to follow
    commas. However, this particular style of defining structs is pretty
    common in qemu code and very readable. So let's declare it as supported
    for the above case.
    
    Reported-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 075b614..70a2111 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -2068,8 +2068,10 @@ sub process {
 					}
 
 				# , must have a space on the right.
+                                # not required when having a single },{ on one line
 				} elsif ($op eq ',') {
-					if ($ctx !~ /.x[WEC]/ && $cc !~ /^}/) {
+					if ($ctx !~ /.x[WEC]/ && $cc !~ /^}/ &&
+                                            ($elements[$n] . $elements[$n + 2]) !~ " *}{") {
 						ERROR("space required after that '$op' $at\n" . $hereptr);
 					}
 
commit 7cef3f4fdbe813ac7d495e15a81531f1181b19f9
Author: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
Date:   Thu Jun 30 15:42:31 2011 +0100

    xen_disk: treat "aio" as "raw"
    
    Sometimes the toolstack uses "aio" without an additional format
    identifier, in such cases use "raw".
    
    Updated in v2:
    
    - fix code style.
    
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/xen_disk.c b/hw/xen_disk.c
index f14e5a6..add815f 100644
--- a/hw/xen_disk.c
+++ b/hw/xen_disk.c
@@ -633,6 +633,9 @@ static int blk_init(struct XenDevice *xendev)
             blkdev->filename  = blkdev->params;
         }
     }
+    if (!strcmp("aio", blkdev->fileproto)) {
+        blkdev->fileproto = "raw";
+    }
     if (blkdev->mode == NULL) {
         blkdev->mode = xenstore_read_be_str(&blkdev->xendev, "mode");
     }
commit 8ab934f93b5ad3d0af4ad419d2531235a75d672c
Author: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
Date:   Mon Jun 27 18:26:06 2011 +0100

    qemu_ram_ptr_length: take ram_addr_t as arguments
    
    qemu_ram_ptr_length should take ram_addr_t as argument rather than
    target_phys_addr_t because is doing comparisons with RAMBlock addresses.
    
    cpu_physical_memory_map should create a ram_addr_t address to pass to
    qemu_ram_ptr_length from PhysPageDesc phys_offset.
    
    Remove code after abort() in qemu_ram_ptr_length.
    
    Changes in v2:
    
    - handle 0 size in qemu_ram_ptr_length;
    
    - rename addr1 to raddr;
    
    - initialize raddr to ULONG_MAX.
    
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/cpu-common.h b/cpu-common.h
index c6a2b5f..a5b80e1 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -65,7 +65,7 @@ void qemu_ram_free_from_ptr(ram_addr_t addr);
 void qemu_ram_remap(ram_addr_t addr, ram_addr_t length);
 /* This should only be used for ram local to a device.  */
 void *qemu_get_ram_ptr(ram_addr_t addr);
-void *qemu_ram_ptr_length(target_phys_addr_t addr, target_phys_addr_t *size);
+void *qemu_ram_ptr_length(ram_addr_t addr, ram_addr_t *size);
 /* Same but slower, to use for migration, where the order of
  * RAMBlocks must not change. */
 void *qemu_safe_ram_ptr(ram_addr_t addr);
diff --git a/exec.c b/exec.c
index 067bb34..8277900 100644
--- a/exec.c
+++ b/exec.c
@@ -3167,8 +3167,11 @@ void *qemu_safe_ram_ptr(ram_addr_t addr)
 
 /* Return a host pointer to guest's ram. Similar to qemu_get_ram_ptr
  * but takes a size argument */
-void *qemu_ram_ptr_length(target_phys_addr_t addr, target_phys_addr_t *size)
+void *qemu_ram_ptr_length(ram_addr_t addr, ram_addr_t *size)
 {
+    if (*size == 0) {
+        return NULL;
+    }
     if (xen_enabled()) {
         return xen_map_cache(addr, *size, 1);
     } else {
@@ -3184,9 +3187,6 @@ void *qemu_ram_ptr_length(target_phys_addr_t addr, target_phys_addr_t *size)
 
         fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
         abort();
-
-        *size = 0;
-        return NULL;
     }
 }
 
@@ -4052,7 +4052,9 @@ void *cpu_physical_memory_map(target_phys_addr_t addr,
     target_phys_addr_t page;
     unsigned long pd;
     PhysPageDesc *p;
-    target_phys_addr_t addr1 = addr;
+    ram_addr_t raddr = ULONG_MAX;
+    ram_addr_t rlen;
+    void *ret;
 
     while (len > 0) {
         page = addr & TARGET_PAGE_MASK;
@@ -4080,13 +4082,18 @@ void *cpu_physical_memory_map(target_phys_addr_t addr,
             *plen = l;
             return bounce.buffer;
         }
+        if (!todo) {
+            raddr = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
+        }
 
         len -= l;
         addr += l;
         todo += l;
     }
-    *plen = todo;
-    return qemu_ram_ptr_length(addr1, plen);
+    rlen = todo;
+    ret = qemu_ram_ptr_length(raddr, &rlen);
+    *plen = rlen;
+    return ret;
 }
 
 /* Unmaps a memory region previously mapped by cpu_physical_memory_map().
commit 5ea3c2b405e1a0937e8ccfdb57345628eb904525
Author: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
Date:   Mon Jun 27 16:10:01 2011 +0100

    xen_disk: cope with missing xenstore "params" node
    
    When disk is a cdrom and the drive is empty the "params" node in
    xenstore might be missing completely: cope with it instead of
    segfaulting.
    
    Updated in v2:
    
    - actually removed the strchr(blkdev->params, ':') that caused the
    segfault;
    
    - free all the allocated strings from xenstore before returning;
    
    Updated in v3:
    
    - set blkdev fields to NULL after free'ing them.
    
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/xen_disk.c b/hw/xen_disk.c
index 0c298af..f14e5a6 100644
--- a/hw/xen_disk.c
+++ b/hw/xen_disk.c
@@ -616,12 +616,14 @@ static int blk_init(struct XenDevice *xendev)
 {
     struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev);
     int index, qflags, have_barriers, info = 0;
-    char *h;
 
     /* read xenstore entries */
     if (blkdev->params == NULL) {
+        char *h = NULL;
         blkdev->params = xenstore_read_be_str(&blkdev->xendev, "params");
-        h = strchr(blkdev->params, ':');
+        if (blkdev->params != NULL) {
+            h = strchr(blkdev->params, ':');
+        }
         if (h != NULL) {
             blkdev->fileproto = blkdev->params;
             blkdev->filename  = h+1;
@@ -649,7 +651,7 @@ static int blk_init(struct XenDevice *xendev)
         blkdev->mode == NULL   ||
         blkdev->type == NULL   ||
         blkdev->dev == NULL) {
-        return -1;
+        goto out_error;
     }
 
     /* read-only ? */
@@ -672,10 +674,15 @@ static int blk_init(struct XenDevice *xendev)
         /* setup via xenbus -> create new block driver instance */
         xen_be_printf(&blkdev->xendev, 2, "create new bdrv (xenbus setup)\n");
         blkdev->bs = bdrv_new(blkdev->dev);
-        if (bdrv_open(blkdev->bs, blkdev->filename, qflags,
-                      bdrv_find_whitelisted_format(blkdev->fileproto)) != 0) {
-            bdrv_delete(blkdev->bs);
-            return -1;
+        if (blkdev->bs) {
+            if (bdrv_open(blkdev->bs, blkdev->filename, qflags,
+                        bdrv_find_whitelisted_format(blkdev->fileproto)) != 0) {
+                bdrv_delete(blkdev->bs);
+                blkdev->bs = NULL;
+            }
+        }
+        if (!blkdev->bs) {
+            goto out_error;
         }
     } else {
         /* setup via qemu cmdline -> already setup for us */
@@ -704,6 +711,19 @@ static int blk_init(struct XenDevice *xendev)
     xenstore_write_be_int(&blkdev->xendev, "sectors",
                           blkdev->file_size / blkdev->file_blk);
     return 0;
+
+out_error:
+    qemu_free(blkdev->params);
+    blkdev->params = NULL;
+    qemu_free(blkdev->mode);
+    blkdev->mode = NULL;
+    qemu_free(blkdev->type);
+    blkdev->type = NULL;
+    qemu_free(blkdev->dev);
+    blkdev->dev = NULL;
+    qemu_free(blkdev->devtype);
+    blkdev->devtype = NULL;
+    return -1;
 }
 
 static int blk_connect(struct XenDevice *xendev)
commit 37cdfcf194825d03334542297bee3a3a4723e6e3
Author: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
Date:   Fri Jun 24 17:36:11 2011 +0100

    xen: add vkbd support for PV on HVM guests
    
    Register the vkbd backend even when running as device emulator for HVM
    guests: it is useful because it doesn't need a frequent timer like usb.
    
    Check whether the XenInput DisplayState has been set in the initialise
    state, rather than the input state.
    In case the DisplayState hasn't been set and there is no vfb for this
    domain, then set the XenInput DisplayState to the default one.
    
    Changed in v2:
    
    - use qemu_free instead of free;
    
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/xenfb.c b/hw/xenfb.c
index 1db75fb..0a01ae3 100644
--- a/hw/xenfb.c
+++ b/hw/xenfb.c
@@ -347,13 +347,6 @@ static void xenfb_mouse_event(void *opaque,
 
 static int input_init(struct XenDevice *xendev)
 {
-    struct XenInput *in = container_of(xendev, struct XenInput, c.xendev);
-
-    if (!in->c.ds) {
-        xen_be_printf(xendev, 1, "ds not set (yet)\n");
-	return -1;
-    }
-
     xenstore_write_be_int(xendev, "feature-abs-pointer", 1);
     return 0;
 }
@@ -367,6 +360,18 @@ static int input_connect(struct XenDevice *xendev)
                              &in->abs_pointer_wanted) == -1)
 	in->abs_pointer_wanted = 0;
 
+    if (!in->c.ds) {
+        char *vfb = xenstore_read_str(NULL, "device/vfb");
+        if (vfb == NULL) {
+            /* there is no vfb, run vkbd on its own */
+            in->c.ds = get_displaystate();
+        } else {
+            qemu_free(vfb);
+            xen_be_printf(xendev, 1, "ds not set (yet)\n");
+            return -1;
+        }
+    }
+
     rc = common_bind(&in->c);
     if (rc != 0)
 	return rc;
diff --git a/xen-all.c b/xen-all.c
index 3d40ab0..fb9bcc8 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -868,6 +868,7 @@ int xen_hvm_init(void)
         exit(1);
     }
     xen_be_register("console", &xen_console_ops);
+    xen_be_register("vkbd", &xen_kbdmouse_ops);
     xen_be_register("qdisk", &xen_blkdev_ops);
 
     return 0;
commit 5e6b701aba8689a336297dda047bf760ffc05291
Author: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
Date:   Fri Jun 24 16:59:46 2011 +0100

    xen_console: fix memory leak
    
    con_init leaks the string "type", fix it.
    
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/xen_console.c b/hw/xen_console.c
index c6c8163..2d613ee 100644
--- a/hw/xen_console.c
+++ b/hw/xen_console.c
@@ -180,6 +180,7 @@ static int con_init(struct XenDevice *xendev)
 {
     struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
     char *type, *dom;
+    int ret = 0;
 
     /* setup */
     dom = xs_get_domain_path(xenstore, con->xendev.dom);
@@ -189,7 +190,8 @@ static int con_init(struct XenDevice *xendev)
     type = xenstore_read_str(con->console, "type");
     if (!type || strcmp(type, "ioemu") != 0) {
 	xen_be_printf(xendev, 1, "not for me (type=%s)\n", type);
-	return -1;
+        ret = -1;
+        goto out;
     }
 
     if (!serial_hds[con->xendev.dev])
@@ -198,7 +200,9 @@ static int con_init(struct XenDevice *xendev)
     else
         con->chr = serial_hds[con->xendev.dev];
 
-    return 0;
+out:
+    qemu_free(type);
+    return ret;
 }
 
 static int con_connect(struct XenDevice *xendev)
commit ad35a7da1a0a40cd8920ba829640bd43e1613ec1
Author: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
Date:   Fri Jun 24 15:54:48 2011 +0100

    xen: enable console and disk backend in HVM mode
    
    Initialize the Xen console backend and the Xen disk backend even when
    running in HVM mode so that PV on HVM drivers can connect to them.
    
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/xen-all.c b/xen-all.c
index 4827d6a..3d40ab0 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -862,6 +862,14 @@ int xen_hvm_init(void)
     cpu_register_phys_memory_client(&state->client);
     state->log_for_dirtybit = NULL;
 
+    /* Initialize backend core & drivers */
+    if (xen_be_init() != 0) {
+        fprintf(stderr, "%s: xen backend core setup failed\n", __FUNCTION__);
+        exit(1);
+    }
+    xen_be_register("console", &xen_console_ops);
+    xen_be_register("qdisk", &xen_blkdev_ops);
+
     return 0;
 }
 
commit 868bb33faa643c7ee291bb308a829122b72d4845
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Jun 21 22:59:09 2011 +0200

    xen: Fold CONFIG_XEN_MAPCACHE into CONFIG_XEN
    
    Xen won't be enabled if there is no backend support available for the
    host. And that also means the map cache will work. So drop the separate
    config switch and move the required stubs over to xen-stub.c.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/Makefile.target b/Makefile.target
index c347176..c566eb1 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -4,7 +4,6 @@ GENERATED_HEADERS = config-target.h
 CONFIG_NO_PCI = $(if $(subst n,,$(CONFIG_PCI)),n,y)
 CONFIG_NO_KVM = $(if $(subst n,,$(CONFIG_KVM)),n,y)
 CONFIG_NO_XEN = $(if $(subst n,,$(CONFIG_XEN)),n,y)
-CONFIG_NO_XEN_MAPCACHE = $(if $(subst n,,$(CONFIG_XEN_MAPCACHE)),n,y)
 
 include ../config-host.mak
 include config-devices.mak
@@ -207,10 +206,8 @@ QEMU_CFLAGS += $(VNC_JPEG_CFLAGS)
 QEMU_CFLAGS += $(VNC_PNG_CFLAGS)
 
 # xen support
-obj-$(CONFIG_XEN) += xen-all.o xen_machine_pv.o xen_domainbuild.o
+obj-$(CONFIG_XEN) += xen-all.o xen_machine_pv.o xen_domainbuild.o xen-mapcache.o
 obj-$(CONFIG_NO_XEN) += xen-stub.o
-obj-i386-$(CONFIG_XEN_MAPCACHE) += xen-mapcache.o
-obj-$(CONFIG_NO_XEN_MAPCACHE) += xen-mapcache-stub.o
 
 obj-i386-$(CONFIG_XEN) += xen_platform.o
 
diff --git a/exec.c b/exec.c
index 50bccd8..067bb34 100644
--- a/exec.c
+++ b/exec.c
@@ -2953,7 +2953,7 @@ ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
                 abort();
             }
 #else
-            if (xen_mapcache_enabled()) {
+            if (xen_enabled()) {
                 xen_ram_alloc(new_block->offset, size);
             } else {
                 new_block->host = qemu_vmalloc(size);
@@ -3019,7 +3019,7 @@ void qemu_ram_free(ram_addr_t addr)
 #if defined(TARGET_S390X) && defined(CONFIG_KVM)
                 munmap(block->host, block->length);
 #else
-                if (xen_mapcache_enabled()) {
+                if (xen_enabled()) {
                     xen_invalidate_map_cache_entry(block->host);
                 } else {
                     qemu_vfree(block->host);
@@ -3112,7 +3112,7 @@ void *qemu_get_ram_ptr(ram_addr_t addr)
                 QLIST_REMOVE(block, next);
                 QLIST_INSERT_HEAD(&ram_list.blocks, block, next);
             }
-            if (xen_mapcache_enabled()) {
+            if (xen_enabled()) {
                 /* We need to check if the requested address is in the RAM
                  * because we don't want to map the entire memory in QEMU.
                  * In that case just map until the end of the page.
@@ -3143,7 +3143,7 @@ void *qemu_safe_ram_ptr(ram_addr_t addr)
 
     QLIST_FOREACH(block, &ram_list.blocks, next) {
         if (addr - block->offset < block->length) {
-            if (xen_mapcache_enabled()) {
+            if (xen_enabled()) {
                 /* We need to check if the requested address is in the RAM
                  * because we don't want to map the entire memory in QEMU.
                  * In that case just map until the end of the page.
@@ -3169,9 +3169,9 @@ void *qemu_safe_ram_ptr(ram_addr_t addr)
  * but takes a size argument */
 void *qemu_ram_ptr_length(target_phys_addr_t addr, target_phys_addr_t *size)
 {
-    if (xen_mapcache_enabled())
+    if (xen_enabled()) {
         return xen_map_cache(addr, *size, 1);
-    else {
+    } else {
         RAMBlock *block;
 
         QLIST_FOREACH(block, &ram_list.blocks, next) {
@@ -3200,7 +3200,7 @@ int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr)
     RAMBlock *block;
     uint8_t *host = ptr;
 
-    if (xen_mapcache_enabled()) {
+    if (xen_enabled()) {
         *ram_addr = xen_ram_addr_from_mapcache(ptr);
         return 0;
     }
@@ -4115,7 +4115,7 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
                 access_len -= l;
             }
         }
-        if (xen_mapcache_enabled()) {
+        if (xen_enabled()) {
             xen_invalidate_map_cache_entry(buffer);
         }
         return;
diff --git a/hw/xen.h b/hw/xen.h
index d435ca0..95029bb 100644
--- a/hw/xen.h
+++ b/hw/xen.h
@@ -31,15 +31,6 @@ static inline int xen_enabled(void)
 #endif
 }
 
-static inline int xen_mapcache_enabled(void)
-{
-#ifdef CONFIG_XEN_MAPCACHE
-    return xen_enabled();
-#else
-    return 0;
-#endif
-}
-
 int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num);
 void xen_piix3_set_irq(void *opaque, int irq_num, int level);
 void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len);
diff --git a/xen-mapcache-stub.c b/xen-mapcache-stub.c
deleted file mode 100644
index f037016..0000000
--- a/xen-mapcache-stub.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2011       Citrix Ltd.
- *
- * This work is licensed under the terms of the GNU GPL, version 2.  See
- * the COPYING file in the top-level directory.
- *
- */
-
-#include "config.h"
-
-#include "cpu.h"
-#include "qemu-common.h"
-#include "cpu-common.h"
-#include "xen-mapcache.h"
-
-void xen_map_cache_init(void)
-{
-}
-
-uint8_t *xen_map_cache(target_phys_addr_t phys_addr, target_phys_addr_t size,
-                       uint8_t lock)
-{
-    return qemu_get_ram_ptr(phys_addr);
-}
-
-ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
-{
-    return -1;
-}
-
-void xen_invalidate_map_cache(void)
-{
-}
-
-void xen_invalidate_map_cache_entry(uint8_t *buffer)
-{
-}
commit e41d7c691ad7f4ad78573f72048eecb16f78974a
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Jun 21 22:59:08 2011 +0200

    xen: Clean up map cache API naming
    
    The map cache is a Xen thing, so its API should make this clear.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/exec.c b/exec.c
index f1777e6..50bccd8 100644
--- a/exec.c
+++ b/exec.c
@@ -3020,7 +3020,7 @@ void qemu_ram_free(ram_addr_t addr)
                 munmap(block->host, block->length);
 #else
                 if (xen_mapcache_enabled()) {
-                    qemu_invalidate_entry(block->host);
+                    xen_invalidate_map_cache_entry(block->host);
                 } else {
                     qemu_vfree(block->host);
                 }
@@ -3118,9 +3118,10 @@ void *qemu_get_ram_ptr(ram_addr_t addr)
                  * In that case just map until the end of the page.
                  */
                 if (block->offset == 0) {
-                    return qemu_map_cache(addr, 0, 0);
+                    return xen_map_cache(addr, 0, 0);
                 } else if (block->host == NULL) {
-                    block->host = qemu_map_cache(block->offset, block->length, 1);
+                    block->host =
+                        xen_map_cache(block->offset, block->length, 1);
                 }
             }
             return block->host + (addr - block->offset);
@@ -3148,9 +3149,10 @@ void *qemu_safe_ram_ptr(ram_addr_t addr)
                  * In that case just map until the end of the page.
                  */
                 if (block->offset == 0) {
-                    return qemu_map_cache(addr, 0, 0);
+                    return xen_map_cache(addr, 0, 0);
                 } else if (block->host == NULL) {
-                    block->host = qemu_map_cache(block->offset, block->length, 1);
+                    block->host =
+                        xen_map_cache(block->offset, block->length, 1);
                 }
             }
             return block->host + (addr - block->offset);
@@ -3168,7 +3170,7 @@ void *qemu_safe_ram_ptr(ram_addr_t addr)
 void *qemu_ram_ptr_length(target_phys_addr_t addr, target_phys_addr_t *size)
 {
     if (xen_mapcache_enabled())
-        return qemu_map_cache(addr, *size, 1);
+        return xen_map_cache(addr, *size, 1);
     else {
         RAMBlock *block;
 
@@ -3199,7 +3201,7 @@ int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr)
     uint8_t *host = ptr;
 
     if (xen_mapcache_enabled()) {
-        *ram_addr = qemu_ram_addr_from_mapcache(ptr);
+        *ram_addr = xen_ram_addr_from_mapcache(ptr);
         return 0;
     }
 
@@ -4114,7 +4116,7 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
             }
         }
         if (xen_mapcache_enabled()) {
-            qemu_invalidate_entry(buffer);
+            xen_invalidate_map_cache_entry(buffer);
         }
         return;
     }
diff --git a/trace-events b/trace-events
index bebf612..2372385 100644
--- a/trace-events
+++ b/trace-events
@@ -399,9 +399,9 @@ disable xen_ram_alloc(unsigned long ram_addr, unsigned long size) "requested: %#
 disable xen_client_set_memory(uint64_t start_addr, unsigned long size, unsigned long phys_offset, bool log_dirty) "%#"PRIx64" size %#lx, offset %#lx, log_dirty %i"
 
 # xen-mapcache.c
-disable qemu_map_cache(uint64_t phys_addr) "want %#"PRIx64""
-disable qemu_remap_bucket(uint64_t index) "index %#"PRIx64""
-disable qemu_map_cache_return(void* ptr) "%p"
+disable xen_map_cache(uint64_t phys_addr) "want %#"PRIx64""
+disable xen_remap_bucket(uint64_t index) "index %#"PRIx64""
+disable xen_map_cache_return(void* ptr) "%p"
 disable xen_map_block(uint64_t phys_addr, uint64_t size) "%#"PRIx64", size %#"PRIx64""
 disable xen_unmap_block(void* addr, unsigned long size) "%p, size %#lx"
 
diff --git a/xen-all.c b/xen-all.c
index fcb106f..4827d6a 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -644,7 +644,7 @@ static void handle_ioreq(ioreq_t *req)
         case IOREQ_TYPE_TIMEOFFSET:
             break;
         case IOREQ_TYPE_INVALIDATE:
-            qemu_invalidate_map_cache();
+            xen_invalidate_map_cache();
             break;
         default:
             hw_error("Invalid ioreq type 0x%x\n", req->type);
@@ -852,7 +852,7 @@ int xen_hvm_init(void)
     }
 
     /* Init RAM management */
-    qemu_map_cache_init();
+    xen_map_cache_init();
     xen_ram_init(ram_size);
 
     qemu_add_vm_change_state_handler(xen_vm_change_state_handler, state);
diff --git a/xen-mapcache-stub.c b/xen-mapcache-stub.c
index 90a994d..f037016 100644
--- a/xen-mapcache-stub.c
+++ b/xen-mapcache-stub.c
@@ -13,24 +13,25 @@
 #include "cpu-common.h"
 #include "xen-mapcache.h"
 
-void qemu_map_cache_init(void)
+void xen_map_cache_init(void)
 {
 }
 
-uint8_t *qemu_map_cache(target_phys_addr_t phys_addr, target_phys_addr_t size, uint8_t lock)
+uint8_t *xen_map_cache(target_phys_addr_t phys_addr, target_phys_addr_t size,
+                       uint8_t lock)
 {
     return qemu_get_ram_ptr(phys_addr);
 }
 
-ram_addr_t qemu_ram_addr_from_mapcache(void *ptr)
+ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
 {
     return -1;
 }
 
-void qemu_invalidate_map_cache(void)
+void xen_invalidate_map_cache(void)
 {
 }
 
-void qemu_invalidate_entry(uint8_t *buffer)
+void xen_invalidate_map_cache_entry(uint8_t *buffer)
 {
 }
diff --git a/xen-mapcache.c b/xen-mapcache.c
index fac47cd..007136a 100644
--- a/xen-mapcache.c
+++ b/xen-mapcache.c
@@ -40,6 +40,9 @@
 #endif
 #define MCACHE_BUCKET_SIZE (1UL << MCACHE_BUCKET_SHIFT)
 
+#define mapcache_lock()   ((void)0)
+#define mapcache_unlock() ((void)0)
+
 typedef struct MapCacheEntry {
     target_phys_addr_t paddr_index;
     uint8_t *vaddr_base;
@@ -79,7 +82,7 @@ static inline int test_bits(int nr, int size, const unsigned long *addr)
         return 0;
 }
 
-void qemu_map_cache_init(void)
+void xen_map_cache_init(void)
 {
     unsigned long size;
     struct rlimit rlimit_as;
@@ -106,13 +109,14 @@ void qemu_map_cache_init(void)
 
     size = mapcache->nr_buckets * sizeof (MapCacheEntry);
     size = (size + XC_PAGE_SIZE - 1) & ~(XC_PAGE_SIZE - 1);
-    DPRINTF("qemu_map_cache_init, nr_buckets = %lx size %lu\n", mapcache->nr_buckets, size);
+    DPRINTF("%s, nr_buckets = %lx size %lu\n", __func__,
+            mapcache->nr_buckets, size);
     mapcache->entry = qemu_mallocz(size);
 }
 
-static void qemu_remap_bucket(MapCacheEntry *entry,
-                              target_phys_addr_t size,
-                              target_phys_addr_t address_index)
+static void xen_remap_bucket(MapCacheEntry *entry,
+                             target_phys_addr_t size,
+                             target_phys_addr_t address_index)
 {
     uint8_t *vaddr_base;
     xen_pfn_t *pfns;
@@ -120,7 +124,7 @@ static void qemu_remap_bucket(MapCacheEntry *entry,
     unsigned int i;
     target_phys_addr_t nb_pfn = size >> XC_PAGE_SHIFT;
 
-    trace_qemu_remap_bucket(address_index);
+    trace_xen_remap_bucket(address_index);
 
     pfns = qemu_mallocz(nb_pfn * sizeof (xen_pfn_t));
     err = qemu_mallocz(nb_pfn * sizeof (int));
@@ -164,17 +168,18 @@ static void qemu_remap_bucket(MapCacheEntry *entry,
     qemu_free(err);
 }
 
-uint8_t *qemu_map_cache(target_phys_addr_t phys_addr, target_phys_addr_t size, uint8_t lock)
+uint8_t *xen_map_cache(target_phys_addr_t phys_addr, target_phys_addr_t size,
+                       uint8_t lock)
 {
     MapCacheEntry *entry, *pentry = NULL;
     target_phys_addr_t address_index  = phys_addr >> MCACHE_BUCKET_SHIFT;
     target_phys_addr_t address_offset = phys_addr & (MCACHE_BUCKET_SIZE - 1);
     target_phys_addr_t __size = size;
 
-    trace_qemu_map_cache(phys_addr);
+    trace_xen_map_cache(phys_addr);
 
     if (address_index == mapcache->last_address_index && !lock && !__size) {
-        trace_qemu_map_cache_return(mapcache->last_address_vaddr + address_offset);
+        trace_xen_map_cache_return(mapcache->last_address_vaddr + address_offset);
         return mapcache->last_address_vaddr + address_offset;
     }
 
@@ -198,20 +203,20 @@ uint8_t *qemu_map_cache(target_phys_addr_t phys_addr, target_phys_addr_t size, u
     if (!entry) {
         entry = qemu_mallocz(sizeof (MapCacheEntry));
         pentry->next = entry;
-        qemu_remap_bucket(entry, __size, address_index);
+        xen_remap_bucket(entry, __size, address_index);
     } else if (!entry->lock) {
         if (!entry->vaddr_base || entry->paddr_index != address_index ||
                 entry->size != __size ||
                 !test_bits(address_offset >> XC_PAGE_SHIFT, size >> XC_PAGE_SHIFT,
                     entry->valid_mapping)) {
-            qemu_remap_bucket(entry, __size, address_index);
+            xen_remap_bucket(entry, __size, address_index);
         }
     }
 
     if(!test_bits(address_offset >> XC_PAGE_SHIFT, size >> XC_PAGE_SHIFT,
                 entry->valid_mapping)) {
         mapcache->last_address_index = -1;
-        trace_qemu_map_cache_return(NULL);
+        trace_xen_map_cache_return(NULL);
         return NULL;
     }
 
@@ -226,11 +231,11 @@ uint8_t *qemu_map_cache(target_phys_addr_t phys_addr, target_phys_addr_t size, u
         QTAILQ_INSERT_HEAD(&mapcache->locked_entries, reventry, next);
     }
 
-    trace_qemu_map_cache_return(mapcache->last_address_vaddr + address_offset);
+    trace_xen_map_cache_return(mapcache->last_address_vaddr + address_offset);
     return mapcache->last_address_vaddr + address_offset;
 }
 
-ram_addr_t qemu_ram_addr_from_mapcache(void *ptr)
+ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
 {
     MapCacheEntry *entry = NULL, *pentry = NULL;
     MapCacheRev *reventry;
@@ -247,7 +252,7 @@ ram_addr_t qemu_ram_addr_from_mapcache(void *ptr)
         }
     }
     if (!found) {
-        fprintf(stderr, "qemu_ram_addr_from_mapcache, could not find %p\n", ptr);
+        fprintf(stderr, "%s, could not find %p\n", __func__, ptr);
         QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) {
             DPRINTF("   "TARGET_FMT_plx" -> %p is present\n", reventry->paddr_index,
                     reventry->vaddr_req);
@@ -269,7 +274,7 @@ ram_addr_t qemu_ram_addr_from_mapcache(void *ptr)
         ((unsigned long) ptr - (unsigned long) entry->vaddr_base);
 }
 
-void qemu_invalidate_entry(uint8_t *buffer)
+void xen_invalidate_map_cache_entry(uint8_t *buffer)
 {
     MapCacheEntry *entry = NULL, *pentry = NULL;
     MapCacheRev *reventry;
@@ -290,7 +295,7 @@ void qemu_invalidate_entry(uint8_t *buffer)
         }
     }
     if (!found) {
-        DPRINTF("qemu_invalidate_entry, could not find %p\n", buffer);
+        DPRINTF("%s, could not find %p\n", __func__, buffer);
         QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) {
             DPRINTF("   "TARGET_FMT_plx" -> %p is present\n", reventry->paddr_index, reventry->vaddr_req);
         }
@@ -322,7 +327,7 @@ void qemu_invalidate_entry(uint8_t *buffer)
     qemu_free(entry);
 }
 
-void qemu_invalidate_map_cache(void)
+void xen_invalidate_map_cache(void)
 {
     unsigned long i;
     MapCacheRev *reventry;
diff --git a/xen-mapcache.h b/xen-mapcache.h
index 6216cc3..606b8af 100644
--- a/xen-mapcache.h
+++ b/xen-mapcache.h
@@ -9,13 +9,11 @@
 #ifndef XEN_MAPCACHE_H
 #define XEN_MAPCACHE_H
 
-void     qemu_map_cache_init(void);
-uint8_t  *qemu_map_cache(target_phys_addr_t phys_addr, target_phys_addr_t size, uint8_t lock);
-ram_addr_t qemu_ram_addr_from_mapcache(void *ptr);
-void     qemu_invalidate_entry(uint8_t *buffer);
-void     qemu_invalidate_map_cache(void);
-
-#define mapcache_lock()   ((void)0)
-#define mapcache_unlock() ((void)0)
+void xen_map_cache_init(void);
+uint8_t *xen_map_cache(target_phys_addr_t phys_addr, target_phys_addr_t size,
+                       uint8_t lock);
+ram_addr_t xen_ram_addr_from_mapcache(void *ptr);
+void xen_invalidate_map_cache_entry(uint8_t *buffer);
+void xen_invalidate_map_cache(void);
 
 #endif /* !XEN_MAPCACHE_H */
commit 6dbd588a412ce1ac2a4ba640b418278e92a71890
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Tue Jun 21 22:59:07 2011 +0200

    xen: Clean up build system
    
    Introduce CONFIG_XEN_BACKEND so that this new config solely controls the
    target-independent backend build and CONFIG_XEN can focus on per-target
    building.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/Makefile.objs b/Makefile.objs
index cea15e4..1635df6 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -155,8 +155,8 @@ slirp-obj-y += tcp_subr.o tcp_timer.o udp.o bootp.o tftp.o
 common-obj-$(CONFIG_SLIRP) += $(addprefix slirp/, $(slirp-obj-y))
 
 # xen backend driver support
-common-obj-$(CONFIG_XEN) += xen_backend.o xen_devconfig.o
-common-obj-$(CONFIG_XEN) += xen_console.o xenfb.o xen_disk.o xen_nic.o
+common-obj-$(CONFIG_XEN_BACKEND) += xen_backend.o xen_devconfig.o
+common-obj-$(CONFIG_XEN_BACKEND) += xen_console.o xenfb.o xen_disk.o xen_nic.o
 
 ######################################################################
 # libuser
diff --git a/Makefile.target b/Makefile.target
index a53a2ff..c347176 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -3,6 +3,8 @@
 GENERATED_HEADERS = config-target.h
 CONFIG_NO_PCI = $(if $(subst n,,$(CONFIG_PCI)),n,y)
 CONFIG_NO_KVM = $(if $(subst n,,$(CONFIG_KVM)),n,y)
+CONFIG_NO_XEN = $(if $(subst n,,$(CONFIG_XEN)),n,y)
+CONFIG_NO_XEN_MAPCACHE = $(if $(subst n,,$(CONFIG_XEN_MAPCACHE)),n,y)
 
 include ../config-host.mak
 include config-devices.mak
@@ -204,17 +206,8 @@ QEMU_CFLAGS += $(VNC_SASL_CFLAGS)
 QEMU_CFLAGS += $(VNC_JPEG_CFLAGS)
 QEMU_CFLAGS += $(VNC_PNG_CFLAGS)
 
-# xen backend driver support
-obj-i386-$(CONFIG_XEN) += xen_machine_pv.o xen_domainbuild.o
-
-ifeq ($(TARGET_BASE_ARCH), i386)
-  CONFIG_NO_XEN = $(if $(subst n,,$(CONFIG_XEN)),n,y)
-else
-  CONFIG_NO_XEN = y
-endif
 # xen support
-CONFIG_NO_XEN_MAPCACHE = $(if $(subst n,,$(CONFIG_XEN_MAPCACHE)),n,y)
-obj-i386-$(CONFIG_XEN) += xen-all.o
+obj-$(CONFIG_XEN) += xen-all.o xen_machine_pv.o xen_domainbuild.o
 obj-$(CONFIG_NO_XEN) += xen-stub.o
 obj-i386-$(CONFIG_XEN_MAPCACHE) += xen-mapcache.o
 obj-$(CONFIG_NO_XEN_MAPCACHE) += xen-mapcache-stub.o
diff --git a/configure b/configure
index 88159ac..e57efb1 100755
--- a/configure
+++ b/configure
@@ -2850,7 +2850,7 @@ if test "$bluez" = "yes" ; then
   echo "BLUEZ_CFLAGS=$bluez_cflags" >> $config_host_mak
 fi
 if test "$xen" = "yes" ; then
-  echo "CONFIG_XEN=y" >> $config_host_mak
+  echo "CONFIG_XEN_BACKEND=y" >> $config_host_mak
   echo "CONFIG_XEN_CTRL_INTERFACE_VERSION=$xen_ctrl_version" >> $config_host_mak
 fi
 if test "$io_thread" = "yes" ; then
commit 89b9ba661bd2d6155308f895ec075d813f0e129b
Author: Alexandre Raymond <cerbere at gmail.com>
Date:   Wed Jun 15 01:20:31 2011 -0400

    Fix signal handling of SIG_IPI when io-thread is enabled
    
    Both the signal thread (via sigwait()) and the cpu thread (via
    a normal signal handler) were attempting to catch SIG_IPI.
    
    This resulted in random freezes under Darwin.
    
    This patch separates SIG_IPI from the rest of the signals handled
    by the signal thread, because it is independently caught by the cpu
    thread.
    
    Signed-off-by: Alexandre Raymond <cerbere at gmail.com>
    Acked-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cpus.c b/cpus.c
index e02576c..3035314 100644
--- a/cpus.c
+++ b/cpus.c
@@ -396,10 +396,18 @@ static int qemu_signal_init(void)
     sigaddset(&set, SIGUSR2);
     pthread_sigmask(SIG_UNBLOCK, &set, NULL);
 
+    /*
+     * SIG_IPI must be blocked in the main thread and must not be caught
+     * by sigwait() in the signal thread. Otherwise, the cpu thread will
+     * not catch it reliably.
+     */
+    sigemptyset(&set);
+    sigaddset(&set, SIG_IPI);
+    pthread_sigmask(SIG_BLOCK, &set, NULL);
+
     sigemptyset(&set);
     sigaddset(&set, SIGIO);
     sigaddset(&set, SIGALRM);
-    sigaddset(&set, SIG_IPI);
     sigaddset(&set, SIGBUS);
 #else
     sigemptyset(&set);
commit 5664aed99a4ab6e661b40e475449a32150f46184
Author: Alexandre Raymond <cerbere at gmail.com>
Date:   Tue Jun 14 10:05:36 2011 -0400

    Fix signal handling when io-thread is disabled
    
    Changes since v1:
    - take pthread_sigmask() out of the ifdef as it is now common
    to both parts.
    
    This fix effectively blocks, in the main thread, the signals handled
    by signalfd or the compatibility signal thread.
    
    This way, such signals are received synchronously in the main thread
    through sigfd_handler() instead of triggering the signal handler
    directly, asynchronously.
    
    Signed-off-by: Alexandre Raymond <cerbere at gmail.com>
    Acked-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cpus.c b/cpus.c
index abd24ab..e02576c 100644
--- a/cpus.c
+++ b/cpus.c
@@ -401,7 +401,6 @@ static int qemu_signal_init(void)
     sigaddset(&set, SIGALRM);
     sigaddset(&set, SIG_IPI);
     sigaddset(&set, SIGBUS);
-    pthread_sigmask(SIG_BLOCK, &set, NULL);
 #else
     sigemptyset(&set);
     sigaddset(&set, SIGBUS);
@@ -414,6 +413,7 @@ static int qemu_signal_init(void)
         sigaddset(&set, SIGALRM);
     }
 #endif
+    pthread_sigmask(SIG_BLOCK, &set, NULL);
 
     sigfd = qemu_signalfd(&set);
     if (sigfd == -1) {
commit 107a47cc2dac1b6c5edae0121831713161cb70c5
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Jun 22 15:40:06 2011 +0100

    tcg/README: Expand advice on number of TCG ops per target insn
    
    Expand the note on the number of TCG ops generated per target insn,
    to be clearer about the range of applicability of the 20 op rule
    of thumb. Also add a note about the hard MAX_OP_PER_INSTR limit.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/tcg/README b/tcg/README
index 6600122..cfdfd96 100644
--- a/tcg/README
+++ b/tcg/README
@@ -504,7 +504,15 @@ register.
 - Don't hesitate to use helpers for complicated or seldom used target
   instructions. There is little performance advantage in using TCG to
   implement target instructions taking more than about twenty TCG
-  instructions.
+  instructions. Note that this rule of thumb is more applicable to
+  helpers doing complex logic or arithmetic, where the C compiler has
+  scope to do a good job of optimisation; it is less relevant where
+  the instruction is mostly doing loads and stores, and in those cases
+  inline TCG may still be faster for longer sequences.
+
+- The hard limit on the number of TCG instructions you can generate
+  per target instruction is set by MAX_OP_PER_INSTR in exec-all.h --
+  you cannot exceed this without risking a buffer overrun.
 
 - Use the 'discard' instruction if you know that TCG won't be able to
   prove that a given global is "dead" at a given program point. The
commit cf973e469bd9d47c0460347764c1315a6180e13c
Author: Artyom Tarasenko <atar4qemu at gmail.com>
Date:   Thu Jul 14 19:37:06 2011 +0200

    set ELF_HWCAP for SPARC and SPARC64
    
    setting ELF_HWCAP fixes dynamic library loading for Linux/sparc64
    This patch allows loading busybox from Debian 6 initrd
    
    Signed-off-by: Artyom Tarasenko <atar4qemu at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index b2746f2..443d246 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -417,7 +417,8 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
 #ifdef TARGET_SPARC64
 
 #define ELF_START_MMAP 0x80000000
-
+#define ELF_HWCAP  (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | HWCAP_SPARC_SWAP \
+                    | HWCAP_SPARC_MULDIV | HWCAP_SPARC_V9)
 #ifndef TARGET_ABI32
 #define elf_check_arch(x) ( (x) == EM_SPARCV9 || (x) == EM_SPARC32PLUS )
 #else
@@ -450,7 +451,8 @@ static inline void init_thread(struct target_pt_regs *regs,
 
 #else
 #define ELF_START_MMAP 0x80000000
-
+#define ELF_HWCAP  (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | HWCAP_SPARC_SWAP \
+                    | HWCAP_SPARC_MULDIV)
 #define elf_check_arch(x) ( (x) == EM_SPARC )
 
 #define ELF_CLASS   ELFCLASS32
commit f838e2c535e47dc8e99ae7ec711407b849700cc9
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Thu Jul 14 17:30:43 2011 +0000

    Sparc: fix FPU and AM enable checks for translation
    
    Translation used incorrectly CPUState fields directly to check
    for FPU enable state and 32 bit address masking on Sparc64.
    
    Fix by using TB flags instead.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 4edae78..22ee274 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -606,17 +606,6 @@ static inline int cpu_pil_allowed(CPUState *env1, int pil)
 #endif
 }
 
-static inline int cpu_fpu_enabled(CPUState *env1)
-{
-#if defined(CONFIG_USER_ONLY)
-    return 1;
-#elif !defined(TARGET_SPARC64)
-    return env1->psref;
-#else
-    return ((env1->pstate & PS_PEF) != 0) && ((env1->fprs & FPRS_FEF) != 0);
-#endif
-}
-
 #if defined(CONFIG_USER_ONLY)
 static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
 {
@@ -639,6 +628,9 @@ void cpu_tick_set_limit(CPUTimer *timer, uint64_t limit);
 trap_state* cpu_tsptr(CPUState* env);
 #endif
 
+#define TB_FLAG_FPU_ENABLED (1 << 4)
+#define TB_FLAG_AM_ENABLED (1 << 5)
+
 static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
                                         target_ulong *cs_base, int *flags)
 {
@@ -646,16 +638,41 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
     *cs_base = env->npc;
 #ifdef TARGET_SPARC64
     // AM . Combined FPU enable bits . PRIV . DMMU enabled . IMMU enabled
-    *flags = ((env->pstate & PS_AM) << 2)          /* 5 */
-        | (((env->pstate & PS_PEF) >> 1)           /* 3 */
-        | ((env->fprs & FPRS_FEF) << 2))           /* 4 */
-        | (env->pstate & PS_PRIV)                  /* 2 */
+    *flags = (env->pstate & PS_PRIV)               /* 2 */
         | ((env->lsu & (DMMU_E | IMMU_E)) >> 2)    /* 1, 0 */
         | ((env->tl & 0xff) << 8)
         | (env->dmmu.mmu_primary_context << 16);   /* 16... */
+    if (env->pstate & PS_AM) {
+        *flags |= TB_FLAG_AM_ENABLED;
+    }
+    if ((env->def->features & CPU_FEATURE_FLOAT) && (env->pstate & PS_PEF)
+        && (env->fprs & FPRS_FEF)) {
+        *flags |= TB_FLAG_FPU_ENABLED;
+    }
 #else
     // FPU enable . Supervisor
-    *flags = (env->psref << 4) | env->psrs;
+    *flags = env->psrs;
+    if ((env->def->features & CPU_FEATURE_FLOAT) && env->psref) {
+        *flags |= TB_FLAG_FPU_ENABLED;
+    }
+#endif
+}
+
+static inline bool tb_fpu_enabled(int tb_flags)
+{
+#if defined(CONFIG_USER_ONLY)
+    return true;
+#else
+    return tb_flags & TB_FLAG_FPU_ENABLED;
+#endif
+}
+
+static inline bool tb_am_enabled(int tb_flags)
+{
+#ifndef TARGET_SPARC64
+    return false;
+#else
+    return tb_flags & TB_FLAG_AM_ENABLED;
 #endif
 }
 
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 5f92dbb..27c2cf9 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -4879,13 +4879,8 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
     dc->cc_op = CC_OP_DYNAMIC;
     dc->mem_idx = cpu_mmu_index(env);
     dc->def = env->def;
-    if ((dc->def->features & CPU_FEATURE_FLOAT))
-        dc->fpu_enabled = cpu_fpu_enabled(env);
-    else
-        dc->fpu_enabled = 0;
-#ifdef TARGET_SPARC64
-    dc->address_mask_32bit = env->pstate & PS_AM;
-#endif
+    dc->fpu_enabled = tb_fpu_enabled(tb->flags);
+    dc->address_mask_32bit = tb_am_enabled(tb->flags);
     dc->singlestep = (env->singlestep_enabled || singlestep);
     gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
 
commit d8e586ffccd73c9c7758166241564c63109fc8d3
Author: Tsuneo Saito <tsnsaito at gmail.com>
Date:   Thu Jul 14 18:41:43 2011 +0900

    SPARC64: C99 comment fix for block-transfer ASIs
    
    Fixed C99 comments on block-tranfer ASIs.
    
    Signed-off-by: Tsuneo Saito <tsnsaito at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 2a28d5f..15af27b 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -3337,10 +3337,10 @@ void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
     addr = asi_address_mask(env, asi, addr);
 
     switch (asi) {
-    case 0xf0: // Block load primary
-    case 0xf1: // Block load secondary
-    case 0xf8: // Block load primary LE
-    case 0xf9: // Block load secondary LE
+    case 0xf0: /* UA2007/JPS1 Block load primary */
+    case 0xf1: /* UA2007/JPS1 Block load secondary */
+    case 0xf8: /* UA2007/JPS1 Block load primary LE */
+    case 0xf9: /* UA2007/JPS1 Block load secondary LE */
         if (rd & 7) {
             raise_exception(TT_ILL_INSN);
             return;
@@ -3357,8 +3357,8 @@ void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
     case 0x17: /* UA2007 Block load secondary, user privilege */
     case 0x1e: /* UA2007 Block load primary LE, user privilege */
     case 0x1f: /* UA2007 Block load secondary LE, user privilege */
-    case 0x70: // Block load primary, user privilege
-    case 0x71: // Block load secondary, user privilege
+    case 0x70: /* JPS1 Block load primary, user privilege */
+    case 0x71: /* JPS1 Block load secondary, user privilege */
     case 0x78: /* JPS1 Block load primary LE, user privilege */
     case 0x79: /* JPS1 Block load secondary LE, user privilege */
         if (rd & 7) {
@@ -3408,12 +3408,12 @@ void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
     addr = asi_address_mask(env, asi, addr);
 
     switch (asi) {
-    case 0xe0: // UA2007 Block commit store primary (cache flush)
-    case 0xe1: // UA2007 Block commit store secondary (cache flush)
-    case 0xf0: // Block store primary
-    case 0xf1: // Block store secondary
-    case 0xf8: // Block store primary LE
-    case 0xf9: // Block store secondary LE
+    case 0xe0: /* UA2007/JPS1 Block commit store primary (cache flush) */
+    case 0xe1: /* UA2007/JPS1 Block commit store secondary (cache flush) */
+    case 0xf0: /* UA2007/JPS1 Block store primary */
+    case 0xf1: /* UA2007/JPS1 Block store secondary */
+    case 0xf8: /* UA2007/JPS1 Block store primary LE */
+    case 0xf9: /* UA2007/JPS1 Block store secondary LE */
         if (rd & 7) {
             raise_exception(TT_ILL_INSN);
             return;
@@ -3430,8 +3430,8 @@ void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
     case 0x17: /* UA2007 Block load secondary, user privilege */
     case 0x1e: /* UA2007 Block load primary LE, user privilege */
     case 0x1f: /* UA2007 Block load secondary LE, user privilege */
-    case 0x70: // Block store primary, user privilege
-    case 0x71: // Block store secondary, user privilege
+    case 0x70: /* JPS1 Block store primary, user privilege */
+    case 0x71: /* JPS1 Block store secondary, user privilege */
     case 0x78: /* JPS1 Block load primary LE, user privilege */
     case 0x79: /* JPS1 Block load secondary LE, user privilege */
         if (rd & 7) {
commit d920bde9235f718f62e73f06be1922b36913f800
Author: Tsuneo Saito <tsnsaito at gmail.com>
Date:   Thu Jul 14 18:41:42 2011 +0900

    SPARC64: Add JPS1 ASI_BLK_AIU[PS]L ASIs for ldfa and stfa
    
    Support JPS1 little endian block transfer ASIs.
    
    Signed-off-by: Tsuneo Saito <tsnsaito at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 4faa709..2a28d5f 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -3359,6 +3359,8 @@ void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
     case 0x1f: /* UA2007 Block load secondary LE, user privilege */
     case 0x70: // Block load primary, user privilege
     case 0x71: // Block load secondary, user privilege
+    case 0x78: /* JPS1 Block load primary LE, user privilege */
+    case 0x79: /* JPS1 Block load secondary LE, user privilege */
         if (rd & 7) {
             raise_exception(TT_ILL_INSN);
             return;
@@ -3430,6 +3432,8 @@ void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
     case 0x1f: /* UA2007 Block load secondary LE, user privilege */
     case 0x70: // Block store primary, user privilege
     case 0x71: // Block store secondary, user privilege
+    case 0x78: /* JPS1 Block load primary LE, user privilege */
+    case 0x79: /* JPS1 Block load secondary LE, user privilege */
         if (rd & 7) {
             raise_exception(TT_ILL_INSN);
             return;
commit 073a0444104767cce1668799476eb882f8badf59
Author: Tsuneo Saito <tsnsaito at gmail.com>
Date:   Thu Jul 14 18:41:41 2011 +0900

    SPARC64: Add UA2007 ASI_BLK_AIU[PS]L? ASIs for stfa
    
    Support UA2007 block store ASIs for stfa instructions.
    
    Signed-off-by: Tsuneo Saito <tsnsaito at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index b76ffb6..4faa709 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -3424,6 +3424,10 @@ void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
         }
 
         return;
+    case 0x16: /* UA2007 Block load primary, user privilege */
+    case 0x17: /* UA2007 Block load secondary, user privilege */
+    case 0x1e: /* UA2007 Block load primary LE, user privilege */
+    case 0x1f: /* UA2007 Block load secondary LE, user privilege */
     case 0x70: // Block store primary, user privilege
     case 0x71: // Block store secondary, user privilege
         if (rd & 7) {
@@ -3433,7 +3437,7 @@ void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
         helper_check_align(addr, 0x3f);
         for (i = 0; i < 16; i++) {
             val = *(uint32_t *)&env->fpr[rd++];
-            helper_st_asi(addr, val, asi & 0x1f, 4);
+            helper_st_asi(addr, val, asi & 0x19, 4);
             addr += 4;
         }
 
commit 41317e2e2b58426ac9a5e1c3083c81840da3ae2b
Author: Tsuneo Saito <tsnsaito at gmail.com>
Date:   Thu Jul 14 18:41:40 2011 +0900

    SPARC64: Add UA2007 ASI_BLK_AIU[PS]L? ASIs for ldfa
    
    Support UA2007 block load ASIs for ldfa instructions.
    
    Signed-off-by: Tsuneo Saito <tsnsaito at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index fe71829..b76ffb6 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -3353,6 +3353,10 @@ void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
         }
 
         return;
+    case 0x16: /* UA2007 Block load primary, user privilege */
+    case 0x17: /* UA2007 Block load secondary, user privilege */
+    case 0x1e: /* UA2007 Block load primary LE, user privilege */
+    case 0x1f: /* UA2007 Block load secondary LE, user privilege */
     case 0x70: // Block load primary, user privilege
     case 0x71: // Block load secondary, user privilege
         if (rd & 7) {
@@ -3361,7 +3365,7 @@ void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
         }
         helper_check_align(addr, 0x3f);
         for (i = 0; i < 16; i++) {
-            *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x1f, 4,
+            *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x19, 4,
                                                          0);
             addr += 4;
         }
commit 5f06b54718b063840e14a93cd1059c3a92e4603a
Author: Tsuneo Saito <tsnsaito at gmail.com>
Date:   Thu Jul 14 18:41:39 2011 +0900

    SPARC64: fp_disabled checks on stfa/stdfa/stqfa
    
    stfa/stdfa/stqfa instructions should raise fp_disabled exceptions
    if %pstate.PEF==0 or %fprs.FEF==0.
    
    Signed-off-by: Tsuneo Saito <tsnsaito at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index a5a8eaf..5f92dbb 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -4732,6 +4732,9 @@ static void disas_sparc_insn(DisasContext * dc)
                 switch (xop) {
 #ifdef TARGET_SPARC64
                 case 0x34: /* V9 stfa */
+                    if (gen_trap_ifnofpu(dc, cpu_cond)) {
+                        goto jmp_insn;
+                    }
                     gen_stf_asi(cpu_addr, insn, 4, rd);
                     break;
                 case 0x36: /* V9 stqfa */
@@ -4739,6 +4742,9 @@ static void disas_sparc_insn(DisasContext * dc)
                         TCGv_i32 r_const;
 
                         CHECK_FPU_FEATURE(dc, FLOAT128);
+                        if (gen_trap_ifnofpu(dc, cpu_cond)) {
+                            goto jmp_insn;
+                        }
                         r_const = tcg_const_i32(7);
                         gen_helper_check_align(cpu_addr, r_const);
                         tcg_temp_free_i32(r_const);
@@ -4746,6 +4752,9 @@ static void disas_sparc_insn(DisasContext * dc)
                     }
                     break;
                 case 0x37: /* V9 stdfa */
+                    if (gen_trap_ifnofpu(dc, cpu_cond)) {
+                        goto jmp_insn;
+                    }
                     gen_stf_asi(cpu_addr, insn, 8, DFPREG(rd));
                     break;
                 case 0x3c: /* V9 casa */
commit e1ef36c4a34082a075182ec0ba44c80a2dbf43c2
Author: Tsuneo Saito <tsnsaito at gmail.com>
Date:   Thu Jul 14 18:41:38 2011 +0900

    SPARC64: Implement stfa/stdfa/stqfa instrcutions properly
    
    This patch implements sparcv9 stfa/stdfa/stqfa instructions
    with non block-store ASIs.
    
    Signed-off-by: Tsuneo Saito <tsnsaito at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index a75ac4f..fe71829 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -3396,6 +3396,7 @@ void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
 {
     unsigned int i;
     target_ulong val = 0;
+    CPU_DoubleU u;
 
     helper_check_align(addr, 3);
     addr = asi_address_mask(env, asi, addr);
@@ -3440,16 +3441,22 @@ void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
     switch(size) {
     default:
     case 4:
-        val = *((uint32_t *)&env->fpr[rd]);
+        helper_st_asi(addr, *(uint32_t *)&env->fpr[rd], asi, size);
         break;
     case 8:
-        val = *((int64_t *)&DT0);
+        u.l.upper = *(uint32_t *)&env->fpr[rd++];
+        u.l.lower = *(uint32_t *)&env->fpr[rd++];
+        helper_st_asi(addr, u.ll, asi, size);
         break;
     case 16:
-        // XXX
+        u.l.upper = *(uint32_t *)&env->fpr[rd++];
+        u.l.lower = *(uint32_t *)&env->fpr[rd++];
+        helper_st_asi(addr, u.ll, asi, 8);
+        u.l.upper = *(uint32_t *)&env->fpr[rd++];
+        u.l.lower = *(uint32_t *)&env->fpr[rd++];
+        helper_st_asi(addr + 8, u.ll, asi, 8);
         break;
     }
-    helper_st_asi(addr, val, asi, size);
 }
 
 target_ulong helper_cas_asi(target_ulong addr, target_ulong val1,
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 1e7e68d..a5a8eaf 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -4742,12 +4742,10 @@ static void disas_sparc_insn(DisasContext * dc)
                         r_const = tcg_const_i32(7);
                         gen_helper_check_align(cpu_addr, r_const);
                         tcg_temp_free_i32(r_const);
-                        gen_op_load_fpr_QT0(QFPREG(rd));
                         gen_stf_asi(cpu_addr, insn, 16, QFPREG(rd));
                     }
                     break;
                 case 0x37: /* V9 stdfa */
-                    gen_op_load_fpr_DT0(DFPREG(rd));
                     gen_stf_asi(cpu_addr, insn, 8, DFPREG(rd));
                     break;
                 case 0x3c: /* V9 casa */
commit 8872eb4f567b9ae36dbd9c320f6a86c53a776d43
Author: Tsuneo Saito <tsnsaito at gmail.com>
Date:   Thu Jul 14 18:41:37 2011 +0900

    SPARC64: fp_disabled checks on ldfa/lddfa/ldqfa
    
    ldfa/lddfa/ldqfa instructions should raise fp_disabled exceptions
    if %pstate.PEF==0 or %fprs.FEF==0.
    
    Signed-off-by: Tsuneo Saito <tsnsaito at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index f32a674..1e7e68d 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -4484,10 +4484,16 @@ static void disas_sparc_insn(DisasContext * dc)
                 case 0x2d: /* V9 prefetch, no effect */
                     goto skip_move;
                 case 0x30: /* V9 ldfa */
+                    if (gen_trap_ifnofpu(dc, cpu_cond)) {
+                        goto jmp_insn;
+                    }
                     save_state(dc, cpu_cond);
                     gen_ldf_asi(cpu_addr, insn, 4, rd);
                     goto skip_move;
                 case 0x33: /* V9 lddfa */
+                    if (gen_trap_ifnofpu(dc, cpu_cond)) {
+                        goto jmp_insn;
+                    }
                     save_state(dc, cpu_cond);
                     gen_ldf_asi(cpu_addr, insn, 8, DFPREG(rd));
                     goto skip_move;
@@ -4495,6 +4501,9 @@ static void disas_sparc_insn(DisasContext * dc)
                     goto skip_move;
                 case 0x32: /* V9 ldqfa */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
+                    if (gen_trap_ifnofpu(dc, cpu_cond)) {
+                        goto jmp_insn;
+                    }
                     save_state(dc, cpu_cond);
                     gen_ldf_asi(cpu_addr, insn, 16, QFPREG(rd));
                     goto skip_move;
commit 4183f36df0bf8cb82dda423414aa3b1a82e91ce9
Author: Tsuneo Saito <tsnsaito at gmail.com>
Date:   Thu Jul 14 18:41:36 2011 +0900

    SPARC64: Implement ldfa/lddfa/ldqfa instructions properly
    
    This patch implements sparcv9 ldfa/lddfa/ldqfa instructions
    with non block-load ASIs.
    
    Signed-off-by: Tsuneo Saito <tsnsaito at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index fd0cfbd..a75ac4f 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -3331,7 +3331,7 @@ void helper_ldda_asi(target_ulong addr, int asi, int rd)
 void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
 {
     unsigned int i;
-    target_ulong val;
+    CPU_DoubleU u;
 
     helper_check_align(addr, 3);
     addr = asi_address_mask(env, asi, addr);
@@ -3371,17 +3371,23 @@ void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
         break;
     }
 
-    val = helper_ld_asi(addr, asi, size, 0);
     switch(size) {
     default:
     case 4:
-        *((uint32_t *)&env->fpr[rd]) = val;
+        *((uint32_t *)&env->fpr[rd]) = helper_ld_asi(addr, asi, size, 0);
         break;
     case 8:
-        *((int64_t *)&DT0) = val;
+        u.ll = helper_ld_asi(addr, asi, size, 0);
+        *((uint32_t *)&env->fpr[rd++]) = u.l.upper;
+        *((uint32_t *)&env->fpr[rd++]) = u.l.lower;
         break;
     case 16:
-        // XXX
+        u.ll = helper_ld_asi(addr, asi, 8, 0);
+        *((uint32_t *)&env->fpr[rd++]) = u.l.upper;
+        *((uint32_t *)&env->fpr[rd++]) = u.l.lower;
+        u.ll = helper_ld_asi(addr + 8, asi, 8, 0);
+        *((uint32_t *)&env->fpr[rd++]) = u.l.upper;
+        *((uint32_t *)&env->fpr[rd++]) = u.l.lower;
         break;
     }
 }
commit 6fea2ea462f4f726249f0e646012d21f24c024b5
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Jul 12 21:27:15 2011 +0100

    linux-user/signal.c: Rename s390 target_ucontext fields to fix ia64
    
    The ia64 sys/ucontext.h defines macros 'uc_link', 'uc_sigmask' and
    'uc_stack'. Rename the s390 target_ucontext struct members to tuc_*,
    bringing them into line with the other targets and fixing a compile
    failure on ia64 hosts caused by this clash.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/signal.c b/linux-user/signal.c
index 7d168e1..07ad07a 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -3662,11 +3662,11 @@ typedef struct {
 } sigframe;
 
 struct target_ucontext {
-    target_ulong uc_flags;
-    struct target_ucontext *uc_link;
-    target_stack_t uc_stack;
-    target_sigregs uc_mcontext;
-    target_sigset_t uc_sigmask;   /* mask last for extensibility */
+    target_ulong tuc_flags;
+    struct target_ucontext *tuc_link;
+    target_stack_t tuc_stack;
+    target_sigregs tuc_mcontext;
+    target_sigset_t tuc_sigmask;   /* mask last for extensibility */
 };
 
 typedef struct {
@@ -3814,16 +3814,16 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
     }
 
     /* Create the ucontext.  */
-    __put_user(0, &frame->uc.uc_flags);
-    __put_user((abi_ulong)0, (abi_ulong *)&frame->uc.uc_link);
-    __put_user(target_sigaltstack_used.ss_sp, &frame->uc.uc_stack.ss_sp);
+    __put_user(0, &frame->uc.tuc_flags);
+    __put_user((abi_ulong)0, (abi_ulong *)&frame->uc.tuc_link);
+    __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
     __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
-                      &frame->uc.uc_stack.ss_flags);
-    __put_user(target_sigaltstack_used.ss_size, &frame->uc.uc_stack.ss_size);
-    save_sigregs(env, &frame->uc.uc_mcontext);
+                      &frame->uc.tuc_stack.ss_flags);
+    __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
+    save_sigregs(env, &frame->uc.tuc_mcontext);
     for (i = 0; i < TARGET_NSIG_WORDS; i++) {
         __put_user((abi_ulong)set->sig[i],
-        (abi_ulong *)&frame->uc.uc_sigmask.sig[i]);
+        (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
     }
 
     /* Set up to return from userspace.  If provided, use a stub
@@ -3928,15 +3928,15 @@ long do_rt_sigreturn(CPUState *env)
     if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
         goto badframe;
     }
-    target_to_host_sigset(&set, &frame->uc.uc_sigmask);
+    target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
 
     sigprocmask(SIG_SETMASK, &set, NULL); /* ~_BLOCKABLE? */
 
-    if (restore_sigregs(env, &frame->uc.uc_mcontext)) {
+    if (restore_sigregs(env, &frame->uc.tuc_mcontext)) {
         goto badframe;
     }
 
-    if (do_sigaltstack(frame_addr + offsetof(rt_sigframe, uc.uc_stack), 0,
+    if (do_sigaltstack(frame_addr + offsetof(rt_sigframe, uc.tuc_stack), 0,
                        get_sp_from_cpustate(env)) == -EFAULT) {
         goto badframe;
     }
commit 48e515d4fa7c6ffdc21944ffc8620a161c772c09
Author: Riku Voipio <riku.voipio at linaro.org>
Date:   Tue Jul 12 15:40:51 2011 +0300

    linux-user: make MIPS and ARM eabi use same argument reordering
    
    MIPS uses similar calling convention than ARM eabi, where when using
    64-bit values some registers are skipped. This patch makes MIPS and ARM
    eabi share the argument reordering code.
    
    This affects ftruncate64, creating insane sized fails (or just failing).
    
    Cc: Wesley W. Terpstra <terpstra at debian.org>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 9eb41a0..1dd7aad 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -580,6 +580,17 @@ extern int setfsuid(int);
 extern int setfsgid(int);
 extern int setgroups(int, gid_t *);
 
+/* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */
+#ifdef TARGET_ARM 
+static inline int regpairs_aligned(void *cpu_env) {
+    return ((((CPUARMState *)cpu_env)->eabi) == 1) ;
+}
+#elif defined(TARGET_MIPS)
+static inline int regpairs_aligned(void *cpu_env) { return 1; }
+#else
+static inline int regpairs_aligned(void *cpu_env) { return 0; }
+#endif
+
 #define ERRNO_TABLE_SIZE 1200
 
 /* target_to_host_errno_table[] is initialized from
@@ -4375,13 +4386,10 @@ static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
                                          abi_long arg3,
                                          abi_long arg4)
 {
-#ifdef TARGET_ARM
-    if (((CPUARMState *)cpu_env)->eabi)
-      {
+    if (regpairs_aligned(cpu_env)) {
         arg2 = arg3;
         arg3 = arg4;
-      }
-#endif
+    }
     return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
 }
 #endif
@@ -4392,13 +4400,10 @@ static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
                                           abi_long arg3,
                                           abi_long arg4)
 {
-#ifdef TARGET_ARM
-    if (((CPUARMState *)cpu_env)->eabi)
-      {
+    if (regpairs_aligned(cpu_env)) {
         arg2 = arg3;
         arg3 = arg4;
-      }
-#endif
+    }
     return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
 }
 #endif
@@ -6857,20 +6862,16 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 #endif
 #ifdef TARGET_NR_pread
     case TARGET_NR_pread:
-#ifdef TARGET_ARM
-        if (((CPUARMState *)cpu_env)->eabi)
+        if (regpairs_aligned(cpu_env))
             arg4 = arg5;
-#endif
         if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
             goto efault;
         ret = get_errno(pread(arg1, p, arg3, arg4));
         unlock_user(p, arg2, ret);
         break;
     case TARGET_NR_pwrite:
-#ifdef TARGET_ARM
-        if (((CPUARMState *)cpu_env)->eabi)
+        if (regpairs_aligned(cpu_env))
             arg4 = arg5;
-#endif
         if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
             goto efault;
         ret = get_errno(pwrite(arg1, p, arg3, arg4));
@@ -7621,14 +7622,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 #ifdef TARGET_NR_readahead
     case TARGET_NR_readahead:
 #if TARGET_ABI_BITS == 32
-#ifdef TARGET_ARM
-        if (((CPUARMState *)cpu_env)->eabi)
-        {
+        if (regpairs_aligned(cpu_env)) {
             arg2 = arg3;
             arg3 = arg4;
             arg4 = arg5;
         }
-#endif
         ret = get_errno(readahead(arg1, ((off64_t)arg3 << 32) | arg2, arg4));
 #else
         ret = get_errno(readahead(arg1, arg2, arg3));
commit c3edf3472faf3dad73a0c504db8e9d853debfde6
Author: Riku Voipio <riku.voipio at linaro.org>
Date:   Tue Jul 12 16:01:54 2011 +0300

    linux-user: correct syscall 123 on sh4
    
    As reported by Cédric VINCENT:
    
    The syscall #123 on SH4 should be "TARGET_NR_cacheflush" instead of
    "TARGET_NR_modify_ldt" [1].  The only consequence of this misnaming is
    that many "Unsupported syscall" warnings are issued when emulating JIT
    compilers.
    
    Reported-by: Cédric VINCENT <cedric.vincent at st.com>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/sh4/syscall_nr.h b/linux-user/sh4/syscall_nr.h
index 6173a7c..365db58 100644
--- a/linux-user/sh4/syscall_nr.h
+++ b/linux-user/sh4/syscall_nr.h
@@ -125,7 +125,7 @@
 #define TARGET_NR_clone		120
 #define TARGET_NR_setdomainname	121
 #define TARGET_NR_uname		122
-#define TARGET_NR_modify_ldt		123
+#define TARGET_NR_cacheflush		123
 #define TARGET_NR_adjtimex		124
 #define TARGET_NR_mprotect		125
 #define TARGET_NR_sigprocmask	126
commit cc4662f9642995c78bed587707eeb9ad8500035b
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Sat Jul 9 10:22:07 2011 +0100

    os-posix: set groups properly for -runas
    
    Andrew Griffiths reports that -runas does not set supplementary group
    IDs.  This means that gid 0 (root) is not dropped when switching to an
    unprivileged user.
    
    Add an initgroups(3) call to use the -runas user's /etc/groups
    membership to update the supplementary group IDs.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Acked-by: Chris Wright <chrisw at sous-sol.org>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/os-posix.c b/os-posix.c
index 7dfb278..6f8d488 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -31,6 +31,7 @@
 /*needed for MAP_POPULATE before including qemu-options.h */
 #include <sys/mman.h>
 #include <pwd.h>
+#include <grp.h>
 #include <libgen.h>
 
 /* Needed early for CONFIG_BSD etc. */
@@ -199,6 +200,11 @@ static void change_process_uid(void)
             fprintf(stderr, "Failed to setgid(%d)\n", user_pwd->pw_gid);
             exit(1);
         }
+        if (initgroups(user_pwd->pw_name, user_pwd->pw_gid) < 0) {
+            fprintf(stderr, "Failed to initgroups(\"%s\", %d)\n",
+                    user_pwd->pw_name, user_pwd->pw_gid);
+            exit(1);
+        }
         if (setuid(user_pwd->pw_uid) < 0) {
             fprintf(stderr, "Failed to setuid(%d)\n", user_pwd->pw_uid);
             exit(1);
commit 429bef6912bd3d504593b9aefdbcb39e981d387e
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Sat Jul 9 16:44:41 2011 +0200

    esp: cancel current request only if some request is in flight
    
    This bug was introduced in 94d3f98a3f3caddd7875f9a11776daeb84962a7b:
    scsi_cancel_io was checking if some request was pending before trying
    to cancel it, while scsi_req_cancel always cancels the request.
    
    This may lead to a crash of Qemu due to dereferencing a NULL pointer,
    as exhibited by NetBSD 5.1 installer on MIPS Magnum emulation.
    
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/esp.c b/hw/esp.c
index 8e95672..aa50800 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -219,7 +219,7 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf)
     s->ti_rptr = 0;
     s->ti_wptr = 0;
 
-    if (s->current_dev) {
+    if (s->current_req) {
         /* Started a new command before the old one finished.  Cancel it.  */
         scsi_req_cancel(s->current_req);
         s->async_len = 0;
commit f5fc40bb8133849618e0d05adc798c5f07f7b17f
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Jul 4 22:02:46 2011 +0100

    target-alpha, target-ppc: Remove unnecessary setjmp.h include
    
    Remove the include of setjmp.h from the cpu.h of target-alpha
    and target-ppc. This is unnecessary because cpu-defs.h already
    includes this header; this change brings these two targets
    into line with all the rest.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index 411bd55..78caa79 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -28,8 +28,6 @@
 
 #include "cpu-defs.h"
 
-#include <setjmp.h>
-
 #include "softfloat.h"
 
 #define TARGET_HAS_ICE 1
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 84f8ff6..d903366 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -75,8 +75,6 @@
 
 #include "cpu-defs.h"
 
-#include <setjmp.h>
-
 #include "softfloat.h"
 
 #define TARGET_HAS_ICE 1
commit 462df2887cf55bb95faa7a76a0fd07722c63bb0c
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Mon Jul 4 20:52:38 2011 +0200

    Remove unneeded setjmp.h (fix compilation on Debian "lenny")
    
    Some versions of png.h cannot be included after setjmp.h,
    even when PNG_SKIP_SETJMP_CHECK was defined.
    
    setjmp.h was included from qemu-common.h and is not needed there.
    Removing the include statement fixes compilation of ui/vnc-enc-tight.c
    with CONFIG_VNC_PNG defined.
    
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/qemu-common.h b/qemu-common.h
index abd7a75..c2b79bd 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -117,7 +117,6 @@ static inline char *realpath(const char *path, char *resolved_path)
 /* FIXME: Remove NEED_CPU_H.  */
 #ifndef NEED_CPU_H
 
-#include <setjmp.h>
 #include "osdep.h"
 #include "bswap.h"
 
commit 0d10193870b5a81c3bce13a602a5403c3a55cf6c
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Sat Jul 2 09:50:51 2011 +0200

    tcg: Reload local variables after return from longjmp
    
    Recent compilers look deep into cpu_exec, find longjmp as a noreturn
    function and decide to smash some stack variables as they won't be used
    again. This may lead to env becoming invalid after return from setjmp,
    causing crashes. Fix it by reloading env from cpu_single_env in that
    case.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cpu-exec.c b/cpu-exec.c
index 20e3ec4..de0d716 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -587,6 +587,10 @@ int cpu_exec(CPUState *env)
                 /* reset soft MMU for next block (it can currently
                    only be set by a memory fault) */
             } /* for(;;) */
+        } else {
+            /* Reload env after longjmp - the compiler may have smashed all
+             * local variables as longjmp is marked 'noreturn'. */
+            env = cpu_single_env;
         }
     } /* for(;;) */
 
commit 5b620fb698e69a5386f2f02c7c455bdbdd59a52b
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Jun 22 15:16:32 2011 +0100

    exec-all.h: Make MAX_OP_PER_INSTR large enough for target-arm's uses
    
    The target-arm frontend's worst-case TCG ops per instr is 194 (and in
    general many of the "load multiple registers" ARM instructions generate
    more than 100 TCG ops). Raise MAX_OP_PER_INSTR accordingly to avoid
    possible buffer overruns.
    
    Since it doesn't make any sense for the "64 bit guest on 32 bit host"
    case to have a smaller limit than the normal case, we collapse the
    two cases back into each other again.
    
    (This increase costs us about 14K in extra static buffer space and
    21K of extra margin at the end of a 32MB codegen buffer.)
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/exec-all.h b/exec-all.h
index 21a69d6..69acf3b 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -44,11 +44,7 @@ struct TranslationBlock;
 typedef struct TranslationBlock TranslationBlock;
 
 /* XXX: make safe guess about sizes */
-#if (HOST_LONG_BITS == 32) && (TARGET_LONG_BITS == 64)
-#define MAX_OP_PER_INSTR 128
-#else
-#define MAX_OP_PER_INSTR 96
-#endif
+#define MAX_OP_PER_INSTR 208
 
 #if HOST_LONG_BITS == 32
 #define MAX_OPC_PARAM_PER_ARG 2
commit a884da8a06806d55fa83c8011bb17d6838583f9b
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Jun 22 11:58:25 2011 +0100

    exec.c: Fix calculation of code_gen_buffer_max_size
    
    When calculating the point at which we should not try to put another
    TB into the code gen buffer, we have to allow not just for OPC_MAX_SIZE
    but OPC_BUF_SIZE. This is because the target translate.c will only
    stop when an instruction has put it past the OPC_MAX_SIZE limit, so
    we have to include the MAX_OP_PER_INSTR margin which that final insn
    might have used.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/exec.c b/exec.c
index 9e6913e..f1777e6 100644
--- a/exec.c
+++ b/exec.c
@@ -555,8 +555,8 @@ static void code_gen_alloc(unsigned long tb_size)
 #endif
 #endif /* !USE_STATIC_CODE_GEN_BUFFER */
     map_exec(code_gen_prologue, sizeof(code_gen_prologue));
-    code_gen_buffer_max_size = code_gen_buffer_size - 
-        (TCG_MAX_OP_SIZE * OPC_MAX_SIZE);
+    code_gen_buffer_max_size = code_gen_buffer_size -
+        (TCG_MAX_OP_SIZE * OPC_BUF_SIZE);
     code_gen_max_blocks = code_gen_buffer_size / CODE_GEN_AVG_BLOCK_SIZE;
     tbs = qemu_malloc(code_gen_max_blocks * sizeof(TranslationBlock));
 }
commit 06c46bbab04faa3b5a1c10756be7db4f09af1ffb
Author: Alexander Graf <agraf at suse.de>
Date:   Tue Jul 5 18:28:10 2011 +0200

    spapr: use specific endian ld/st_phys
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/spapr.h b/hw/spapr.h
index b52133a..263691b 100644
--- a/hw/spapr.h
+++ b/hw/spapr.h
@@ -280,12 +280,12 @@ target_ulong spapr_hypercall(CPUState *env, target_ulong opcode,
 
 static inline uint32_t rtas_ld(target_ulong phys, int n)
 {
-    return ldl_phys(phys + 4*n);
+    return ldl_be_phys(phys + 4*n);
 }
 
 static inline void rtas_st(target_ulong phys, int n, uint32_t val)
 {
-    stl_phys(phys + 4*n, val);
+    stl_be_phys(phys + 4*n, val);
 }
 
 typedef void (*spapr_rtas_fn)(sPAPREnvironment *spapr, uint32_t token,
diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c
index 84da8fc..5cd8d8f 100644
--- a/hw/spapr_hcall.c
+++ b/hw/spapr_hcall.c
@@ -278,7 +278,7 @@ static target_ulong register_vpa(CPUState *env, target_ulong vpa)
     }
     /* FIXME: bounds check the address */
 
-    size = lduw_phys(vpa + 0x4);
+    size = lduw_be_phys(vpa + 0x4);
 
     if (size < VPA_MIN_SIZE) {
         return H_PARAMETER;
@@ -321,7 +321,7 @@ static target_ulong register_slb_shadow(CPUState *env, target_ulong addr)
         return H_HARDWARE;
     }
 
-    size = ldl_phys(addr + 0x4);
+    size = ldl_be_phys(addr + 0x4);
     if (size < 0x8) {
         return H_PARAMETER;
     }
@@ -354,7 +354,7 @@ static target_ulong register_dtl(CPUState *env, target_ulong addr)
         return H_HARDWARE;
     }
 
-    size = ldl_phys(addr + 0x4);
+    size = ldl_be_phys(addr + 0x4);
 
     if (size < 48) {
         return H_PARAMETER;
@@ -441,9 +441,9 @@ static target_ulong h_rtas(CPUState *env, sPAPREnvironment *spapr,
                            target_ulong opcode, target_ulong *args)
 {
     target_ulong rtas_r3 = args[0];
-    uint32_t token = ldl_phys(rtas_r3);
-    uint32_t nargs = ldl_phys(rtas_r3 + 4);
-    uint32_t nret = ldl_phys(rtas_r3 + 8);
+    uint32_t token = ldl_be_phys(rtas_r3);
+    uint32_t nargs = ldl_be_phys(rtas_r3 + 4);
+    uint32_t nret = ldl_be_phys(rtas_r3 + 8);
 
     return spapr_rtas_call(spapr, token, nargs, rtas_r3 + 12,
                            nret, rtas_r3 + 12 + 4*nargs);
commit 04bc74edecef1b671c84be0b402998e96a282889
Author: Alexander Graf <agraf at suse.de>
Date:   Tue Jul 5 18:28:09 2011 +0200

    s390-virtio: use specific endian ld/st_phys
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c
index 2bf4821..e2f3e32 100644
--- a/hw/s390-virtio-bus.c
+++ b/hw/s390-virtio-bus.c
@@ -166,7 +166,7 @@ static uint64_t s390_virtio_device_vq_token(VirtIOS390Device *dev, int vq)
                 (vq * VIRTIO_VQCONFIG_LEN) +
                 VIRTIO_VQCONFIG_OFFS_TOKEN;
 
-    return ldq_phys(token_off);
+    return ldq_be_phys(token_off);
 }
 
 static ram_addr_t s390_virtio_device_num_vq(VirtIOS390Device *dev)
@@ -220,8 +220,8 @@ void s390_virtio_device_sync(VirtIOS390Device *dev)
         vring = s390_virtio_next_ring(bus);
         virtio_queue_set_addr(dev->vdev, i, vring);
         virtio_queue_set_vector(dev->vdev, i, i);
-        stq_phys(vq + VIRTIO_VQCONFIG_OFFS_ADDRESS, vring);
-        stw_phys(vq + VIRTIO_VQCONFIG_OFFS_NUM, virtio_queue_get_num(dev->vdev, i));
+        stq_be_phys(vq + VIRTIO_VQCONFIG_OFFS_ADDRESS, vring);
+        stw_be_phys(vq + VIRTIO_VQCONFIG_OFFS_NUM, virtio_queue_get_num(dev->vdev, i));
     }
 
     cur_offs = dev->dev_offs;
@@ -229,7 +229,7 @@ void s390_virtio_device_sync(VirtIOS390Device *dev)
     cur_offs += num_vq * VIRTIO_VQCONFIG_LEN;
 
     /* Sync feature bitmap */
-    stl_phys(cur_offs, bswap32(dev->host_features));
+    stl_le_phys(cur_offs, dev->host_features);
 
     dev->feat_offs = cur_offs + dev->feat_len;
     cur_offs += dev->feat_len * 2;
@@ -253,7 +253,7 @@ void s390_virtio_device_update_status(VirtIOS390Device *dev)
 
     /* Update guest supported feature bitmap */
 
-    features = bswap32(ldl_phys(dev->feat_offs));
+    features = bswap32(ldl_be_phys(dev->feat_offs));
     if (vdev->set_features) {
         vdev->set_features(vdev, features);
     }
diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c
index 3eba7ea..abe954d 100644
--- a/hw/s390-virtio.c
+++ b/hw/s390-virtio.c
@@ -193,7 +193,7 @@ static void s390_init(ram_addr_t my_ram_size,
     if (kernel_filename) {
         kernel_size = load_image(kernel_filename, qemu_get_ram_ptr(0));
 
-        if (lduw_phys(KERN_IMAGE_START) != 0x0dd0) {
+        if (lduw_be_phys(KERN_IMAGE_START) != 0x0dd0) {
             fprintf(stderr, "Specified image is not an s390 boot image\n");
             exit(1);
         }
@@ -232,8 +232,8 @@ static void s390_init(ram_addr_t my_ram_size,
         }
         initrd_size = load_image(initrd_filename, qemu_get_ram_ptr(initrd_offset));
 
-        stq_phys(INITRD_PARM_START, initrd_offset);
-        stq_phys(INITRD_PARM_SIZE, initrd_size);
+        stq_be_phys(INITRD_PARM_START, initrd_offset);
+        stq_be_phys(INITRD_PARM_SIZE, initrd_size);
     }
 
     if (kernel_cmdline) {
commit db663d0f7aae936d10e2452d0eab8bb3b0147e74
Author: Alexander Graf <agraf at suse.de>
Date:   Tue Jul 5 18:28:08 2011 +0200

    ppc405_uc: use specific endian ld/st_phys
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c
index 2ce79ee..06a053b 100644
--- a/hw/ppc405_uc.c
+++ b/hw/ppc405_uc.c
@@ -51,39 +51,42 @@ ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd,
         bdloc = 0x01000000UL - sizeof(struct ppc4xx_bd_info_t);
     else
         bdloc = bd->bi_memsize - sizeof(struct ppc4xx_bd_info_t);
-    stl_phys(bdloc + 0x00, bd->bi_memstart);
-    stl_phys(bdloc + 0x04, bd->bi_memsize);
-    stl_phys(bdloc + 0x08, bd->bi_flashstart);
-    stl_phys(bdloc + 0x0C, bd->bi_flashsize);
-    stl_phys(bdloc + 0x10, bd->bi_flashoffset);
-    stl_phys(bdloc + 0x14, bd->bi_sramstart);
-    stl_phys(bdloc + 0x18, bd->bi_sramsize);
-    stl_phys(bdloc + 0x1C, bd->bi_bootflags);
-    stl_phys(bdloc + 0x20, bd->bi_ipaddr);
-    for (i = 0; i < 6; i++)
+    stl_be_phys(bdloc + 0x00, bd->bi_memstart);
+    stl_be_phys(bdloc + 0x04, bd->bi_memsize);
+    stl_be_phys(bdloc + 0x08, bd->bi_flashstart);
+    stl_be_phys(bdloc + 0x0C, bd->bi_flashsize);
+    stl_be_phys(bdloc + 0x10, bd->bi_flashoffset);
+    stl_be_phys(bdloc + 0x14, bd->bi_sramstart);
+    stl_be_phys(bdloc + 0x18, bd->bi_sramsize);
+    stl_be_phys(bdloc + 0x1C, bd->bi_bootflags);
+    stl_be_phys(bdloc + 0x20, bd->bi_ipaddr);
+    for (i = 0; i < 6; i++) {
         stb_phys(bdloc + 0x24 + i, bd->bi_enetaddr[i]);
-    stw_phys(bdloc + 0x2A, bd->bi_ethspeed);
-    stl_phys(bdloc + 0x2C, bd->bi_intfreq);
-    stl_phys(bdloc + 0x30, bd->bi_busfreq);
-    stl_phys(bdloc + 0x34, bd->bi_baudrate);
-    for (i = 0; i < 4; i++)
+    }
+    stw_be_phys(bdloc + 0x2A, bd->bi_ethspeed);
+    stl_be_phys(bdloc + 0x2C, bd->bi_intfreq);
+    stl_be_phys(bdloc + 0x30, bd->bi_busfreq);
+    stl_be_phys(bdloc + 0x34, bd->bi_baudrate);
+    for (i = 0; i < 4; i++) {
         stb_phys(bdloc + 0x38 + i, bd->bi_s_version[i]);
+    }
     for (i = 0; i < 32; i++) {
         stb_phys(bdloc + 0x3C + i, bd->bi_r_version[i]);
     }
-    stl_phys(bdloc + 0x5C, bd->bi_plb_busfreq);
-    stl_phys(bdloc + 0x60, bd->bi_pci_busfreq);
-    for (i = 0; i < 6; i++)
+    stl_be_phys(bdloc + 0x5C, bd->bi_plb_busfreq);
+    stl_be_phys(bdloc + 0x60, bd->bi_pci_busfreq);
+    for (i = 0; i < 6; i++) {
         stb_phys(bdloc + 0x64 + i, bd->bi_pci_enetaddr[i]);
+    }
     n = 0x6A;
     if (flags & 0x00000001) {
         for (i = 0; i < 6; i++)
             stb_phys(bdloc + n++, bd->bi_pci_enetaddr2[i]);
     }
-    stl_phys(bdloc + n, bd->bi_opbfreq);
+    stl_be_phys(bdloc + n, bd->bi_opbfreq);
     n += 4;
     for (i = 0; i < 2; i++) {
-        stl_phys(bdloc + n, bd->bi_iic_fast[i]);
+        stl_be_phys(bdloc + n, bd->bi_iic_fast[i]);
         n += 4;
     }
 
commit 75b0646f9e25e42cdf1d73f7d2407c4966be48f1
Author: Alexander Graf <agraf at suse.de>
Date:   Tue Jul 5 18:28:07 2011 +0200

    pl080: use specific endian ld/st_phys
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/pl080.c b/hw/pl080.c
index 901f04a..dd8139b 100644
--- a/hw/pl080.c
+++ b/hw/pl080.c
@@ -199,10 +199,10 @@ again:
             if (size == 0) {
                 /* Transfer complete.  */
                 if (ch->lli) {
-                    ch->src = ldl_phys(ch->lli);
-                    ch->dest = ldl_phys(ch->lli + 4);
-                    ch->ctrl = ldl_phys(ch->lli + 12);
-                    ch->lli = ldl_phys(ch->lli + 8);
+                    ch->src = ldl_le_phys(ch->lli);
+                    ch->dest = ldl_le_phys(ch->lli + 4);
+                    ch->ctrl = ldl_le_phys(ch->lli + 12);
+                    ch->lli = ldl_le_phys(ch->lli + 8);
                 } else {
                     ch->conf &= ~PL080_CCONF_E;
                 }
commit ae5d3eb4745dbcc38a4d6bbaff563f4c2d0e7a16
Author: Alexander Graf <agraf at suse.de>
Date:   Tue Jul 5 18:28:06 2011 +0200

    msix: use specific endian ld/st_phys
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/msix.c b/hw/msix.c
index 03d7bec..e67e700 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -359,7 +359,7 @@ void msix_notify(PCIDevice *dev, unsigned vector)
 
     address = pci_get_quad(table_entry + PCI_MSIX_ENTRY_LOWER_ADDR);
     data = pci_get_long(table_entry + PCI_MSIX_ENTRY_DATA);
-    stl_phys(address, data);
+    stl_le_phys(address, data);
 }
 
 void msix_reset(PCIDevice *dev)
commit c5d29d2fecff299d4b65bfd5546d58915d8e25e0
Author: Alexander Graf <agraf at suse.de>
Date:   Tue Jul 5 18:28:05 2011 +0200

    msi: use specific endian ld/st_phys
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/msi.c b/hw/msi.c
index e8c5607..f214fcf 100644
--- a/hw/msi.c
+++ b/hw/msi.c
@@ -249,7 +249,7 @@ void msi_notify(PCIDevice *dev, unsigned int vector)
                    "notify vector 0x%x"
                    " address: 0x%"PRIx64" data: 0x%"PRIx32"\n",
                    vector, address, data);
-    stl_phys(address, data);
+    stl_le_phys(address, data);
 }
 
 /* call this function after updating configs by pci_default_write_config(). */
commit 6c7796e5c17bc23d0add756b5248fcf419e999a9
Author: Alexander Graf <agraf at suse.de>
Date:   Tue Jul 5 18:28:04 2011 +0200

    intel-hda: use specific endian ld/st_phys
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/intel-hda.c b/hw/intel-hda.c
index 0ffffce..5a2bc3a 100644
--- a/hw/intel-hda.c
+++ b/hw/intel-hda.c
@@ -224,19 +224,6 @@ static target_phys_addr_t intel_hda_addr(uint32_t lbase, uint32_t ubase)
     return addr;
 }
 
-static void stl_phys_le(target_phys_addr_t addr, uint32_t value)
-{
-    uint32_t value_le = cpu_to_le32(value);
-    cpu_physical_memory_write(addr, (uint8_t*)(&value_le), sizeof(value_le));
-}
-
-static uint32_t ldl_phys_le(target_phys_addr_t addr)
-{
-    uint32_t value_le;
-    cpu_physical_memory_read(addr, (uint8_t*)(&value_le), sizeof(value_le));
-    return le32_to_cpu(value_le);
-}
-
 static void intel_hda_update_int_sts(IntelHDAState *d)
 {
     uint32_t sts = 0;
@@ -341,7 +328,7 @@ static void intel_hda_corb_run(IntelHDAState *d)
 
         rp = (d->corb_rp + 1) & 0xff;
         addr = intel_hda_addr(d->corb_lbase, d->corb_ubase);
-        verb = ldl_phys_le(addr + 4*rp);
+        verb = ldl_le_phys(addr + 4*rp);
         d->corb_rp = rp;
 
         dprint(d, 2, "%s: [rp 0x%x] verb 0x%08x\n", __FUNCTION__, rp, verb);
@@ -373,8 +360,8 @@ static void intel_hda_response(HDACodecDevice *dev, bool solicited, uint32_t res
     ex = (solicited ? 0 : (1 << 4)) | dev->cad;
     wp = (d->rirb_wp + 1) & 0xff;
     addr = intel_hda_addr(d->rirb_lbase, d->rirb_ubase);
-    stl_phys_le(addr + 8*wp, response);
-    stl_phys_le(addr + 8*wp + 4, ex);
+    stl_le_phys(addr + 8*wp, response);
+    stl_le_phys(addr + 8*wp + 4, ex);
     d->rirb_wp = wp;
 
     dprint(d, 2, "%s: [wp 0x%x] response 0x%x, extra 0x%x\n",
@@ -461,7 +448,7 @@ static bool intel_hda_xfer(HDACodecDevice *dev, uint32_t stnr, bool output,
     }
     if (d->dp_lbase & 0x01) {
         addr = intel_hda_addr(d->dp_lbase & ~0x01, d->dp_ubase);
-        stl_phys_le(addr + 8*s, st->lpib);
+        stl_le_phys(addr + 8*s, st->lpib);
     }
     dprint(d, 3, "dma: --\n");
 
commit 8517263fcbf2182ce97e3335f2a20b52d4e33fce
Author: Alexander Graf <agraf at suse.de>
Date:   Tue Jul 5 18:28:03 2011 +0200

    hpet: use specific endian ld/st_phys
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/hpet.c b/hw/hpet.c
index ef9a2a0..4eda33d 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -192,7 +192,7 @@ static void update_irq(struct HPETTimer *timer, int set)
             qemu_irq_lower(s->irqs[route]);
         }
     } else if (timer_fsb_route(timer)) {
-        stl_phys(timer->fsb >> 32, timer->fsb & 0xffffffff);
+        stl_le_phys(timer->fsb >> 32, timer->fsb & 0xffffffff);
     } else if (timer->config & HPET_TN_TYPE_LEVEL) {
         s->isr |= mask;
         qemu_irq_raise(s->irqs[route]);
commit 1e78bcc19c60c60c11ece020ab35952b5b2895ec
Author: Alexander Graf <agraf at suse.de>
Date:   Wed Jul 6 09:09:23 2011 +0200

    exec: add endian specific phys ld/st functions
    
    Device code some times needs to access physical memory and does that
    through the ld./st._phys functions. However, these are the exact same
    functions that the CPU uses to access memory, which means they will
    be endianness swapped depending on the target CPU.
    
    However, devices don't know about the CPU's endianness, but instead
    access memory directly using their own interface to the memory bus,
    so they need some way to read data with their native endianness.
    
    This patch adds _le and _be functions to ld./st._phys.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cpu-common.h b/cpu-common.h
index b027e43..c6a2b5f 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -135,14 +135,26 @@ void qemu_flush_coalesced_mmio_buffer(void);
 
 uint32_t ldub_phys(target_phys_addr_t addr);
 uint32_t lduw_phys(target_phys_addr_t addr);
+uint32_t lduw_le_phys(target_phys_addr_t addr);
+uint32_t lduw_be_phys(target_phys_addr_t addr);
 uint32_t ldl_phys(target_phys_addr_t addr);
+uint32_t ldl_le_phys(target_phys_addr_t addr);
+uint32_t ldl_be_phys(target_phys_addr_t addr);
 uint64_t ldq_phys(target_phys_addr_t addr);
+uint64_t ldq_le_phys(target_phys_addr_t addr);
+uint64_t ldq_be_phys(target_phys_addr_t addr);
 void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val);
 void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val);
 void stb_phys(target_phys_addr_t addr, uint32_t val);
 void stw_phys(target_phys_addr_t addr, uint32_t val);
+void stw_le_phys(target_phys_addr_t addr, uint32_t val);
+void stw_be_phys(target_phys_addr_t addr, uint32_t val);
 void stl_phys(target_phys_addr_t addr, uint32_t val);
+void stl_le_phys(target_phys_addr_t addr, uint32_t val);
+void stl_be_phys(target_phys_addr_t addr, uint32_t val);
 void stq_phys(target_phys_addr_t addr, uint64_t val);
+void stq_le_phys(target_phys_addr_t addr, uint64_t val);
+void stq_be_phys(target_phys_addr_t addr, uint64_t val);
 
 void cpu_physical_memory_write_rom(target_phys_addr_t addr,
                                    const uint8_t *buf, int len);
diff --git a/exec.c b/exec.c
index 4c45299..9e6913e 100644
--- a/exec.c
+++ b/exec.c
@@ -4127,7 +4127,8 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
 }
 
 /* warning: addr must be aligned */
-uint32_t ldl_phys(target_phys_addr_t addr)
+static inline uint32_t ldl_phys_internal(target_phys_addr_t addr,
+                                         enum device_endian endian)
 {
     int io_index;
     uint8_t *ptr;
@@ -4149,17 +4150,52 @@ uint32_t ldl_phys(target_phys_addr_t addr)
         if (p)
             addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
         val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
+#if defined(TARGET_WORDS_BIGENDIAN)
+        if (endian == DEVICE_LITTLE_ENDIAN) {
+            val = bswap32(val);
+        }
+#else
+        if (endian == DEVICE_BIG_ENDIAN) {
+            val = bswap32(val);
+        }
+#endif
     } else {
         /* RAM case */
         ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
             (addr & ~TARGET_PAGE_MASK);
-        val = ldl_p(ptr);
+        switch (endian) {
+        case DEVICE_LITTLE_ENDIAN:
+            val = ldl_le_p(ptr);
+            break;
+        case DEVICE_BIG_ENDIAN:
+            val = ldl_be_p(ptr);
+            break;
+        default:
+            val = ldl_p(ptr);
+            break;
+        }
     }
     return val;
 }
 
+uint32_t ldl_phys(target_phys_addr_t addr)
+{
+    return ldl_phys_internal(addr, DEVICE_NATIVE_ENDIAN);
+}
+
+uint32_t ldl_le_phys(target_phys_addr_t addr)
+{
+    return ldl_phys_internal(addr, DEVICE_LITTLE_ENDIAN);
+}
+
+uint32_t ldl_be_phys(target_phys_addr_t addr)
+{
+    return ldl_phys_internal(addr, DEVICE_BIG_ENDIAN);
+}
+
 /* warning: addr must be aligned */
-uint64_t ldq_phys(target_phys_addr_t addr)
+static inline uint64_t ldq_phys_internal(target_phys_addr_t addr,
+                                         enum device_endian endian)
 {
     int io_index;
     uint8_t *ptr;
@@ -4180,6 +4216,9 @@ uint64_t ldq_phys(target_phys_addr_t addr)
         io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
         if (p)
             addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
+
+        /* XXX This is broken when device endian != cpu endian.
+               Fix and add "endian" variable check */
 #ifdef TARGET_WORDS_BIGENDIAN
         val = (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr) << 32;
         val |= io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4);
@@ -4191,11 +4230,36 @@ uint64_t ldq_phys(target_phys_addr_t addr)
         /* RAM case */
         ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
             (addr & ~TARGET_PAGE_MASK);
-        val = ldq_p(ptr);
+        switch (endian) {
+        case DEVICE_LITTLE_ENDIAN:
+            val = ldq_le_p(ptr);
+            break;
+        case DEVICE_BIG_ENDIAN:
+            val = ldq_be_p(ptr);
+            break;
+        default:
+            val = ldq_p(ptr);
+            break;
+        }
     }
     return val;
 }
 
+uint64_t ldq_phys(target_phys_addr_t addr)
+{
+    return ldq_phys_internal(addr, DEVICE_NATIVE_ENDIAN);
+}
+
+uint64_t ldq_le_phys(target_phys_addr_t addr)
+{
+    return ldq_phys_internal(addr, DEVICE_LITTLE_ENDIAN);
+}
+
+uint64_t ldq_be_phys(target_phys_addr_t addr)
+{
+    return ldq_phys_internal(addr, DEVICE_BIG_ENDIAN);
+}
+
 /* XXX: optimize */
 uint32_t ldub_phys(target_phys_addr_t addr)
 {
@@ -4205,7 +4269,8 @@ uint32_t ldub_phys(target_phys_addr_t addr)
 }
 
 /* warning: addr must be aligned */
-uint32_t lduw_phys(target_phys_addr_t addr)
+static inline uint32_t lduw_phys_internal(target_phys_addr_t addr,
+                                          enum device_endian endian)
 {
     int io_index;
     uint8_t *ptr;
@@ -4227,15 +4292,49 @@ uint32_t lduw_phys(target_phys_addr_t addr)
         if (p)
             addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
         val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr);
+#if defined(TARGET_WORDS_BIGENDIAN)
+        if (endian == DEVICE_LITTLE_ENDIAN) {
+            val = bswap16(val);
+        }
+#else
+        if (endian == DEVICE_BIG_ENDIAN) {
+            val = bswap16(val);
+        }
+#endif
     } else {
         /* RAM case */
         ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
             (addr & ~TARGET_PAGE_MASK);
-        val = lduw_p(ptr);
+        switch (endian) {
+        case DEVICE_LITTLE_ENDIAN:
+            val = lduw_le_p(ptr);
+            break;
+        case DEVICE_BIG_ENDIAN:
+            val = lduw_be_p(ptr);
+            break;
+        default:
+            val = lduw_p(ptr);
+            break;
+        }
     }
     return val;
 }
 
+uint32_t lduw_phys(target_phys_addr_t addr)
+{
+    return lduw_phys_internal(addr, DEVICE_NATIVE_ENDIAN);
+}
+
+uint32_t lduw_le_phys(target_phys_addr_t addr)
+{
+    return lduw_phys_internal(addr, DEVICE_LITTLE_ENDIAN);
+}
+
+uint32_t lduw_be_phys(target_phys_addr_t addr)
+{
+    return lduw_phys_internal(addr, DEVICE_BIG_ENDIAN);
+}
+
 /* warning: addr must be aligned. The ram page is not masked as dirty
    and the code inside is not invalidated. It is useful if the dirty
    bits are used to track modified PTEs */
@@ -4308,7 +4407,8 @@ void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val)
 }
 
 /* warning: addr must be aligned */
-void stl_phys(target_phys_addr_t addr, uint32_t val)
+static inline void stl_phys_internal(target_phys_addr_t addr, uint32_t val,
+                                     enum device_endian endian)
 {
     int io_index;
     uint8_t *ptr;
@@ -4326,13 +4426,32 @@ void stl_phys(target_phys_addr_t addr, uint32_t val)
         io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
         if (p)
             addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
+#if defined(TARGET_WORDS_BIGENDIAN)
+        if (endian == DEVICE_LITTLE_ENDIAN) {
+            val = bswap32(val);
+        }
+#else
+        if (endian == DEVICE_BIG_ENDIAN) {
+            val = bswap32(val);
+        }
+#endif
         io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
     } else {
         unsigned long addr1;
         addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
         /* RAM case */
         ptr = qemu_get_ram_ptr(addr1);
-        stl_p(ptr, val);
+        switch (endian) {
+        case DEVICE_LITTLE_ENDIAN:
+            stl_le_p(ptr, val);
+            break;
+        case DEVICE_BIG_ENDIAN:
+            stl_be_p(ptr, val);
+            break;
+        default:
+            stl_p(ptr, val);
+            break;
+        }
         if (!cpu_physical_memory_is_dirty(addr1)) {
             /* invalidate code */
             tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
@@ -4343,6 +4462,21 @@ void stl_phys(target_phys_addr_t addr, uint32_t val)
     }
 }
 
+void stl_phys(target_phys_addr_t addr, uint32_t val)
+{
+    stl_phys_internal(addr, val, DEVICE_NATIVE_ENDIAN);
+}
+
+void stl_le_phys(target_phys_addr_t addr, uint32_t val)
+{
+    stl_phys_internal(addr, val, DEVICE_LITTLE_ENDIAN);
+}
+
+void stl_be_phys(target_phys_addr_t addr, uint32_t val)
+{
+    stl_phys_internal(addr, val, DEVICE_BIG_ENDIAN);
+}
+
 /* XXX: optimize */
 void stb_phys(target_phys_addr_t addr, uint32_t val)
 {
@@ -4351,7 +4485,8 @@ void stb_phys(target_phys_addr_t addr, uint32_t val)
 }
 
 /* warning: addr must be aligned */
-void stw_phys(target_phys_addr_t addr, uint32_t val)
+static inline void stw_phys_internal(target_phys_addr_t addr, uint32_t val,
+                                     enum device_endian endian)
 {
     int io_index;
     uint8_t *ptr;
@@ -4369,13 +4504,32 @@ void stw_phys(target_phys_addr_t addr, uint32_t val)
         io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
         if (p)
             addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
+#if defined(TARGET_WORDS_BIGENDIAN)
+        if (endian == DEVICE_LITTLE_ENDIAN) {
+            val = bswap16(val);
+        }
+#else
+        if (endian == DEVICE_BIG_ENDIAN) {
+            val = bswap16(val);
+        }
+#endif
         io_mem_write[io_index][1](io_mem_opaque[io_index], addr, val);
     } else {
         unsigned long addr1;
         addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
         /* RAM case */
         ptr = qemu_get_ram_ptr(addr1);
-        stw_p(ptr, val);
+        switch (endian) {
+        case DEVICE_LITTLE_ENDIAN:
+            stw_le_p(ptr, val);
+            break;
+        case DEVICE_BIG_ENDIAN:
+            stw_be_p(ptr, val);
+            break;
+        default:
+            stw_p(ptr, val);
+            break;
+        }
         if (!cpu_physical_memory_is_dirty(addr1)) {
             /* invalidate code */
             tb_invalidate_phys_page_range(addr1, addr1 + 2, 0);
@@ -4386,6 +4540,21 @@ void stw_phys(target_phys_addr_t addr, uint32_t val)
     }
 }
 
+void stw_phys(target_phys_addr_t addr, uint32_t val)
+{
+    stw_phys_internal(addr, val, DEVICE_NATIVE_ENDIAN);
+}
+
+void stw_le_phys(target_phys_addr_t addr, uint32_t val)
+{
+    stw_phys_internal(addr, val, DEVICE_LITTLE_ENDIAN);
+}
+
+void stw_be_phys(target_phys_addr_t addr, uint32_t val)
+{
+    stw_phys_internal(addr, val, DEVICE_BIG_ENDIAN);
+}
+
 /* XXX: optimize */
 void stq_phys(target_phys_addr_t addr, uint64_t val)
 {
@@ -4393,6 +4562,18 @@ void stq_phys(target_phys_addr_t addr, uint64_t val)
     cpu_physical_memory_write(addr, &val, 8);
 }
 
+void stq_le_phys(target_phys_addr_t addr, uint64_t val)
+{
+    val = cpu_to_le64(val);
+    cpu_physical_memory_write(addr, &val, 8);
+}
+
+void stq_be_phys(target_phys_addr_t addr, uint64_t val)
+{
+    val = cpu_to_be64(val);
+    cpu_physical_memory_write(addr, &val, 8);
+}
+
 /* virtual memory access for debug (includes writing to ROM) */
 int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
                         uint8_t *buf, int len, int is_write)
commit e22b7015353be824620b1f0f5e32a8575b898a8c
Author: Wesley W. Terpstra <terpstra at debian.org>
Date:   Tue Jul 12 14:42:00 2011 +0300

    mips: rlimit codes are not the same
    
    The codes for get/setrlimit differ between linux target platforms.
    This patch adds conversion.
    This is important else programs (rsyslog, python, ...) can go into a
    near infinite loop trying to close all the file descriptors from 0 to
    -1.
    
    Signed-off-by: Wesley W. Terpstra <terpstra at debian.org>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 4b9e3b8..9eb41a0 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -960,6 +960,44 @@ static inline target_ulong host_to_target_rlim(rlim_t rlim)
     return result;
 }
 
+static inline int target_to_host_resource(int code)
+{
+    switch (code) {
+    case TARGET_RLIMIT_AS:
+        return RLIMIT_AS;
+    case TARGET_RLIMIT_CORE:
+        return RLIMIT_CORE;
+    case TARGET_RLIMIT_CPU:
+        return RLIMIT_CPU;
+    case TARGET_RLIMIT_DATA:
+        return RLIMIT_DATA;
+    case TARGET_RLIMIT_FSIZE:
+        return RLIMIT_FSIZE;
+    case TARGET_RLIMIT_LOCKS:
+        return RLIMIT_LOCKS;
+    case TARGET_RLIMIT_MEMLOCK:
+        return RLIMIT_MEMLOCK;
+    case TARGET_RLIMIT_MSGQUEUE:
+        return RLIMIT_MSGQUEUE;
+    case TARGET_RLIMIT_NICE:
+        return RLIMIT_NICE;
+    case TARGET_RLIMIT_NOFILE:
+        return RLIMIT_NOFILE;
+    case TARGET_RLIMIT_NPROC:
+        return RLIMIT_NPROC;
+    case TARGET_RLIMIT_RSS:
+        return RLIMIT_RSS;
+    case TARGET_RLIMIT_RTPRIO:
+        return RLIMIT_RTPRIO;
+    case TARGET_RLIMIT_SIGPENDING:
+        return RLIMIT_SIGPENDING;
+    case TARGET_RLIMIT_STACK:
+        return RLIMIT_STACK;
+    default:
+        return code;
+    }
+}
+
 static inline abi_long copy_from_user_timeval(struct timeval *tv,
                                               abi_ulong target_tv_addr)
 {
@@ -5570,7 +5608,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         break;
     case TARGET_NR_setrlimit:
         {
-            int resource = arg1;
+            int resource = target_to_host_resource(arg1);
             struct target_rlimit *target_rlim;
             struct rlimit rlim;
             if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
@@ -5583,7 +5621,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         break;
     case TARGET_NR_getrlimit:
         {
-            int resource = arg1;
+            int resource = target_to_host_resource(arg1);
             struct target_rlimit *target_rlim;
             struct rlimit rlim;
 
@@ -6892,7 +6930,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
     case TARGET_NR_ugetrlimit:
     {
 	struct rlimit rlim;
-	ret = get_errno(getrlimit(arg1, &rlim));
+	int resource = target_to_host_resource(arg1);
+	ret = get_errno(getrlimit(resource, &rlim));
 	if (!is_error(ret)) {
 	    struct target_rlimit *target_rlim;
             if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 1fdc84d..a117407 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -693,6 +693,40 @@ struct target_rlimit {
 #define TARGET_RLIM_INFINITY	((target_ulong)~0UL)
 #endif
 
+#if defined(TARGET_MIPS)
+#define TARGET_RLIMIT_CPU		0
+#define TARGET_RLIMIT_FSIZE		1
+#define TARGET_RLIMIT_DATA		2
+#define TARGET_RLIMIT_STACK		3
+#define TARGET_RLIMIT_CORE		4
+#define TARGET_RLIMIT_RSS		7
+#define TARGET_RLIMIT_NPROC		8
+#define TARGET_RLIMIT_NOFILE		5
+#define TARGET_RLIMIT_MEMLOCK		9
+#define TARGET_RLIMIT_AS		6
+#define TARGET_RLIMIT_LOCKS		10
+#define TARGET_RLIMIT_SIGPENDING	11
+#define TARGET_RLIMIT_MSGQUEUE		12
+#define TARGET_RLIMIT_NICE		13
+#define TARGET_RLIMIT_RTPRIO		14
+#else
+#define TARGET_RLIMIT_CPU		0
+#define TARGET_RLIMIT_FSIZE		1
+#define TARGET_RLIMIT_DATA		2
+#define TARGET_RLIMIT_STACK		3
+#define TARGET_RLIMIT_CORE		4
+#define TARGET_RLIMIT_RSS		5
+#define TARGET_RLIMIT_NPROC		6
+#define TARGET_RLIMIT_NOFILE		7
+#define TARGET_RLIMIT_MEMLOCK		8
+#define TARGET_RLIMIT_AS		9
+#define TARGET_RLIMIT_LOCKS		10
+#define TARGET_RLIMIT_SIGPENDING	11
+#define TARGET_RLIMIT_MSGQUEUE		12
+#define TARGET_RLIMIT_NICE		13
+#define TARGET_RLIMIT_RTPRIO		14
+#endif
+
 struct target_pollfd {
     int fd;           /* file descriptor */
     short events;     /* requested events */
commit 95b33b2f4f0293068d1a42b3ab5badcc6333c6ba
Author: Wesley W. Terpstra <terpstra at debian.org>
Date:   Tue Jul 12 14:38:22 2011 +0300

    mips: rlimit incorrectly converts values
    
    Byte swap was applied in the wrong order with testing for
    RLIM_INFINITY. On mips bigendian from an amd64 system this results in
    infinity being misinterpretted as 2^31-1.
    
    This is a serious bug because it causes setrlimit stack size to kill
    all child processes. This means (for example) that 'make' can run no
    children. The mechanism of failure:
    1. parent sets stack size rlimit to 'infinity'
    2. qemu screws this value up
    3. child process fetches stack size as a large (but non-infinite) value
    4. qemu tries to allocate stack before execution
    5. stack allocation fails (too big) and child process dies
    
    Signed-off-by: Wesley W. Terpstra <terpstra at debian.org>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 90f6789..4b9e3b8 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -934,18 +934,30 @@ static inline abi_long host_to_target_rusage(abi_ulong target_addr,
 
 static inline rlim_t target_to_host_rlim(target_ulong target_rlim)
 {
-    if (target_rlim == TARGET_RLIM_INFINITY)
-        return RLIM_INFINITY;
+    target_ulong target_rlim_swap;
+    rlim_t result;
+    
+    target_rlim_swap = tswapl(target_rlim);
+    if (target_rlim_swap == TARGET_RLIM_INFINITY || target_rlim_swap != (rlim_t)target_rlim_swap)
+        result = RLIM_INFINITY;
     else
-        return tswapl(target_rlim);
+        result = target_rlim_swap;
+    
+    return result;
 }
 
 static inline target_ulong host_to_target_rlim(rlim_t rlim)
 {
+    target_ulong target_rlim_swap;
+    target_ulong result;
+    
     if (rlim == RLIM_INFINITY || rlim != (target_long)rlim)
-        return TARGET_RLIM_INFINITY;
+        target_rlim_swap = TARGET_RLIM_INFINITY;
     else
-        return tswapl(rlim);
+        target_rlim_swap = rlim;
+    result = tswapl(target_rlim_swap);
+    
+    return result;
 }
 
 static inline abi_long copy_from_user_timeval(struct timeval *tv,
commit e6e5bd2dd1868b5a244bc572422f585cef579ffb
Author: Wesley W. Terpstra <terpstra at debian.org>
Date:   Tue Jul 12 14:34:23 2011 +0300

    mips: null pointer deref should segfault
    
    Dereferencing a null pointer causes an exception 0xC (EXCP_AdEL)
    instead of EXCP_TLBL. This should also trigger a segfault.
    
    Signed-off-by: Wesley W. Terpstra <terpstra at debian.org>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/main.c b/linux-user/main.c
index e32f987..2135b9c 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2120,6 +2120,8 @@ void cpu_loop(CPUMIPSState *env)
             break;
         case EXCP_TLBL:
         case EXCP_TLBS:
+        case EXCP_AdEL:
+        case EXCP_AdES:
             info.si_signo = TARGET_SIGSEGV;
             info.si_errno = 0;
             /* XXX: check env->error_code */
commit 7c2f6157d833cb95b355c7321597bc5a5ac976e4
Author: Wesley W. Terpstra <terpstra at debian.org>
Date:   Tue Jul 12 14:33:23 2011 +0300

    mips: missing syscall returns wrong errno
    
    Return -TARGET_ENOSYS instead of -ENOSYS from linux-user/main.c
       * Caused strange 'Level 2 synchronization messages' instead of
    correctly reporting the syscall was missing.
       * Made glibc simply fail instead of using older syscalls
    
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>
    Signed-off-by: Wesley W. Terpstra <terpstra at debian.org>

diff --git a/linux-user/main.c b/linux-user/main.c
index d695610..e32f987 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2080,7 +2080,7 @@ void cpu_loop(CPUMIPSState *env)
             syscall_num = env->active_tc.gpr[2] - 4000;
             env->active_tc.PC += 4;
             if (syscall_num >= sizeof(mips_syscall_args)) {
-                ret = -ENOSYS;
+                ret = -TARGET_ENOSYS;
             } else {
                 int nb_args;
                 abi_ulong sp_reg;
commit 053ebb2726c17af6133cfcc8de2193121a107eb5
Author: Wesley W. Terpstra <terpstra at debian.org>
Date:   Tue Jul 12 14:32:31 2011 +0300

    mips: sigaltstack args
    
    The syscall sigaltstack takes two parameters, not zero. This patch
    should have no impact as only values above 4 influence the runtime
    behaviour. Nevertheless, it is wrong.
    
    Signed-off-by: Wesley W. Terpstra <terpstra at debian.org>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/main.c b/linux-user/main.c
index 48f0443..d695610 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -1875,7 +1875,7 @@ static const uint8_t mips_syscall_args[] = {
 	MIPS_SYS(sys_getcwd	, 2)
 	MIPS_SYS(sys_capget	, 2)
 	MIPS_SYS(sys_capset	, 2)	/* 4205 */
-	MIPS_SYS(sys_sigaltstack	, 0)
+	MIPS_SYS(sys_sigaltstack	, 2)
 	MIPS_SYS(sys_sendfile	, 4)
 	MIPS_SYS(sys_ni_syscall	, 0)
 	MIPS_SYS(sys_ni_syscall	, 0)
commit 8f04eeb3c094bf370f131e50b7e3da85d08d518f
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Jun 28 12:21:57 2011 +0100

    linux-user/syscall.c: Enforce pselect6 sigset size restrictions
    
    Enforce the same restriction on the size of the sigset passed to
    pselect6 as the Linux kernel does. This is both correct and silences
    a gcc 4.6 warning about a write-only variable.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index e2f356b..90f6789 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5699,6 +5699,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 
                 if (arg_sigset) {
                     sig.set = &set;
+                    if (arg_sigsize != sizeof(*target_sigset)) {
+                        /* Like the kernel, we enforce correct size sigsets */
+                        ret = -TARGET_EINVAL;
+                        goto fail;
+                    }
                     target_sigset = lock_user(VERIFY_READ, arg_sigset,
                                               sizeof(*target_sigset), 1);
                     if (!target_sigset) {
commit 163a05a8398bc4b56c7498fa9901422a159168bf
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Jun 27 17:44:52 2011 +0100

    linux-user: Implement prlimit64 syscall
    
    Implement the prlimit64 syscall.
    
    Slightly modified to apply upstream -Riku
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index fed7a8f..e2f356b 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -559,6 +559,21 @@ _syscall6(int, sys_pselect6, int, nfds, fd_set *, readfds, fd_set *, writefds,
           fd_set *, exceptfds, struct timespec *, timeout, void *, sig);
 #endif
 
+#if defined(TARGET_NR_prlimit64)
+#ifndef __NR_prlimit64
+# define __NR_prlimit64 -1
+#endif
+#define __NR_sys_prlimit64 __NR_prlimit64
+/* The glibc rlimit structure may not be that used by the underlying syscall */
+struct host_rlimit64 {
+    uint64_t rlim_cur;
+    uint64_t rlim_max;
+};
+_syscall4(int, sys_prlimit64, pid_t, pid, int, resource,
+          const struct host_rlimit64 *, new_limit,
+          struct host_rlimit64 *, old_limit)
+#endif
+
 extern int personality(int);
 extern int flock(int, int);
 extern int setfsuid(int);
@@ -7990,6 +8005,34 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
     }
 #endif
 #endif
+#ifdef TARGET_NR_prlimit64
+    case TARGET_NR_prlimit64:
+    {
+        /* args: pid, resource number, ptr to new rlimit, ptr to old rlimit */
+        struct target_rlimit64 *target_rnew, *target_rold;
+        struct host_rlimit64 rnew, rold, *rnewp = 0;
+        if (arg3) {
+            if (!lock_user_struct(VERIFY_READ, target_rnew, arg3, 1)) {
+                goto efault;
+            }
+            rnew.rlim_cur = tswap64(target_rnew->rlim_cur);
+            rnew.rlim_max = tswap64(target_rnew->rlim_max);
+            unlock_user_struct(target_rnew, arg3, 0);
+            rnewp = &rnew;
+        }
+
+        ret = get_errno(sys_prlimit64(arg1, arg2, rnewp, arg4 ? &rold : 0));
+        if (!is_error(ret) && arg4) {
+            if (!lock_user_struct(VERIFY_WRITE, target_rold, arg4, 1)) {
+                goto efault;
+            }
+            target_rold->rlim_cur = tswap64(rold.rlim_cur);
+            target_rold->rlim_max = tswap64(rold.rlim_max);
+            unlock_user_struct(target_rold, arg4, 1);
+        }
+        break;
+    }
+#endif
     default:
     unimplemented:
         gemu_log("qemu: Unsupported syscall: %d\n", num);
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 1b73451..1fdc84d 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -2293,3 +2293,7 @@ struct target_epoll_event {
     target_epoll_data_t data;
 };
 #endif
+struct target_rlimit64 {
+    uint64_t rlim_cur;
+    uint64_t rlim_max;
+};
commit d979e8eb544da31df78bc76358a73f0d1c823c17
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Jun 27 17:44:51 2011 +0100

    linux-user: Add syscall numbers from kernel 2.6.39.2
    
    Add syscall numbers for new syscall numbers; this brings us
    into line with Linux 2.6.39.2.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/alpha/syscall_nr.h b/linux-user/alpha/syscall_nr.h
index e3127df..f6284db 100644
--- a/linux-user/alpha/syscall_nr.h
+++ b/linux-user/alpha/syscall_nr.h
@@ -411,4 +411,25 @@
 #define TARGET_NR_signalfd			476
 #define TARGET_NR_timerfd			477
 #define TARGET_NR_eventfd			478
-
+#define TARGET_NR_recvmmsg                      479
+#define TARGET_NR_fallocate                     480
+#define TARGET_NR_timerfd_create                481
+#define TARGET_NR_timerfd_settime               482
+#define TARGET_NR_timerfd_gettime               483
+#define TARGET_NR_signalfd4                     484
+#define TARGET_NR_eventfd2                      485
+#define TARGET_NR_epoll_create1                 486
+#define TARGET_NR_dup3                          487
+#define TARGET_NR_pipe2                         488
+#define TARGET_NR_inotify_init1                 489
+#define TARGET_NR_preadv                        490
+#define TARGET_NR_pwritev                       491
+#define TARGET_NR_rt_tgsigqueueinfo             492
+#define TARGET_NR_perf_event_open               493
+#define TARGET_NR_fanotify_init                 494
+#define TARGET_NR_fanotify_mark                 495
+#define TARGET_NR_prlimit64                     496
+#define TARGET_NR_name_to_handle_at             497
+#define TARGET_NR_open_by_handle_at             498
+#define TARGET_NR_clock_adjtime                 499
+#define TARGET_NR_syncfs                        500
diff --git a/linux-user/arm/syscall_nr.h b/linux-user/arm/syscall_nr.h
index 79a216a..7f05879 100644
--- a/linux-user/arm/syscall_nr.h
+++ b/linux-user/arm/syscall_nr.h
@@ -365,3 +365,16 @@
 #define TARGET_NR_dup3				(358)
 #define TARGET_NR_pipe2			(359)
 #define TARGET_NR_inotify_init1		(360)
+#define TARGET_NR_preadv                       (361)
+#define TARGET_NR_pwritev                      (362)
+#define TARGET_NR_rt_tgsigqueueinfo            (363)
+#define TARGET_NR_perf_event_open              (364)
+#define TARGET_NR_recvmmsg                     (365)
+#define TARGET_NR_accept4                      (366)
+#define TARGET_NR_fanotify_init                (367)
+#define TARGET_NR_fanotify_mark                (368)
+#define TARGET_NR_prlimit64                    (369)
+#define TARGET_NR_name_to_handle_at            (370)
+#define TARGET_NR_open_by_handle_at            (371)
+#define TARGET_NR_clock_adjtime                (372)
+#define TARGET_NR_syncfs                       (373)
diff --git a/linux-user/cris/syscall_nr.h b/linux-user/cris/syscall_nr.h
index 6132817..98f1a0b 100644
--- a/linux-user/cris/syscall_nr.h
+++ b/linux-user/cris/syscall_nr.h
@@ -333,3 +333,5 @@
 #define TARGET_NR_dup3               330
 #define TARGET_NR_pipe2              331
 #define TARGET_NR_inotify_init1      332
+#define TARGET_NR_preadv             333
+#define TARGET_NR_pwritev            334
diff --git a/linux-user/i386/syscall_nr.h b/linux-user/i386/syscall_nr.h
index 3ef71ce..74abfca 100644
--- a/linux-user/i386/syscall_nr.h
+++ b/linux-user/i386/syscall_nr.h
@@ -335,3 +335,15 @@
 #define TARGET_NR_dup3			330
 #define TARGET_NR_pipe2		331
 #define TARGET_NR_inotify_init1	332
+#define TARGET_NR_preadv                333
+#define TARGET_NR_pwritev               334
+#define TARGET_NR_rt_tgsigqueueinfo     335
+#define TARGET_NR_perf_event_open       336
+#define TARGET_NR_recvmmsg              337
+#define TARGET_NR_fanotify_init         338
+#define TARGET_NR_fanotify_mark         339
+#define TARGET_NR_prlimit64             340
+#define TARGET_NR_name_to_handle_at     341
+#define TARGET_NR_open_by_handle_at     342
+#define TARGET_NR_clock_adjtime         343
+#define TARGET_NR_syncfs                344
diff --git a/linux-user/m68k/syscall_nr.h b/linux-user/m68k/syscall_nr.h
index 1c0ba07..4d0937e 100644
--- a/linux-user/m68k/syscall_nr.h
+++ b/linux-user/m68k/syscall_nr.h
@@ -328,3 +328,19 @@
 #define TARGET_NR_dup3			326
 #define TARGET_NR_pipe2		327
 #define TARGET_NR_inotify_init1	328
+#define TARGET_NR_inotify_init1         328
+#define TARGET_NR_preadv                329
+#define TARGET_NR_pwritev               330
+#define TARGET_NR_rt_tgsigqueueinfo     331
+#define TARGET_NR_perf_event_open       332
+#define TARGET_NR_get_thread_area       333
+#define TARGET_NR_set_thread_area       334
+#define TARGET_NR_atomic_cmpxchg_32     335
+#define TARGET_NR_atomic_barrier        336
+#define TARGET_NR_fanotify_init         337
+#define TARGET_NR_fanotify_mark         338
+#define TARGET_NR_prlimit64             339
+#define TARGET_NR_name_to_handle_at     340
+#define TARGET_NR_open_by_handle_at     341
+#define TARGET_NR_clock_adjtime         342
+#define TARGET_NR_syncfs                343
diff --git a/linux-user/main.c b/linux-user/main.c
index 289054b..48f0443 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -1985,6 +1985,33 @@ static const uint8_t mips_syscall_args[] = {
 	MIPS_SYS(sys_epoll_pwait, 6)
 	MIPS_SYS(sys_ioprio_set, 3)
 	MIPS_SYS(sys_ioprio_get, 2)
+        MIPS_SYS(sys_utimensat, 4)
+        MIPS_SYS(sys_signalfd, 3)
+        MIPS_SYS(sys_ni_syscall, 0)     /* was timerfd */
+        MIPS_SYS(sys_eventfd, 1)
+        MIPS_SYS(sys_fallocate, 6)      /* 4320 */
+        MIPS_SYS(sys_timerfd_create, 2)
+        MIPS_SYS(sys_timerfd_gettime, 2)
+        MIPS_SYS(sys_timerfd_settime, 4)
+        MIPS_SYS(sys_signalfd4, 4)
+        MIPS_SYS(sys_eventfd2, 2)       /* 4325 */
+        MIPS_SYS(sys_epoll_create1, 1)
+        MIPS_SYS(sys_dup3, 3)
+        MIPS_SYS(sys_pipe2, 2)
+        MIPS_SYS(sys_inotify_init1, 1)
+        MIPS_SYS(sys_preadv, 6)         /* 4330 */
+        MIPS_SYS(sys_pwritev, 6)
+        MIPS_SYS(sys_rt_tgsigqueueinfo, 4)
+        MIPS_SYS(sys_perf_event_open, 5)
+        MIPS_SYS(sys_accept4, 4)
+        MIPS_SYS(sys_recvmmsg, 5)       /* 4335 */
+        MIPS_SYS(sys_fanotify_init, 2)
+        MIPS_SYS(sys_fanotify_mark, 6)
+        MIPS_SYS(sys_prlimit64, 4)
+        MIPS_SYS(sys_name_to_handle_at, 5)
+        MIPS_SYS(sys_open_by_handle_at, 3) /* 4340 */
+        MIPS_SYS(sys_clock_adjtime, 2)
+        MIPS_SYS(sys_syncfs, 1)
 };
 
 #undef MIPS_SYS
diff --git a/linux-user/microblaze/syscall_nr.h b/linux-user/microblaze/syscall_nr.h
index 3e641cd..f1fe0e7 100644
--- a/linux-user/microblaze/syscall_nr.h
+++ b/linux-user/microblaze/syscall_nr.h
@@ -364,6 +364,16 @@
 #define TARGET_NR_sendmsg		360 /* new */
 #define TARGET_NR_recvmsg		361 /* new */
 #define TARGET_NR_accept04		362 /* new */
-
-#define TARGET_NR_syscalls		363
+#define TARGET_NR_preadv                363 /* new */
+#define TARGET_NR_pwritev               364 /* new */
+#define TARGET_NR_rt_tgsigqueueinfo     365 /* new */
+#define TARGET_NR_perf_event_open       366 /* new */
+#define TARGET_NR_recvmmsg              367 /* new */
+#define TARGET_NR_fanotify_init         368
+#define TARGET_NR_fanotify_mark         369
+#define TARGET_NR_prlimit64             370
+#define TARGET_NR_name_to_handle_at     371
+#define TARGET_NR_open_by_handle_at     372
+#define TARGET_NR_clock_adjtime         373
+#define TARGET_NR_syncfs                374
 
diff --git a/linux-user/mips/syscall_nr.h b/linux-user/mips/syscall_nr.h
index 0595308..fbdc348 100644
--- a/linux-user/mips/syscall_nr.h
+++ b/linux-user/mips/syscall_nr.h
@@ -332,3 +332,16 @@
 #define TARGET_NR_dup3			(TARGET_NR_Linux + 327)
 #define TARGET_NR_pipe2		(TARGET_NR_Linux + 328)
 #define TARGET_NR_inotify_init1	(TARGET_NR_Linux + 329)
+#define TARGET_NR_preadv                (TARGET_NR_Linux + 330)
+#define TARGET_NR_pwritev               (TARGET_NR_Linux + 331)
+#define TARGET_NR_rt_tgsigqueueinfo     (TARGET_NR_Linux + 332)
+#define TARGET_NR_perf_event_open       (TARGET_NR_Linux + 333)
+#define TARGET_NR_accept4               (TARGET_NR_Linux + 334)
+#define TARGET_NR_recvmmsg              (TARGET_NR_Linux + 335)
+#define TARGET_NR_fanotify_init         (TARGET_NR_Linux + 336)
+#define TARGET_NR_fanotify_mark         (TARGET_NR_Linux + 337)
+#define TARGET_NR_prlimit64             (TARGET_NR_Linux + 338)
+#define TARGET_NR_name_to_handle_at     (TARGET_NR_Linux + 339)
+#define TARGET_NR_open_by_handle_at     (TARGET_NR_Linux + 340)
+#define TARGET_NR_clock_adjtime         (TARGET_NR_Linux + 341)
+#define TARGET_NR_syncfs                (TARGET_NR_Linux + 342)
diff --git a/linux-user/mips64/syscall_nr.h b/linux-user/mips64/syscall_nr.h
index ee1d134..36d27b5 100644
--- a/linux-user/mips64/syscall_nr.h
+++ b/linux-user/mips64/syscall_nr.h
@@ -291,3 +291,16 @@
 #define TARGET_NR_dup3				(TARGET_NR_Linux + 286)
 #define TARGET_NR_pipe2			(TARGET_NR_Linux + 287)
 #define TARGET_NR_inotify_init1		(TARGET_NR_Linux + 288)
+#define TARGET_NR_preadv                        (TARGET_NR_Linux + 289)
+#define TARGET_NR_pwritev                       (TARGET_NR_Linux + 290)
+#define TARGET_NR_rt_tgsigqueueinfo             (TARGET_NR_Linux + 291)
+#define TARGET_NR_perf_event_open               (TARGET_NR_Linux + 292)
+#define TARGET_NR_accept4                       (TARGET_NR_Linux + 293)
+#define TARGET_NR_recvmmsg                      (TARGET_NR_Linux + 294)
+#define TARGET_NR_fanotify_init                 (TARGET_NR_Linux + 295)
+#define TARGET_NR_fanotify_mark                 (TARGET_NR_Linux + 296)
+#define TARGET_NR_prlimit64                     (TARGET_NR_Linux + 297)
+#define TARGET_NR_name_to_handle_at             (TARGET_NR_Linux + 298)
+#define TARGET_NR_open_by_handle_at             (TARGET_NR_Linux + 299)
+#define TARGET_NR_clock_adjtime                 (TARGET_NR_Linux + 300)
+#define TARGET_NR_syncfs                        (TARGET_NR_Linux + 301)
diff --git a/linux-user/mipsn32/syscall_nr.h b/linux-user/mipsn32/syscall_nr.h
index 60a99dd..4e1aca3 100644
--- a/linux-user/mipsn32/syscall_nr.h
+++ b/linux-user/mipsn32/syscall_nr.h
@@ -295,3 +295,17 @@
 #define TARGET_NR_dup3				(TARGET_NR_Linux + 290)
 #define TARGET_NR_pipe2			(TARGET_NR_Linux + 291)
 #define TARGET_NR_inotify_init1		(TARGET_NR_Linux + 292)
+#define TARGET_NR_preadv                        (TARGET_NR_Linux + 293)
+#define TARGET_NR_pwritev                       (TARGET_NR_Linux + 294)
+#define TARGET_NR_rt_tgsigqueueinfo             (TARGET_NR_Linux + 295)
+#define TARGET_NR_perf_event_open               (TARGET_NR_Linux + 296)
+#define TARGET_NR_accept4                       (TARGET_NR_Linux + 297)
+#define TARGET_NR_recvmmsg                      (TARGET_NR_Linux + 298)
+#define TARGET_NR_getdents64                    (TARGET_NR_Linux + 299)
+#define TARGET_NR_fanotify_init                 (TARGET_NR_Linux + 300)
+#define TARGET_NR_fanotify_mark                 (TARGET_NR_Linux + 301)
+#define TARGET_NR_prlimit64                     (TARGET_NR_Linux + 302)
+#define TARGET_NR_name_to_handle_at             (TARGET_NR_Linux + 303)
+#define TARGET_NR_open_by_handle_at             (TARGET_NR_Linux + 304)
+#define TARGET_NR_clock_adjtime                 (TARGET_NR_Linux + 305)
+#define TARGET_NR_syncfs                        (TARGET_NR_Linux + 306)
diff --git a/linux-user/ppc/syscall_nr.h b/linux-user/ppc/syscall_nr.h
index cc84a4c..0673b7d 100644
--- a/linux-user/ppc/syscall_nr.h
+++ b/linux-user/ppc/syscall_nr.h
@@ -332,3 +332,33 @@
 #define TARGET_NR_dup3			316
 #define TARGET_NR_pipe2		317
 #define TARGET_NR_inotify_init1	318
+#define TARGET_NR_perf_event_open       319
+#define TARGET_NR_preadv                320
+#define TARGET_NR_pwritev               321
+#define TARGET_NR_rt_tgsigqueueinfo     322
+#define TARGET_NR_fanotify_init         323
+#define TARGET_NR_fanotify_mark         324
+#define TARGET_NR_prlimit64             325
+#define TARGET_NR_socket                326
+#define TARGET_NR_bind                  327
+#define TARGET_NR_connect               328
+#define TARGET_NR_listen                329
+#define TARGET_NR_accept                330
+#define TARGET_NR_getsockname           331
+#define TARGET_NR_getpeername           332
+#define TARGET_NR_socketpair            333
+#define TARGET_NR_send                  334
+#define TARGET_NR_sendto                335
+#define TARGET_NR_recv                  336
+#define TARGET_NR_recvfrom              337
+#define TARGET_NR_shutdown              338
+#define TARGET_NR_setsockopt            339
+#define TARGET_NR_getsockopt            340
+#define TARGET_NR_sendmsg               341
+#define TARGET_NR_recvmsg               342
+#define TARGET_NR_recvmmsg              343
+#define TARGET_NR_accept4               344
+#define TARGET_NR_name_to_handle_at     345
+#define TARGET_NR_open_by_handle_at     346
+#define TARGET_NR_clock_adjtime         347
+#define TARGET_NR_syncfs                348
diff --git a/linux-user/s390x/syscall_nr.h b/linux-user/s390x/syscall_nr.h
index 7cc6db2..d4529ac 100644
--- a/linux-user/s390x/syscall_nr.h
+++ b/linux-user/s390x/syscall_nr.h
@@ -254,8 +254,17 @@
 #define TARGET_NR_pipe2		325
 #define TARGET_NR_dup3		326
 #define TARGET_NR_epoll_create1	327
-#undef NR_syscalls
-#define NR_syscalls 328
+#define TARGET_NR_preadv                328
+#define TARGET_NR_pwritev               329
+#define TARGET_NR_rt_tgsigqueueinfo     330
+#define TARGET_NR_perf_event_open       331
+#define TARGET_NR_fanotify_init         332
+#define TARGET_NR_fanotify_mark         333
+#define TARGET_NR_prlimit64             334
+#define TARGET_NR_name_to_handle_at     335
+#define TARGET_NR_open_by_handle_at     336
+#define TARGET_NR_clock_adjtime         337
+#define TARGET_NR_syncfs                338
 
 /*
  * There are some system calls that are not present on 64 bit, some
diff --git a/linux-user/sh4/syscall_nr.h b/linux-user/sh4/syscall_nr.h
index 262b236..6173a7c 100644
--- a/linux-user/sh4/syscall_nr.h
+++ b/linux-user/sh4/syscall_nr.h
@@ -334,3 +334,35 @@
 #define TARGET_NR_dup3			330
 #define TARGET_NR_pipe2		331
 #define TARGET_NR_inotify_init1	332
+#define TARGET_NR_preadv                333
+#define TARGET_NR_pwritev               334
+#define TARGET_NR_rt_tgsigqueueinfo     335
+#define TARGET_NR_perf_event_open       336
+#define TARGET_NR_fanotify_init         337
+#define TARGET_NR_fanotify_mark         338
+#define TARGET_NR_prlimit64             339
+
+/* Non-multiplexed socket family */
+#define TARGET_NR_socket                340
+#define TARGET_NR_bind                  341
+#define TARGET_NR_connect               342
+#define TARGET_NR_listen                343
+#define TARGET_NR_accept                344
+#define TARGET_NR_getsockname           345
+#define TARGET_NR_getpeername           346
+#define TARGET_NR_socketpair            347
+#define TARGET_NR_send                  348
+#define TARGET_NR_sendto                349
+#define TARGET_NR_recv                  350
+#define TARGET_NR_recvfrom              351
+#define TARGET_NR_shutdown              352
+#define TARGET_NR_setsockopt            353
+#define TARGET_NR_getsockopt            354
+#define TARGET_NR_sendmsg               355
+#define TARGET_NR_recvmsg               356
+#define TARGET_NR_recvmmsg              357
+#define TARGET_NR_accept4               358
+#define TARGET_NR_name_to_handle_at     359
+#define TARGET_NR_open_by_handle_at     360
+#define TARGET_NR_clock_adjtime         361
+#define TARGET_NR_syncfs                362
diff --git a/linux-user/sparc/syscall_nr.h b/linux-user/sparc/syscall_nr.h
index 5d1ac21..be503f2 100644
--- a/linux-user/sparc/syscall_nr.h
+++ b/linux-user/sparc/syscall_nr.h
@@ -285,3 +285,15 @@
 #define TARGET_NR_pipe2		321
 #define TARGET_NR_inotify_init1	322
 #define TARGET_NR_accept4		323
+#define TARGET_NR_preadv                324
+#define TARGET_NR_pwritev               325
+#define TARGET_NR_rt_tgsigqueueinfo     326
+#define TARGET_NR_perf_event_open       327
+#define TARGET_NR_recvmmsg              328
+#define TARGET_NR_fanotify_init         329
+#define TARGET_NR_fanotify_mark         330
+#define TARGET_NR_prlimit64             331
+#define TARGET_NR_name_to_handle_at     332
+#define TARGET_NR_open_by_handle_at     333
+#define TARGET_NR_clock_adjtime         334
+#define TARGET_NR_syncfs                335
diff --git a/linux-user/sparc64/syscall_nr.h b/linux-user/sparc64/syscall_nr.h
index bdca2a7..70988b2 100644
--- a/linux-user/sparc64/syscall_nr.h
+++ b/linux-user/sparc64/syscall_nr.h
@@ -322,3 +322,15 @@
 #define TARGET_NR_pipe2		321
 #define TARGET_NR_inotify_init1	322
 #define TARGET_NR_accept4		323
+#define TARGET_NR_preadv                324
+#define TARGET_NR_pwritev               325
+#define TARGET_NR_rt_tgsigqueueinfo     326
+#define TARGET_NR_perf_event_open       327
+#define TARGET_NR_recvmmsg              328
+#define TARGET_NR_fanotify_init         329
+#define TARGET_NR_fanotify_mark         330
+#define TARGET_NR_prlimit64             331
+#define TARGET_NR_name_to_handle_at     332
+#define TARGET_NR_open_by_handle_at     333
+#define TARGET_NR_clock_adjtime         334
+#define TARGET_NR_syncfs                335
diff --git a/linux-user/x86_64/syscall_nr.h b/linux-user/x86_64/syscall_nr.h
index 568a901..947e961 100644
--- a/linux-user/x86_64/syscall_nr.h
+++ b/linux-user/x86_64/syscall_nr.h
@@ -293,3 +293,15 @@
 #define TARGET_NR_dup3			292
 #define TARGET_NR_pipe2		293
 #define TARGET_NR_inotify_init1	294
+#define TARGET_NR_preadv                295
+#define TARGET_NR_pwritev               296
+#define TARGET_NR_rt_tgsigqueueinfo     297
+#define TARGET_NR_perf_event_open       298
+#define TARGET_NR_recvmmsg              299
+#define TARGET_NR_fanotify_init         300
+#define TARGET_NR_fanotify_mark         301
+#define TARGET_NR_prlimit64             302
+#define TARGET_NR_name_to_handle_at     303
+#define TARGET_NR_open_by_handle_at     304
+#define TARGET_NR_clock_adjtime         305
+#define TARGET_NR_syncfs                306
commit 12b81b7145ec28a3c608d1eee5abcd5cdd6a677b
Author: Cédric VINCENT <cedric.vincent at st.com>
Date:   Wed Jun 29 15:09:11 2011 +0200

    linux-user: Add support for even more FB ioctls
    
    This patch was validated with programs from DirectFB-1.0 and
    WebKit/DirectFB.
    
    Signed-off-by: Cédric VINCENT <cedric.vincent at st.com>
    Cc: Riku Voipio <riku.voipio at iki.fi>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index 7bc1c48..6514502 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -329,6 +329,11 @@
   IOCTL(FBIOGET_FSCREENINFO, IOC_R, MK_PTR(MK_STRUCT(STRUCT_fb_fix_screeninfo)))
   IOCTL(FBIOGET_VSCREENINFO, IOC_R, MK_PTR(MK_STRUCT(STRUCT_fb_var_screeninfo)))
   IOCTL(FBIOPUT_VSCREENINFO, IOC_W, MK_PTR(MK_STRUCT(STRUCT_fb_var_screeninfo)))
+  IOCTL(FBIOGETCMAP,        IOC_RW, MK_PTR(MK_STRUCT(STRUCT_fb_cmap)))
+  IOCTL(FBIOPUTCMAP,        IOC_RW, MK_PTR(MK_STRUCT(STRUCT_fb_cmap)))
+  IOCTL(FBIOPAN_DISPLAY,    IOC_RW, MK_PTR(MK_STRUCT(STRUCT_fb_var_screeninfo)))
+  IOCTL(FBIOGET_CON2FBMAP,  IOC_RW, MK_PTR(MK_STRUCT(STRUCT_fb_con2fbmap)))
+  IOCTL(FBIOPUT_CON2FBMAP,  IOC_RW, MK_PTR(MK_STRUCT(STRUCT_fb_con2fbmap)))
 
   IOCTL(VT_OPENQRY, IOC_R, MK_PTR(TYPE_INT))
   IOCTL(VT_GETSTATE, IOC_R, MK_PTR(MK_STRUCT(STRUCT_vt_stat)))
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 4a59b36..1b73451 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -932,6 +932,11 @@ struct target_pollfd {
 #define TARGET_FBIOGET_VSCREENINFO    0x4600
 #define TARGET_FBIOPUT_VSCREENINFO    0x4601
 #define TARGET_FBIOGET_FSCREENINFO    0x4602
+#define TARGET_FBIOGETCMAP            0x4604
+#define TARGET_FBIOPUTCMAP            0x4605
+#define TARGET_FBIOPAN_DISPLAY        0x4606
+#define TARGET_FBIOGET_CON2FBMAP      0x460F
+#define TARGET_FBIOPUT_CON2FBMAP      0x4610
 
 /* vt ioctls */
 #define TARGET_VT_OPENQRY             0x5600
diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h
index 94b0ce0..c370125 100644
--- a/linux-user/syscall_types.h
+++ b/linux-user/syscall_types.h
@@ -161,6 +161,19 @@ STRUCT(fb_var_screeninfo,
        TYPE_INT, /* rotate */
        MK_ARRAY(TYPE_INT, 5)) /* reserved */
 
+STRUCT(fb_cmap,
+       TYPE_INT, /* start  */
+       TYPE_INT, /* len    */
+       TYPE_PTRVOID, /* red    */
+       TYPE_PTRVOID, /* green  */
+       TYPE_PTRVOID, /* blue   */
+       TYPE_PTRVOID) /* transp */
+
+STRUCT(fb_con2fbmap,
+       TYPE_INT, /* console     */
+       TYPE_INT) /* framebuffer */
+
+
 STRUCT(vt_stat,
        TYPE_SHORT, /* v_active */
        TYPE_SHORT, /* v_signal */
commit 774750c088192112df1623610dc35d9e03983d49
Author: Cédric VINCENT <cedric.vincent at st.com>
Date:   Wed Jun 29 15:09:10 2011 +0200

    linux-user: Add support for more VT ioctls
    
    DirectFB-1.0 uses at least two of the four added ioctls, and the two
    others were added for completeness.  This patch was validated with the
    program "vlock -all/-new".
    
    Signed-off-by: Cédric VINCENT <cedric.vincent at st.com>
    Cc: Riku Voipio <riku.voipio at iki.fi>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index 68418e4..7bc1c48 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -336,3 +336,7 @@
   IOCTL(VT_WAITACTIVE, 0, TYPE_INT)
   IOCTL(VT_LOCKSWITCH, 0, TYPE_INT)
   IOCTL(VT_UNLOCKSWITCH, 0, TYPE_INT)
+  IOCTL(VT_GETMODE, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_vt_mode)))
+  IOCTL(VT_SETMODE, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_vt_mode)))
+  IOCTL(VT_RELDISP, 0, TYPE_INT)
+  IOCTL(VT_DISALLOCATE, 0, TYPE_INT)
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 2b74547..4a59b36 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -940,6 +940,10 @@ struct target_pollfd {
 #define TARGET_VT_WAITACTIVE          0x5607
 #define TARGET_VT_LOCKSWITCH          0x560b
 #define TARGET_VT_UNLOCKSWITCH        0x560c
+#define TARGET_VT_GETMODE             0x5601
+#define TARGET_VT_SETMODE             0x5602
+#define TARGET_VT_RELDISP             0x5605
+#define TARGET_VT_DISALLOCATE         0x5608
 
 /* from asm/termbits.h */
 
diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h
index 0e67cd8..94b0ce0 100644
--- a/linux-user/syscall_types.h
+++ b/linux-user/syscall_types.h
@@ -166,6 +166,13 @@ STRUCT(vt_stat,
        TYPE_SHORT, /* v_signal */
        TYPE_SHORT) /* v_state */
 
+STRUCT(vt_mode,
+       TYPE_CHAR,  /* mode   */
+       TYPE_CHAR,  /* waitv  */
+       TYPE_SHORT, /* relsig */
+       TYPE_SHORT, /* acqsig */
+       TYPE_SHORT) /* frsig  */
+
 STRUCT(fiemap_extent,
        TYPE_ULONGLONG, /* fe_logical */
        TYPE_ULONGLONG, /* fe_physical */
commit e6fe18fb318cb399623246e2561581442ffc0372
Author: Cédric VINCENT <cedric.vincent at st.com>
Date:   Wed Jun 29 15:09:09 2011 +0200

    linux-user: Add support for KD...LED ioctls
    
    DirectFB-1.0 uses at least one of the four added ioctls, and the three
    others were added for completeness.  This patch was validated with the
    program "setleds" and the following Makefile:
    
        SETLEDS_INIT  = setleds -v -num -caps -scroll
        SETLEDS_TESTS = sh -c ' \
    	setleds -v +num +caps +scroll; \
    	setleds -v -num -caps -scroll; \
    	setleds -v +num -caps -scroll; \
    	setleds -v +num +caps -scroll; \
    	setleds -v +num +caps +scroll; \
    	setleds -v -num +caps +scroll; \
    	setleds -v -num -caps +scroll; \
    	setleds -v -num -caps -scroll'
    
        SETLEDS_HOST = setleds
        SETLEDS_QEMU = "SETLEDS_QEMU not set"
    
        .PHONY: setleds_tests
        setleds_tests:
    	rm -f setleds.host setleds.target
    	$(SETLEDS_INIT:setleds=$(SETLEDS_HOST))
    	$(SETLEDS_TESTS:setleds=$(SETLEDS_HOST)) >> setleds.host
    	$(SETLEDS_INIT:setleds=$(SETLEDS_QEMU))
    	$(SETLEDS_TESTS:setleds=$(SETLEDS_QEMU)) >> setleds.target
    	cmp setleds.host setleds.target
    
    Signed-off-by: Cédric VINCENT <cedric.vincent at st.com>
    Cc: Riku Voipio <riku.voipio at iki.fi>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index 42b3ae3..68418e4 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -59,6 +59,10 @@
      IOCTL(KDSKBMODE, 0, TYPE_INT)
      IOCTL(KDGKBENT, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_kbentry)))
      IOCTL(KDGKBSENT, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_kbsentry)))
+     IOCTL(KDGKBLED, 0, TYPE_INT)
+     IOCTL(KDSKBLED, 0, TYPE_INT)
+     IOCTL(KDGETLED, 0, TYPE_INT)
+     IOCTL(KDSETLED, 0, TYPE_INT)
 
      IOCTL(BLKROSET, IOC_W, MK_PTR(TYPE_INT))
      IOCTL(BLKROGET, IOC_R, MK_PTR(TYPE_INT))
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 04c268d..2b74547 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -708,6 +708,10 @@ struct target_pollfd {
 #define TARGET_KDSKBMODE       0x4b45
 #define TARGET_KDGKBENT	       0x4B46	/* gets one entry in translation table */
 #define TARGET_KDGKBSENT       0x4B48	/* gets one function key string entry */
+#define TARGET_KDGKBLED        0x4B64	/* get led flags (not lights) */
+#define TARGET_KDSKBLED        0x4B65	/* set led flags (not lights) */
+#define TARGET_KDGETLED        0x4B31	/* return current led state */
+#define TARGET_KDSETLED        0x4B32	/* set led state [lights, not flags] */
 
 #define TARGET_SIOCATMARK      0x8905
 
commit 1c1b40c162a6964e1898e84304230a308f4d16c3
Author: Cédric VINCENT <cedric.vincent at st.com>
Date:   Wed Jun 29 12:49:41 2011 +0200

    arm-semi: Provide access to CLI arguments passed through the "-append" option
    
    This patch basically adapts the new semi-hosting command-line support
    -- introduced by Wolfgang Schildbach in the commit 2e8785ac -- for use
    in system-mode.
    
    Note that the "arm_cmdline_len" and "host_cmdline_len" variables were
    renamed respectively "input_size" and "output_size" because:
    
        * in C, the term "length" is generally used to count the number of
          character in a string, not to count the number of bytes in a
          buffer (as it is the case here).
    
        * in QEMU, the term "host" is used to name variables that are in
          the host address space, not to name variables in the target
          address space (as it is the case here).
    
        * in the case of this system-call, the terms "input" and "output"
          fit the semantic of the official ARM semi-hosting specification
          quite well.
    
    I know renaming can be considered harmful but I do think in this case
    the semantic really matters to keep this code more understandable.
    
    Signed-off-by: Cédric VINCENT <cedric.vincent at st.com>
    Reviewed-by: Christophe Lyon <christophe.lyon at st.com>
    Cc: Peter Maydell <peter.maydell at linaro.org>
    Cc: Paul Brook <paul at codesourcery.com>
    Cc: Wolfgang Schildbach <wschi at dolby.com>
    Cc: Riku Voipio <riku.voipio at iki.fi>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/arm-semi.c b/arm-semi.c
index 5a62d03..873518a 100644
--- a/arm-semi.c
+++ b/arm-semi.c
@@ -34,6 +34,7 @@
 #else
 #include "qemu-common.h"
 #include "gdbstub.h"
+#include "hw/arm-misc.h"
 #endif
 
 #define SYS_OPEN        0x01
@@ -369,68 +370,88 @@ uint32_t do_arm_semihosting(CPUState *env)
         return syscall_err;
 #endif
     case SYS_GET_CMDLINE:
-#ifdef CONFIG_USER_ONLY
-        /* Build a commandline from the original argv.  */
         {
-            char *arm_cmdline_buffer;
-            const char *host_cmdline_buffer;
+            /* Build a command-line from the original argv.
+             *
+             * The inputs are:
+             *     * ARG(0), pointer to a buffer of at least the size
+             *               specified in ARG(1).
+             *     * ARG(1), size of the buffer pointed to by ARG(0) in
+             *               bytes.
+             *
+             * The outputs are:
+             *     * ARG(0), pointer to null-terminated string of the
+             *               command line.
+             *     * ARG(1), length of the string pointed to by ARG(0).
+             */
 
-            unsigned int i;
-            unsigned int arm_cmdline_len = ARG(1);
-            unsigned int host_cmdline_len =
-                ts->info->arg_end-ts->info->arg_start;
+            char *output_buffer;
+            size_t input_size = ARG(1);
+            size_t output_size;
+            int status = 0;
 
-            if (!arm_cmdline_len || host_cmdline_len > arm_cmdline_len) {
-                return -1; /* not enough space to store command line */
-            }
+            /* Compute the size of the output string.  */
+#if !defined(CONFIG_USER_ONLY)
+            output_size = strlen(ts->boot_info->kernel_filename)
+                        + 1  /* Separating space.  */
+                        + strlen(ts->boot_info->kernel_cmdline)
+                        + 1; /* Terminating null byte.  */
+#else
+            unsigned int i;
 
-            if (!host_cmdline_len) {
+            output_size = ts->info->arg_end - ts->info->arg_start;
+            if (!output_size) {
                 /* We special-case the "empty command line" case (argc==0).
                    Just provide the terminating 0. */
-                arm_cmdline_buffer = lock_user(VERIFY_WRITE, ARG(0), 1, 0);
-                arm_cmdline_buffer[0] = 0;
-                unlock_user(arm_cmdline_buffer, ARG(0), 1);
+                output_size = 1;
+            }
+#endif
 
-                /* Adjust the commandline length argument. */
-                SET_ARG(1, 0);
-                return 0;
+            if (output_size > input_size) {
+                 /* Not enough space to store command-line arguments.  */
+                return -1;
             }
 
-            /* lock the buffers on the ARM side */
-            arm_cmdline_buffer =
-                lock_user(VERIFY_WRITE, ARG(0), host_cmdline_len, 0);
-            host_cmdline_buffer =
-                lock_user(VERIFY_READ, ts->info->arg_start,
-                                       host_cmdline_len, 1);
+            /* Adjust the command-line length.  */
+            SET_ARG(1, output_size - 1);
 
-            if (arm_cmdline_buffer && host_cmdline_buffer)
-            {
-                /* the last argument is zero-terminated;
-                   no need for additional termination */
-                memcpy(arm_cmdline_buffer, host_cmdline_buffer,
-                       host_cmdline_len);
+            /* Lock the buffer on the ARM side.  */
+            output_buffer = lock_user(VERIFY_WRITE, ARG(0), output_size, 0);
+            if (!output_buffer) {
+                return -1;
+            }
 
-                /* separate arguments by white spaces */
-                for (i = 0; i < host_cmdline_len-1; i++) {
-                    if (arm_cmdline_buffer[i] == 0) {
-                        arm_cmdline_buffer[i] = ' ';
-                    }
-                }
+            /* Copy the command-line arguments.  */
+#if !defined(CONFIG_USER_ONLY)
+            pstrcpy(output_buffer, output_size, ts->boot_info->kernel_filename);
+            pstrcat(output_buffer, output_size, " ");
+            pstrcat(output_buffer, output_size, ts->boot_info->kernel_cmdline);
+#else
+            if (output_size == 1) {
+                /* Empty command-line.  */
+                output_buffer[0] = '\0';
+                goto out;
+            }
 
-                /* Adjust the commandline length argument. */
-                SET_ARG(1, host_cmdline_len-1);
+            if (copy_from_user(output_buffer, ts->info->arg_start,
+                               output_size)) {
+                status = -1;
+                goto out;
             }
 
-            /* Unlock the buffers on the ARM side.  */
-            unlock_user(arm_cmdline_buffer, ARG(0), host_cmdline_len);
-            unlock_user((void*)host_cmdline_buffer, ts->info->arg_start, 0);
+            /* Separate arguments by white spaces.  */
+            for (i = 0; i < output_size - 1; i++) {
+                if (output_buffer[i] == 0) {
+                    output_buffer[i] = ' ';
+                }
+            }
+        out:
+#endif
+            /* Unlock the buffer on the ARM side.  */
+            unlock_user(output_buffer, ARG(0), output_size);
 
-            /* Return success if we could return a commandline.  */
-            return (arm_cmdline_buffer && host_cmdline_buffer) ? 0 : -1;
+            return status;
         }
-#else
-        return -1;
-#endif
     case SYS_HEAPINFO:
         {
             uint32_t *ptr;
commit 3dc345d5874475a05794e7e1688f133b35384a9a
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Jul 7 15:18:50 2011 +0200

    usb-ohci: raise interrupt on attach
    
    Got lost in commit 618c169b577db64ac6589ad48825d2e11760d1a6,
    add it back in.  Also fix codestyle while we are at it.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index c77a20e..8491d59 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -327,6 +327,7 @@ static void ohci_attach(USBPort *port1)
 {
     OHCIState *s = port1->opaque;
     OHCIPort *port = &s->rhport[port1->index];
+    uint32_t old_state = port->ctrl;
 
     /* set connect status */
     port->ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC;
@@ -344,6 +345,10 @@ static void ohci_attach(USBPort *port1)
     }
 
     DPRINTF("usb-ohci: Attached port %d\n", port1->index);
+
+    if (old_state != port->ctrl) {
+        ohci_set_interrupt(s, OHCI_INTR_RHSC);
+    }
 }
 
 static void ohci_detach(USBPort *port1)
@@ -366,8 +371,9 @@ static void ohci_detach(USBPort *port1)
     }
     DPRINTF("usb-ohci: Detached port %d\n", port1->index);
 
-    if (old_state != port->ctrl)
+    if (old_state != port->ctrl) {
         ohci_set_interrupt(s, OHCI_INTR_RHSC);
+    }
 }
 
 static void ohci_wakeup(USBPort *port1)
commit 6c2385270b1c495515cd685b2f77c76a1b3fc864
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Jul 7 15:02:58 2011 +0200

    usb-hub: remove unused descriptor arrays
    
    Somehow they where left over when converting the hub
    to the new usb descriptor infrastructure ...
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index b7557ce..b49a2fe 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -138,74 +138,6 @@ static const USBDesc desc_hub = {
     .str  = desc_strings,
 };
 
-static const uint8_t qemu_hub_dev_descriptor[] = {
-	0x12,       /*  u8 bLength; */
-	0x01,       /*  u8 bDescriptorType; Device */
-	0x10, 0x01, /*  u16 bcdUSB; v1.1 */
-
-	0x09,	    /*  u8  bDeviceClass; HUB_CLASSCODE */
-	0x00,	    /*  u8  bDeviceSubClass; */
-	0x00,       /*  u8  bDeviceProtocol; [ low/full speeds only ] */
-	0x08,       /*  u8  bMaxPacketSize0; 8 Bytes */
-
-	0x00, 0x00, /*  u16 idVendor; */
- 	0x00, 0x00, /*  u16 idProduct; */
-	0x01, 0x01, /*  u16 bcdDevice */
-
-	0x03,       /*  u8  iManufacturer; */
-	0x02,       /*  u8  iProduct; */
-	0x01,       /*  u8  iSerialNumber; */
-	0x01        /*  u8  bNumConfigurations; */
-};
-
-/* XXX: patch interrupt size */
-static const uint8_t qemu_hub_config_descriptor[] = {
-
-	/* one configuration */
-	0x09,       /*  u8  bLength; */
-	0x02,       /*  u8  bDescriptorType; Configuration */
-	0x19, 0x00, /*  u16 wTotalLength; */
-	0x01,       /*  u8  bNumInterfaces; (1) */
-	0x01,       /*  u8  bConfigurationValue; */
-	0x00,       /*  u8  iConfiguration; */
-	0xe0,       /*  u8  bmAttributes;
-				 Bit 7: must be set,
-				     6: Self-powered,
-				     5: Remote wakeup,
-				     4..0: resvd */
-	0x00,       /*  u8  MaxPower; */
-
-	/* USB 1.1:
-	 * USB 2.0, single TT organization (mandatory):
-	 *	one interface, protocol 0
-	 *
-	 * USB 2.0, multiple TT organization (optional):
-	 *	two interfaces, protocols 1 (like single TT)
-	 *	and 2 (multiple TT mode) ... config is
-	 *	sometimes settable
-	 *	NOT IMPLEMENTED
-	 */
-
-	/* one interface */
-	0x09,       /*  u8  if_bLength; */
-	0x04,       /*  u8  if_bDescriptorType; Interface */
-	0x00,       /*  u8  if_bInterfaceNumber; */
-	0x00,       /*  u8  if_bAlternateSetting; */
-	0x01,       /*  u8  if_bNumEndpoints; */
-	0x09,       /*  u8  if_bInterfaceClass; HUB_CLASSCODE */
-	0x00,       /*  u8  if_bInterfaceSubClass; */
-	0x00,       /*  u8  if_bInterfaceProtocol; [usb1.1 or single tt] */
-	0x00,       /*  u8  if_iInterface; */
-
-	/* one endpoint (status change endpoint) */
-	0x07,       /*  u8  ep_bLength; */
-	0x05,       /*  u8  ep_bDescriptorType; Endpoint */
-	0x81,       /*  u8  ep_bEndpointAddress; IN Endpoint 1 */
- 	0x03,       /*  u8  ep_bmAttributes; Interrupt */
- 	0x02, 0x00, /*  u16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
-	0xff        /*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
-};
-
 static const uint8_t qemu_hub_hub_descriptor[] =
 {
 	0x00,			/*  u8  bLength; patched in later */
commit dd850cf2030b99d34019dd50e0df43907a3e1b41
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Jul 6 12:40:28 2011 +0200

    usb: fixup bluetooth descriptors
    
    Commit 4696425cd05c7baa0a4b469d43ba4b8488bcfc0f changes some
    endpoints from isocrounous to interrupt by mistake.  Fix it.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-bt.c b/hw/usb-bt.c
index baae487..e364513 100644
--- a/hw/usb-bt.c
+++ b/hw/usb-bt.c
@@ -99,13 +99,13 @@ static const USBDescIface desc_iface_bluetooth[] = {
         .eps = (USBDescEndpoint[]) {
             {
                 .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
-                .bmAttributes          = USB_ENDPOINT_XFER_INT,
+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
                 .wMaxPacketSize        = 0,
                 .bInterval             = 0x01,
             },
             {
                 .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
-                .bmAttributes          = USB_ENDPOINT_XFER_INT,
+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
                 .wMaxPacketSize        = 0,
                 .bInterval             = 0x01,
             },
@@ -120,13 +120,13 @@ static const USBDescIface desc_iface_bluetooth[] = {
         .eps = (USBDescEndpoint[]) {
             {
                 .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
-                .bmAttributes          = USB_ENDPOINT_XFER_INT,
+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
                 .wMaxPacketSize        = 0x09,
                 .bInterval             = 0x01,
             },
             {
                 .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
-                .bmAttributes          = USB_ENDPOINT_XFER_INT,
+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
                 .wMaxPacketSize        = 0x09,
                 .bInterval             = 0x01,
             },
@@ -141,13 +141,13 @@ static const USBDescIface desc_iface_bluetooth[] = {
         .eps = (USBDescEndpoint[]) {
             {
                 .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
-                .bmAttributes          = USB_ENDPOINT_XFER_INT,
+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
                 .wMaxPacketSize        = 0x11,
                 .bInterval             = 0x01,
             },
             {
                 .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
-                .bmAttributes          = USB_ENDPOINT_XFER_INT,
+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
                 .wMaxPacketSize        = 0x11,
                 .bInterval             = 0x01,
             },
@@ -162,13 +162,13 @@ static const USBDescIface desc_iface_bluetooth[] = {
         .eps = (USBDescEndpoint[]) {
             {
                 .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
-                .bmAttributes          = USB_ENDPOINT_XFER_INT,
+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
                 .wMaxPacketSize        = 0x19,
                 .bInterval             = 0x01,
             },
             {
                 .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
-                .bmAttributes          = USB_ENDPOINT_XFER_INT,
+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
                 .wMaxPacketSize        = 0x19,
                 .bInterval             = 0x01,
             },
@@ -183,13 +183,13 @@ static const USBDescIface desc_iface_bluetooth[] = {
         .eps = (USBDescEndpoint[]) {
             {
                 .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
-                .bmAttributes          = USB_ENDPOINT_XFER_INT,
+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
                 .wMaxPacketSize        = 0x21,
                 .bInterval             = 0x01,
             },
             {
                 .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
-                .bmAttributes          = USB_ENDPOINT_XFER_INT,
+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
                 .wMaxPacketSize        = 0x21,
                 .bInterval             = 0x01,
             },
@@ -204,13 +204,13 @@ static const USBDescIface desc_iface_bluetooth[] = {
         .eps = (USBDescEndpoint[]) {
             {
                 .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
-                .bmAttributes          = USB_ENDPOINT_XFER_INT,
+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
                 .wMaxPacketSize        = 0x31,
                 .bInterval             = 0x01,
             },
             {
                 .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
-                .bmAttributes          = USB_ENDPOINT_XFER_INT,
+                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
                 .wMaxPacketSize        = 0x31,
                 .bInterval             = 0x01,
             },
commit eb3b58f96f6740ab1cc64ba514367ce1814779e4
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Mon Jul 4 17:33:05 2011 +0200

    usb_register_port(): do not set port->opaque and port->index twice
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index c8347e9..f1dd55e 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -143,8 +143,6 @@ static void usb_fill_port(USBPort *port, void *opaque, int index,
 {
     port->opaque = opaque;
     port->index = index;
-    port->opaque = opaque;
-    port->index = index;
     port->ops = ops;
     port->speedmask = speedmask;
     usb_port_location(port, NULL, index + 1);
commit 76f30473da752ee8448e80dfd1e050cedd482b6c
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Jul 5 16:58:41 2011 +0200

    usb: update documentation
    
    Add a paragraph on companion controller mode and a
    configuration file which sets it all up for you.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/docs/ich9-ehci-uhci.cfg b/docs/ich9-ehci-uhci.cfg
new file mode 100644
index 0000000..a0e9b96
--- /dev/null
+++ b/docs/ich9-ehci-uhci.cfg
@@ -0,0 +1,37 @@
+###########################################################################
+#
+# You can pass this file directly to qemu using the -readconfig
+# command line switch.
+#
+# This config file creates a EHCI adapter with companion UHCI
+# controllers as multifunction device in PCI slot "1d".
+#
+# Specify "bus=ehci.0" when creating usb devices to hook them up
+# there.
+#
+
+[device "ehci"]
+  driver = "ich9-usb-ehci1"
+  addr = "1d.7"
+  multifunction = "on"
+
+[device "uhci-1"]
+  driver = "ich9-usb-uhci1"
+  addr = "1d.0"
+  multifunction = "on"
+  masterbus = "ehci.0"
+  firstport = "0"
+
+[device "uhci-2"]
+  driver = "ich9-usb-uhci2"
+  addr = "1d.1"
+  multifunction = "on"
+  masterbus = "ehci.0"
+  firstport = "2"
+
+[device "uhci-3"]
+  driver = "ich9-usb-uhci3"
+  addr = "1d.2"
+  multifunction = "on"
+  masterbus = "ehci.0"
+  firstport = "4"
diff --git a/docs/usb2.txt b/docs/usb2.txt
index 5950c71..228aa33 100644
--- a/docs/usb2.txt
+++ b/docs/usb2.txt
@@ -2,11 +2,13 @@
 USB 2.0 Quick Start
 ===================
 
-The QEMU EHCI Adapter does *not* support companion controllers.  That
-implies there are two completely separate USB busses: One USB 1.1 bus
-driven by the UHCI controller and one USB 2.0 bus driven by the EHCI
-controller.  Devices must be attached to the correct controller
-manually.
+The QEMU EHCI Adapter can be used with and without companion
+controllers.  See below for the companion controller mode.
+
+When not running in companion controller mode there are two completely
+separate USB busses: One USB 1.1 bus driven by the UHCI controller and
+one USB 2.0 bus driven by the EHCI controller.  Devices must be
+attached to the correct controller manually.
 
 The '-usb' switch will make qemu create the UHCI controller as part of
 the PIIX3 chipset.  The USB 1.1 bus will carry the name "usb.0".
@@ -32,6 +34,27 @@ This attaches a usb tablet to the UHCI adapter and a usb mass storage
 device to the EHCI adapter.
 
 
+Companion controller support
+----------------------------
+
+Companion controller support has been added recently.  The operational
+model described above with two completely separate busses still works
+fine.  Additionally the UHCI and OHCI controllers got the ability to
+attach to a usb bus created by EHCI as companion controllers.  This is
+done by specifying the masterbus and firstport properties.  masterbus
+specifies the bus name the controller should attach to.  firstport
+specifies the first port the controller should attach to, which is
+needed as usually one ehci controller with six ports has three uhci
+companion controllers with two ports each.
+
+There is a config file in docs which will do all this for you, just
+try ...
+
+    qemu -readconfig docs/ich9-ehci-uhci.cfg
+
+... then use "bus=ehci.0" to assign your usb devices to that bus.
+
+
 More USB tips & tricks
 ======================
 
commit 3028376ea0239e3820842bb596b21822e2373e9d
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Jul 1 11:51:02 2011 +0200

    ehci: add ich9 controller.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index 0b959ca..a4758f9 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -2244,19 +2244,34 @@ static USBBusOps ehci_bus_ops = {
     .register_companion = ehci_register_companion,
 };
 
-static PCIDeviceInfo ehci_info = {
-    .qdev.name    = "usb-ehci",
-    .qdev.size    = sizeof(EHCIState),
-    .init         = usb_ehci_initfn,
-    .vendor_id    = PCI_VENDOR_ID_INTEL,
-    .device_id    = PCI_DEVICE_ID_INTEL_82801D,
-    .revision     = 0x10,
-    .class_id     = PCI_CLASS_SERIAL_USB,
-    .qdev.props   = (Property[]) {
-        DEFINE_PROP_UINT32("freq",      EHCIState, freq, FRAME_TIMER_FREQ),
-        DEFINE_PROP_UINT32("maxframes", EHCIState, maxframes, 128),
-        DEFINE_PROP_END_OF_LIST(),
-    },
+static Property ehci_properties[] = {
+    DEFINE_PROP_UINT32("freq",      EHCIState, freq, FRAME_TIMER_FREQ),
+    DEFINE_PROP_UINT32("maxframes", EHCIState, maxframes, 128),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static PCIDeviceInfo ehci_info[] = {
+    {
+        .qdev.name    = "usb-ehci",
+        .qdev.size    = sizeof(EHCIState),
+        .init         = usb_ehci_initfn,
+        .vendor_id    = PCI_VENDOR_ID_INTEL,
+        .device_id    = PCI_DEVICE_ID_INTEL_82801D, /* ich4 */
+        .revision     = 0x10,
+        .class_id     = PCI_CLASS_SERIAL_USB,
+        .qdev.props   = ehci_properties,
+    },{
+        .qdev.name    = "ich9-usb-ehci1",
+        .qdev.size    = sizeof(EHCIState),
+        .init         = usb_ehci_initfn,
+        .vendor_id    = PCI_VENDOR_ID_INTEL,
+        .device_id    = PCI_DEVICE_ID_INTEL_82801I_EHCI1,
+        .revision     = 0x03,
+        .class_id     = PCI_CLASS_SERIAL_USB,
+        .qdev.props   = ehci_properties,
+    },{
+        /* end of list */
+    }
 };
 
 static int usb_ehci_initfn(PCIDevice *dev)
@@ -2335,7 +2350,7 @@ static int usb_ehci_initfn(PCIDevice *dev)
 
 static void ehci_register(void)
 {
-    pci_qdev_register(&ehci_info);
+    pci_qdev_register_many(ehci_info);
 }
 device_init(ehci_register);
 
commit 5cc194caeb019cf1dae7f74ccbdf0401a56c2ac6
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Jul 1 09:56:43 2011 +0200

    ehci: fix port count.
    
    The ICH4 EHCI controller which we emulate has six ports not four.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index ec68c29..0b959ca 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -130,7 +130,7 @@
 #define FRAME_TIMER_NS   (1000000000 / FRAME_TIMER_FREQ)
 
 #define NB_MAXINTRATE    8        // Max rate at which controller issues ints
-#define NB_PORTS         4        // Number of downstream ports
+#define NB_PORTS         6        // Number of downstream ports
 #define BUFF_SIZE        5*4096   // Max bytes to transfer per transaction
 #define MAX_ITERATIONS   20       // Max number of QH before we break the loop
 #define MAX_QH           100      // Max allowable queue heads in a chain
commit 1b5a757067a5ecd3504a067937b6494811a62f46
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Jul 1 09:48:49 2011 +0200

    uhci: add ich9 controllers
    
    Add ich9 controllers,  Factor out properties to a separate
    struct and reference it to reduce duplication.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 925c03b..2ef4c5b 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -1176,6 +1176,12 @@ static int usb_uhci_vt82c686b_initfn(PCIDevice *dev)
     return usb_uhci_common_initfn(dev);
 }
 
+static Property uhci_properties[] = {
+    DEFINE_PROP_STRING("masterbus", UHCIState, masterbus),
+    DEFINE_PROP_UINT32("firstport", UHCIState, firstport, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
 static PCIDeviceInfo uhci_info[] = {
     {
         .qdev.name    = "piix3-usb-uhci",
@@ -1186,11 +1192,7 @@ static PCIDeviceInfo uhci_info[] = {
         .device_id    = PCI_DEVICE_ID_INTEL_82371SB_2,
         .revision     = 0x01,
         .class_id     = PCI_CLASS_SERIAL_USB,
-        .qdev.props   = (Property[]) {
-            DEFINE_PROP_STRING("masterbus", UHCIState, masterbus),
-            DEFINE_PROP_UINT32("firstport", UHCIState, firstport, 0),
-            DEFINE_PROP_END_OF_LIST(),
-        },
+        .qdev.props   = uhci_properties,
     },{
         .qdev.name    = "piix4-usb-uhci",
         .qdev.size    = sizeof(UHCIState),
@@ -1200,11 +1202,7 @@ static PCIDeviceInfo uhci_info[] = {
         .device_id    = PCI_DEVICE_ID_INTEL_82371AB_2,
         .revision     = 0x01,
         .class_id     = PCI_CLASS_SERIAL_USB,
-        .qdev.props   = (Property[]) {
-            DEFINE_PROP_STRING("masterbus", UHCIState, masterbus),
-            DEFINE_PROP_UINT32("firstport", UHCIState, firstport, 0),
-            DEFINE_PROP_END_OF_LIST(),
-        },
+        .qdev.props   = uhci_properties,
     },{
         .qdev.name    = "vt82c686b-usb-uhci",
         .qdev.size    = sizeof(UHCIState),
@@ -1214,11 +1212,37 @@ static PCIDeviceInfo uhci_info[] = {
         .device_id    = PCI_DEVICE_ID_VIA_UHCI,
         .revision     = 0x01,
         .class_id     = PCI_CLASS_SERIAL_USB,
-        .qdev.props   = (Property[]) {
-            DEFINE_PROP_STRING("masterbus", UHCIState, masterbus),
-            DEFINE_PROP_UINT32("firstport", UHCIState, firstport, 0),
-            DEFINE_PROP_END_OF_LIST(),
-        },
+        .qdev.props   = uhci_properties,
+    },{
+        .qdev.name    = "ich9-usb-uhci1",
+        .qdev.size    = sizeof(UHCIState),
+        .qdev.vmsd    = &vmstate_uhci,
+        .init         = usb_uhci_common_initfn,
+        .vendor_id    = PCI_VENDOR_ID_INTEL,
+        .device_id    = PCI_DEVICE_ID_INTEL_82801I_UHCI1,
+        .revision     = 0x03,
+        .class_id     = PCI_CLASS_SERIAL_USB,
+        .qdev.props   = uhci_properties,
+    },{
+        .qdev.name    = "ich9-usb-uhci2",
+        .qdev.size    = sizeof(UHCIState),
+        .qdev.vmsd    = &vmstate_uhci,
+        .init         = usb_uhci_common_initfn,
+        .vendor_id    = PCI_VENDOR_ID_INTEL,
+        .device_id    = PCI_DEVICE_ID_INTEL_82801I_UHCI2,
+        .revision     = 0x03,
+        .class_id     = PCI_CLASS_SERIAL_USB,
+        .qdev.props   = uhci_properties,
+    },{
+        .qdev.name    = "ich9-usb-uhci3",
+        .qdev.size    = sizeof(UHCIState),
+        .qdev.vmsd    = &vmstate_uhci,
+        .init         = usb_uhci_common_initfn,
+        .vendor_id    = PCI_VENDOR_ID_INTEL,
+        .device_id    = PCI_DEVICE_ID_INTEL_82801I_UHCI3,
+        .revision     = 0x03,
+        .class_id     = PCI_CLASS_SERIAL_USB,
+        .qdev.props   = uhci_properties,
     },{
         /* end of list */
     }
commit f9ebf5e564efe10115b48b743d3e175917917248
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Jul 1 11:45:02 2011 +0200

    pci: add ich9 usb controller ids
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/pci_ids.h b/hw/pci_ids.h
index d94578c..927f2b0 100644
--- a/hw/pci_ids.h
+++ b/hw/pci_ids.h
@@ -109,5 +109,13 @@
 #define PCI_DEVICE_ID_INTEL_82371AB      0x7111
 #define PCI_DEVICE_ID_INTEL_82371AB_2    0x7112
 #define PCI_DEVICE_ID_INTEL_82371AB_3    0x7113
+#define PCI_DEVICE_ID_INTEL_82801I_UHCI1 0x2934
+#define PCI_DEVICE_ID_INTEL_82801I_UHCI2 0x2935
+#define PCI_DEVICE_ID_INTEL_82801I_UHCI3 0x2936
+#define PCI_DEVICE_ID_INTEL_82801I_UHCI4 0x2937
+#define PCI_DEVICE_ID_INTEL_82801I_UHCI5 0x2938
+#define PCI_DEVICE_ID_INTEL_82801I_UHCI6 0x2939
+#define PCI_DEVICE_ID_INTEL_82801I_EHCI1 0x293a
+#define PCI_DEVICE_ID_INTEL_82801I_EHCI2 0x293c
 
 #define PCI_VENDOR_ID_XENSOURCE          0x5853
commit 9c9fc3346bd6ff87babd0e5f7ea0f500d3af5765
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Jun 24 20:29:05 2011 +0200

    usb-ohci: Add support for being a companion controller
    
    To use as a companion controller, use pci-ohci as device and set the
    masterbus and num-ports properties, ie:
    
    -device usb-ehci,addr=0b.1,multifunction=on,id=ehci0
    -device pci-ohci,addr=0b.0,multifunction=on,masterbus=ehci0.0,num-ports=4
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 46f0bcb..c77a20e 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -1716,8 +1716,9 @@ static USBPortOps ohci_port_ops = {
 static USBBusOps ohci_bus_ops = {
 };
 
-static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
-                          int num_ports, uint32_t localmem_base)
+static int usb_ohci_init(OHCIState *ohci, DeviceState *dev,
+                         int num_ports, uint32_t localmem_base,
+                         char *masterbus, uint32_t firstport)
 {
     int i;
 
@@ -1737,38 +1738,58 @@ static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
                 usb_frame_time, usb_bit_time);
     }
 
+    ohci->num_ports = num_ports;
+    if (masterbus) {
+        USBPort *ports[OHCI_MAX_PORTS];
+        for(i = 0; i < num_ports; i++) {
+            ports[i] = &ohci->rhport[i].port;
+        }
+        if (usb_register_companion(masterbus, ports, num_ports,
+                firstport, ohci, &ohci_port_ops,
+                USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL) != 0) {
+            return -1;
+        }
+    } else {
+        usb_bus_new(&ohci->bus, &ohci_bus_ops, dev);
+        for (i = 0; i < num_ports; i++) {
+            usb_register_port(&ohci->bus, &ohci->rhport[i].port,
+                              ohci, i, &ohci_port_ops,
+                              USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
+        }
+    }
+
     ohci->mem = cpu_register_io_memory(ohci_readfn, ohci_writefn, ohci,
                                        DEVICE_LITTLE_ENDIAN);
     ohci->localmem_base = localmem_base;
 
     ohci->name = dev->info->name;
 
-    usb_bus_new(&ohci->bus, &ohci_bus_ops, dev);
-    ohci->num_ports = num_ports;
-    for (i = 0; i < num_ports; i++) {
-        usb_register_port(&ohci->bus, &ohci->rhport[i].port, ohci, i, &ohci_port_ops,
-                          USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
-    }
-
     ohci->async_td = 0;
     qemu_register_reset(ohci_reset, ohci);
+
+    return 0;
 }
 
 typedef struct {
     PCIDevice pci_dev;
     OHCIState state;
+    char *masterbus;
+    uint32_t num_ports;
+    uint32_t firstport;
 } OHCIPCIState;
 
 static int usb_ohci_initfn_pci(struct PCIDevice *dev)
 {
     OHCIPCIState *ohci = DO_UPCAST(OHCIPCIState, pci_dev, dev);
-    int num_ports = 3;
 
     ohci->pci_dev.config[PCI_CLASS_PROG] = 0x10; /* OHCI */
     /* TODO: RST# value should be 0. */
     ohci->pci_dev.config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin 1 */
 
-    usb_ohci_init(&ohci->state, &dev->qdev, num_ports, 0);
+    if (usb_ohci_init(&ohci->state, &dev->qdev, ohci->num_ports, 0,
+                      ohci->masterbus, ohci->firstport) != 0) {
+        return -1;
+    }
     ohci->state.irq = ohci->pci_dev.irq[0];
 
     /* TODO: avoid cast below by using dev */
@@ -1792,7 +1813,8 @@ static int ohci_init_pxa(SysBusDevice *dev)
 {
     OHCISysBusState *s = FROM_SYSBUS(OHCISysBusState, dev);
 
-    usb_ohci_init(&s->ohci, &dev->qdev, s->num_ports, s->dma_offset);
+    /* Cannot fail as we pass NULL for masterbus */
+    usb_ohci_init(&s->ohci, &dev->qdev, s->num_ports, s->dma_offset, NULL, 0);
     sysbus_init_irq(dev, &s->ohci.irq);
     sysbus_init_mmio(dev, 0x1000, s->ohci.mem);
 
@@ -1807,6 +1829,12 @@ static PCIDeviceInfo ohci_pci_info = {
     .vendor_id    = PCI_VENDOR_ID_APPLE,
     .device_id    = PCI_DEVICE_ID_APPLE_IPID_USB,
     .class_id     = PCI_CLASS_SERIAL_USB,
+    .qdev.props   = (Property[]) {
+        DEFINE_PROP_STRING("masterbus", OHCIPCIState, masterbus),
+        DEFINE_PROP_UINT32("num-ports", OHCIPCIState, num_ports, 3),
+        DEFINE_PROP_UINT32("firstport", OHCIPCIState, firstport, 0),
+        DEFINE_PROP_END_OF_LIST(),
+    },
 };
 
 static SysBusDeviceInfo ohci_sysbus_info = {
commit 35e4977f575a377fc1fa05d819a533b2c5c8646f
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Jun 24 17:44:53 2011 +0200

    usb-uhci: Add support for being a companion controller
    
    To use as a companion controller set the masterbus property.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index a46d61a..925c03b 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -132,7 +132,7 @@ typedef struct UHCIPort {
 
 struct UHCIState {
     PCIDevice dev;
-    USBBus bus;
+    USBBus bus; /* Note unused when we're a companion controller */
     uint16_t cmd; /* cmd register */
     uint16_t status;
     uint16_t intr; /* interrupt enable register */
@@ -150,6 +150,10 @@ struct UHCIState {
     /* Active packets */
     QTAILQ_HEAD(,UHCIAsync) async_pending;
     uint8_t num_ports_vmstate;
+
+    /* Properties */
+    char *masterbus;
+    uint32_t firstport;
 };
 
 typedef struct UHCI_TD {
@@ -1126,10 +1130,22 @@ static int usb_uhci_common_initfn(PCIDevice *dev)
     pci_conf[PCI_INTERRUPT_PIN] = 4; // interrupt pin 3
     pci_conf[USB_SBRN] = USB_RELEASE_1; // release number
 
-    usb_bus_new(&s->bus, &uhci_bus_ops, &s->dev.qdev);
-    for(i = 0; i < NB_PORTS; i++) {
-        usb_register_port(&s->bus, &s->ports[i].port, s, i, &uhci_port_ops,
-                          USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
+    if (s->masterbus) {
+        USBPort *ports[NB_PORTS];
+        for(i = 0; i < NB_PORTS; i++) {
+            ports[i] = &s->ports[i].port;
+        }
+        if (usb_register_companion(s->masterbus, ports, NB_PORTS,
+                s->firstport, s, &uhci_port_ops,
+                USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL) != 0) {
+            return -1;
+        }
+    } else {
+        usb_bus_new(&s->bus, &uhci_bus_ops, &s->dev.qdev);
+        for (i = 0; i < NB_PORTS; i++) {
+            usb_register_port(&s->bus, &s->ports[i].port, s, i, &uhci_port_ops,
+                              USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
+        }
     }
     s->frame_timer = qemu_new_timer_ns(vm_clock, uhci_frame_timer, s);
     s->num_ports_vmstate = NB_PORTS;
@@ -1170,6 +1186,11 @@ static PCIDeviceInfo uhci_info[] = {
         .device_id    = PCI_DEVICE_ID_INTEL_82371SB_2,
         .revision     = 0x01,
         .class_id     = PCI_CLASS_SERIAL_USB,
+        .qdev.props   = (Property[]) {
+            DEFINE_PROP_STRING("masterbus", UHCIState, masterbus),
+            DEFINE_PROP_UINT32("firstport", UHCIState, firstport, 0),
+            DEFINE_PROP_END_OF_LIST(),
+        },
     },{
         .qdev.name    = "piix4-usb-uhci",
         .qdev.size    = sizeof(UHCIState),
@@ -1179,6 +1200,11 @@ static PCIDeviceInfo uhci_info[] = {
         .device_id    = PCI_DEVICE_ID_INTEL_82371AB_2,
         .revision     = 0x01,
         .class_id     = PCI_CLASS_SERIAL_USB,
+        .qdev.props   = (Property[]) {
+            DEFINE_PROP_STRING("masterbus", UHCIState, masterbus),
+            DEFINE_PROP_UINT32("firstport", UHCIState, firstport, 0),
+            DEFINE_PROP_END_OF_LIST(),
+        },
     },{
         .qdev.name    = "vt82c686b-usb-uhci",
         .qdev.size    = sizeof(UHCIState),
@@ -1188,6 +1214,11 @@ static PCIDeviceInfo uhci_info[] = {
         .device_id    = PCI_DEVICE_ID_VIA_UHCI,
         .revision     = 0x01,
         .class_id     = PCI_CLASS_SERIAL_USB,
+        .qdev.props   = (Property[]) {
+            DEFINE_PROP_STRING("masterbus", UHCIState, masterbus),
+            DEFINE_PROP_UINT32("firstport", UHCIState, firstport, 0),
+            DEFINE_PROP_END_OF_LIST(),
+        },
     },{
         /* end of list */
     }
commit a0a3167a910d4ff9b43c9e69000f43753719909a
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Jun 24 16:18:13 2011 +0200

    usb-ehci: Add support for registering companion controllers
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index 973c342..ec68c29 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -20,9 +20,6 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
- *
- * TODO:
- *  o Downstream port handoff
  */
 
 #include "hw.h"
@@ -106,7 +103,7 @@
  * Bits that are reserved or are read-only are masked out of values
  * written to us by software
  */
-#define PORTSC_RO_MASK       0x007021c0
+#define PORTSC_RO_MASK       0x007001c0
 #define PORTSC_RWC_MASK      0x0000002a
 #define PORTSC_WKOC_E        (1 << 22)    // Wake on Over Current Enable
 #define PORTSC_WKDS_E        (1 << 21)    // Wake on Disconnect Enable
@@ -373,6 +370,7 @@ struct EHCIState {
     qemu_irq irq;
     target_phys_addr_t mem_base;
     int mem;
+    int companion_count;
 
     /* properties */
     uint32_t freq;
@@ -408,6 +406,7 @@ struct EHCIState {
     int astate;                        // Current state in asynchronous schedule
     int pstate;                        // Current state in periodic schedule
     USBPort ports[NB_PORTS];
+    USBPort *companion_ports[NB_PORTS];
     uint32_t usbsts_pending;
     QTAILQ_HEAD(, EHCIQueue) queues;
 
@@ -730,17 +729,17 @@ static void ehci_attach(USBPort *port)
 
     trace_usb_ehci_port_attach(port->index, port->dev->product_desc);
 
+    if (*portsc & PORTSC_POWNER) {
+        USBPort *companion = s->companion_ports[port->index];
+        companion->dev = port->dev;
+        companion->ops->attach(companion);
+        return;
+    }
+
     *portsc |= PORTSC_CONNECT;
     *portsc |= PORTSC_CSC;
 
-    /*
-     *  If a high speed device is attached then we own this port(indicated
-     *  by zero in the PORTSC_POWNER bit field) so set the status bit
-     *  and set an interrupt if enabled.
-     */
-    if ( !(*portsc & PORTSC_POWNER)) {
-        ehci_set_interrupt(s, USBSTS_PCD);
-    }
+    ehci_set_interrupt(s, USBSTS_PCD);
 }
 
 static void ehci_detach(USBPort *port)
@@ -750,36 +749,110 @@ static void ehci_detach(USBPort *port)
 
     trace_usb_ehci_port_detach(port->index);
 
+    if (*portsc & PORTSC_POWNER) {
+        USBPort *companion = s->companion_ports[port->index];
+        companion->ops->detach(companion);
+        companion->dev = NULL;
+        return;
+    }
+
     ehci_queues_rip_device(s, port->dev);
 
     *portsc &= ~(PORTSC_CONNECT|PORTSC_PED);
     *portsc |= PORTSC_CSC;
 
-    /*
-     *  If a high speed device is attached then we own this port(indicated
-     *  by zero in the PORTSC_POWNER bit field) so set the status bit
-     *  and set an interrupt if enabled.
-     */
-    if ( !(*portsc & PORTSC_POWNER)) {
-        ehci_set_interrupt(s, USBSTS_PCD);
-    }
+    ehci_set_interrupt(s, USBSTS_PCD);
 }
 
 static void ehci_child_detach(USBPort *port, USBDevice *child)
 {
     EHCIState *s = port->opaque;
+    uint32_t portsc = s->portsc[port->index];
+
+    if (portsc & PORTSC_POWNER) {
+        USBPort *companion = s->companion_ports[port->index];
+        companion->ops->child_detach(companion, child);
+        companion->dev = NULL;
+        return;
+    }
 
     ehci_queues_rip_device(s, child);
 }
 
+static void ehci_wakeup(USBPort *port)
+{
+    EHCIState *s = port->opaque;
+    uint32_t portsc = s->portsc[port->index];
+
+    if (portsc & PORTSC_POWNER) {
+        USBPort *companion = s->companion_ports[port->index];
+        if (companion->ops->wakeup) {
+            companion->ops->wakeup(companion);
+        }
+    }
+}
+
+static int ehci_register_companion(USBBus *bus, USBPort *ports[],
+                                   uint32_t portcount, uint32_t firstport)
+{
+    EHCIState *s = container_of(bus, EHCIState, bus);
+    uint32_t i;
+
+    if (firstport + portcount > NB_PORTS) {
+        qerror_report(QERR_INVALID_PARAMETER_VALUE, "firstport",
+                      "firstport on masterbus");
+        error_printf_unless_qmp(
+            "firstport value of %u makes companion take ports %u - %u, which "
+            "is outside of the valid range of 0 - %u\n", firstport, firstport,
+            firstport + portcount - 1, NB_PORTS - 1);
+        return -1;
+    }
+
+    for (i = 0; i < portcount; i++) {
+        if (s->companion_ports[firstport + i]) {
+            qerror_report(QERR_INVALID_PARAMETER_VALUE, "masterbus",
+                          "an USB masterbus");
+            error_printf_unless_qmp(
+                "port %u on masterbus %s already has a companion assigned\n",
+                firstport + i, bus->qbus.name);
+            return -1;
+        }
+    }
+
+    for (i = 0; i < portcount; i++) {
+        s->companion_ports[firstport + i] = ports[i];
+        s->ports[firstport + i].speedmask |=
+            USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL;
+        /* Ensure devs attached before the initial reset go to the companion */
+        s->portsc[firstport + i] = PORTSC_POWNER;
+    }
+
+    s->companion_count++;
+    s->mmio[0x05] = (s->companion_count << 4) | portcount;
+
+    return 0;
+}
+
 /* 4.1 host controller initialization */
 static void ehci_reset(void *opaque)
 {
     EHCIState *s = opaque;
     int i;
+    USBDevice *devs[NB_PORTS];
 
     trace_usb_ehci_reset();
 
+    /*
+     * Do the detach before touching portsc, so that it correctly gets send to
+     * us or to our companion based on PORTSC_POWNER before the reset.
+     */
+    for(i = 0; i < NB_PORTS; i++) {
+        devs[i] = s->ports[i].dev;
+        if (devs[i]) {
+            usb_attach(&s->ports[i], NULL);
+        }
+    }
+
     memset(&s->mmio[OPREGBASE], 0x00, MMIO_SIZE - OPREGBASE);
 
     s->usbcmd = NB_MAXINTRATE << USBCMD_ITC_SH;
@@ -791,10 +864,13 @@ static void ehci_reset(void *opaque)
     s->attach_poll_counter = 0;
 
     for(i = 0; i < NB_PORTS; i++) {
-        s->portsc[i] = PORTSC_POWNER | PORTSC_PPOWER;
-
-        if (s->ports[i].dev) {
-            usb_attach(&s->ports[i], s->ports[i].dev);
+        if (s->companion_ports[i]) {
+            s->portsc[i] = PORTSC_POWNER | PORTSC_PPOWER;
+        } else {
+            s->portsc[i] = PORTSC_PPOWER;
+        }
+        if (devs[i]) {
+            usb_attach(&s->ports[i], devs[i]);
         }
     }
     ehci_queues_rip_all(s);
@@ -844,6 +920,34 @@ static void ehci_mem_writew(void *ptr, target_phys_addr_t addr, uint32_t val)
     exit(1);
 }
 
+static void handle_port_owner_write(EHCIState *s, int port, uint32_t owner)
+{
+    USBDevice *dev = s->ports[port].dev;
+    uint32_t *portsc = &s->portsc[port];
+    uint32_t orig;
+
+    if (s->companion_ports[port] == NULL)
+        return;
+
+    owner = owner & PORTSC_POWNER;
+    orig  = *portsc & PORTSC_POWNER;
+
+    if (!(owner ^ orig)) {
+        return;
+    }
+
+    if (dev) {
+        usb_attach(&s->ports[port], NULL);
+    }
+
+    *portsc &= ~PORTSC_POWNER;
+    *portsc |= owner;
+
+    if (dev) {
+        usb_attach(&s->ports[port], dev);
+    }
+}
+
 static void handle_port_status_write(EHCIState *s, int port, uint32_t val)
 {
     uint32_t *portsc = &s->portsc[port];
@@ -853,6 +957,9 @@ static void handle_port_status_write(EHCIState *s, int port, uint32_t val)
     *portsc &= ~(val & PORTSC_RWC_MASK);
     /* The guest may clear, but not set the PED bit */
     *portsc &= val | ~PORTSC_PED;
+    /* POWNER is masked out by RO_MASK as it is RO when we've no companion */
+    handle_port_owner_write(s, port, val);
+    /* And finally apply RO_MASK */
     val &= PORTSC_RO_MASK;
 
     if ((val & PORTSC_PRESET) && !(*portsc & PORTSC_PRESET)) {
@@ -956,7 +1063,7 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
         val &= 0x1;
         if (val) {
             for(i = 0; i < NB_PORTS; i++)
-                s->portsc[i] &= ~PORTSC_POWNER;
+                handle_port_owner_write(s, i, 0);
         }
         break;
 
@@ -1114,8 +1221,17 @@ static int ehci_buffer_rw(EHCIQueue *q, int bytes, int rw)
 
 static void ehci_async_complete_packet(USBPort *port, USBPacket *packet)
 {
-    EHCIQueue *q = container_of(packet, EHCIQueue, packet);
+    EHCIQueue *q;
+    EHCIState *s = port->opaque;
+    uint32_t portsc = s->portsc[port->index];
+
+    if (portsc & PORTSC_POWNER) {
+        USBPort *companion = s->companion_ports[port->index];
+        companion->ops->complete(companion, packet);
+        return;
+    }
 
+    q = container_of(packet, EHCIQueue, packet);
     trace_usb_ehci_queue_action(q, "wakeup");
     assert(q->async == EHCI_ASYNC_INFLIGHT);
     q->async = EHCI_ASYNC_FINISHED;
@@ -1245,8 +1361,6 @@ static int ehci_execute(EHCIQueue *q)
         port = &q->ehci->ports[i];
         dev = port->dev;
 
-        // TODO sometime we will also need to check if we are the port owner
-
         if (!(q->ehci->portsc[i] &(PORTSC_CONNECT))) {
             DPRINTF("Port %d, no exec, not connected(%08X)\n",
                     i, q->ehci->portsc[i]);
@@ -1339,8 +1453,6 @@ static int ehci_process_itd(EHCIState *ehci,
                 port = &ehci->ports[j];
                 dev = port->dev;
 
-                // TODO sometime we will also need to check if we are the port owner
-
                 if (!(ehci->portsc[j] &(PORTSC_CONNECT))) {
                     continue;
                 }
@@ -2124,10 +2236,12 @@ static USBPortOps ehci_port_ops = {
     .attach = ehci_attach,
     .detach = ehci_detach,
     .child_detach = ehci_child_detach,
+    .wakeup = ehci_wakeup,
     .complete = ehci_async_complete_packet,
 };
 
 static USBBusOps ehci_bus_ops = {
+    .register_companion = ehci_register_companion,
 };
 
 static PCIDeviceInfo ehci_info = {
commit fbd97532d22b6989fc71d64471c905d3c8174f5d
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Jun 24 14:36:13 2011 +0200

    usb-ehci: Fix handling of PED and PEDC port status bits
    
    The PED bit should only be set for highspeed devices and the PEDC bit
    should not be set on "normal" PED bit changes, only on io errors.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index d85e0a9..973c342 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -106,7 +106,7 @@
  * Bits that are reserved or are read-only are masked out of values
  * written to us by software
  */
-#define PORTSC_RO_MASK       0x007021c4
+#define PORTSC_RO_MASK       0x007021c0
 #define PORTSC_RWC_MASK      0x0000002a
 #define PORTSC_WKOC_E        (1 << 22)    // Wake on Over Current Enable
 #define PORTSC_WKDS_E        (1 << 21)    // Wake on Disconnect Enable
@@ -752,7 +752,7 @@ static void ehci_detach(USBPort *port)
 
     ehci_queues_rip_device(s, port->dev);
 
-    *portsc &= ~PORTSC_CONNECT;
+    *portsc &= ~(PORTSC_CONNECT|PORTSC_PED);
     *portsc |= PORTSC_CSC;
 
     /*
@@ -847,16 +847,14 @@ static void ehci_mem_writew(void *ptr, target_phys_addr_t addr, uint32_t val)
 static void handle_port_status_write(EHCIState *s, int port, uint32_t val)
 {
     uint32_t *portsc = &s->portsc[port];
-    int rwc;
     USBDevice *dev = s->ports[port].dev;
 
-    rwc = val & PORTSC_RWC_MASK;
+    /* Clear rwc bits */
+    *portsc &= ~(val & PORTSC_RWC_MASK);
+    /* The guest may clear, but not set the PED bit */
+    *portsc &= val | ~PORTSC_PED;
     val &= PORTSC_RO_MASK;
 
-    // handle_read_write_clear(&val, portsc, PORTSC_PEDC | PORTSC_CSC);
-
-    *portsc &= ~rwc;
-
     if ((val & PORTSC_PRESET) && !(*portsc & PORTSC_PRESET)) {
         trace_usb_ehci_port_reset(port, 1);
     }
@@ -869,13 +867,13 @@ static void handle_port_status_write(EHCIState *s, int port, uint32_t val)
             *portsc &= ~PORTSC_CSC;
         }
 
-        /*  Table 2.16 Set the enable bit(and enable bit change) to indicate
+        /*
+         *  Table 2.16 Set the enable bit(and enable bit change) to indicate
          *  to SW that this port has a high speed device attached
-         *
-         *  TODO - when to disable?
          */
-        val |= PORTSC_PED;
-        val |= PORTSC_PEDC;
+        if (dev && (dev->speedmask & USB_SPEED_MASK_HIGH)) {
+            val |= PORTSC_PED;
+        }
     }
 
     *portsc &= ~PORTSC_RO_MASK;
commit 45b9fd348061ab793cf4521bb3621f07a5bd7bf6
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Jun 24 14:26:18 2011 +0200

    usb: assert on calling usb_attach(port, NULL) on a port without a dev
    
    with the "usb-ehci: cleanup port reset handling" patch in place no callers
    are calling usb_attach(port, NULL) for a port where port->dev is NULL.
    
    Doing that makes no sense as that causes the port detach op to get called
    for a port with nothing attached. Add an assert that port->dev != NULL when
    dev == NULL, and remove the check for not having a port->dev in the dev == NULL
    case.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb.c b/hw/usb.c
index 735ffd1..27a983c 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -40,12 +40,11 @@ void usb_attach(USBPort *port, USBDevice *dev)
     } else {
         /* detach */
         dev = port->dev;
+        assert(dev);
         port->ops->detach(port);
-        if (dev) {
-            usb_send_msg(dev, USB_MSG_DETACH);
-            dev->port = NULL;
-            port->dev = NULL;
-        }
+        usb_send_msg(dev, USB_MSG_DETACH);
+        dev->port = NULL;
+        port->dev = NULL;
     }
 }
 
commit fbf9db645765a22b796e128967bebb64c073938a
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Tue Jun 21 12:23:40 2011 +0200

    usb-ehci: cleanup port reset handling
    
    Doing a usb_attach when dev is NULL will just result in the
    port detach op getting called even though nothing was connected in
    the first place.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index ce1a432..d85e0a9 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -863,14 +863,9 @@ static void handle_port_status_write(EHCIState *s, int port, uint32_t val)
 
     if (!(val & PORTSC_PRESET) &&(*portsc & PORTSC_PRESET)) {
         trace_usb_ehci_port_reset(port, 0);
-        usb_attach(&s->ports[port], dev);
-
-        // TODO how to handle reset of ports with no device
         if (dev) {
+            usb_attach(&s->ports[port], dev);
             usb_send_msg(dev, USB_MSG_RESET);
-        }
-
-        if (s->ports[port].dev) {
             *portsc &= ~PORTSC_CSC;
         }
 
commit c44fd61c0f38aa7927fd41bd7e59cb3e60fd4d75
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Tue Jun 21 12:12:35 2011 +0200

    usb-ehci: Connect Status bit is read only, don't allow changing it by the guest
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index 87e1de3..ce1a432 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -103,10 +103,10 @@
 #define PORTSC_BEGIN         PORTSC
 #define PORTSC_END           (PORTSC + 4 * NB_PORTS)
 /*
- * Bits that are reserverd or are read-only are masked out of values
+ * Bits that are reserved or are read-only are masked out of values
  * written to us by software
  */
-#define PORTSC_RO_MASK       0x007021c5
+#define PORTSC_RO_MASK       0x007021c4
 #define PORTSC_RWC_MASK      0x0000002a
 #define PORTSC_WKOC_E        (1 << 22)    // Wake on Over Current Enable
 #define PORTSC_WKDS_E        (1 << 21)    // Wake on Disconnect Enable
commit 053f9fcfb1d84ab2f1d8fbd608d5e31aae58cbb7
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Jun 17 15:26:29 2011 +0200

    usb-ehci: drop unused num-ports state member
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index 96451f3..87e1de3 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -373,7 +373,6 @@ struct EHCIState {
     qemu_irq irq;
     target_phys_addr_t mem_base;
     int mem;
-    int num_ports;
 
     /* properties */
     uint32_t freq;
commit 4706ab6cc0af86d3f38806664420cc3eb8999bd9
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Jun 24 12:31:11 2011 +0200

    usb: Replace device_destroy bus op with a child_detach port op
    
    Note this fixes 2 things in one go, first of all the device_destroy bus
    op should be a device_detach bus op, as pending async packets from the
    device should be cancelled on detach not on destroy.
    
    Secondly having this as a bus op won't work with companion controllers, since
    then there will be 1 bus driven by the ehci controller and thus 1 set of bus
    ops, but the device being detached may be downstream of a handed over port.
    Making the detach of a downstream device a port op allows the ehci controller
    to forward this to the companion controller port for handed over ports.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/milkymist-softusb.c b/hw/milkymist-softusb.c
index 5ab35c3..ce2bfc6 100644
--- a/hw/milkymist-softusb.c
+++ b/hw/milkymist-softusb.c
@@ -247,16 +247,21 @@ static void softusb_attach(USBPort *port)
 {
 }
 
-static void softusb_device_destroy(USBBus *bus, USBDevice *dev)
+static void softusb_detach(USBPort *port)
+{
+}
+
+static void softusb_child_detach(USBPort *port, USBDevice *child)
 {
 }
 
 static USBPortOps softusb_ops = {
     .attach = softusb_attach,
+    .detach = softusb_detach,
+    .child_detach = softusb_child_detach,
 };
 
 static USBBusOps softusb_bus_ops = {
-    .device_destroy = softusb_device_destroy,
 };
 
 static void milkymist_softusb_reset(DeviceState *d)
diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index b511bac..c8347e9 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -82,12 +82,10 @@ static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base)
 static int usb_qdev_exit(DeviceState *qdev)
 {
     USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev);
-    USBBus *bus = usb_bus_from_device(dev);
 
     if (dev->attached) {
         usb_device_detach(dev);
     }
-    bus->ops->device_destroy(bus, dev);
     if (dev->info->handle_destroy) {
         dev->info->handle_destroy(dev);
     }
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index 428c90b..96451f3 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -751,6 +751,8 @@ static void ehci_detach(USBPort *port)
 
     trace_usb_ehci_port_detach(port->index);
 
+    ehci_queues_rip_device(s, port->dev);
+
     *portsc &= ~PORTSC_CONNECT;
     *portsc |= PORTSC_CSC;
 
@@ -764,6 +766,13 @@ static void ehci_detach(USBPort *port)
     }
 }
 
+static void ehci_child_detach(USBPort *port, USBDevice *child)
+{
+    EHCIState *s = port->opaque;
+
+    ehci_queues_rip_device(s, child);
+}
+
 /* 4.1 host controller initialization */
 static void ehci_reset(void *opaque)
 {
@@ -2117,23 +2126,16 @@ static void ehci_map(PCIDevice *pci_dev, int region_num,
     cpu_register_physical_memory(addr, size, s->mem);
 }
 
-static void ehci_device_destroy(USBBus *bus, USBDevice *dev)
-{
-    EHCIState *s = container_of(bus, EHCIState, bus);
-
-    ehci_queues_rip_device(s, dev);
-}
-
 static int usb_ehci_initfn(PCIDevice *dev);
 
 static USBPortOps ehci_port_ops = {
     .attach = ehci_attach,
     .detach = ehci_detach,
+    .child_detach = ehci_child_detach,
     .complete = ehci_async_complete_packet,
 };
 
 static USBBusOps ehci_bus_ops = {
-    .device_destroy = ehci_device_destroy,
 };
 
 static PCIDeviceInfo ehci_info = {
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index d324bba..b7557ce 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -238,6 +238,9 @@ static void usb_hub_detach(USBPort *port1)
     USBHubState *s = port1->opaque;
     USBHubPort *port = &s->ports[port1->index];
 
+    /* Let upstream know the device on this port is gone */
+    s->dev.port->ops->child_detach(s->dev.port, port1->dev);
+
     port->wPortStatus &= ~PORT_STAT_CONNECTION;
     port->wPortChange |= PORT_STAT_C_CONNECTION;
     if (port->wPortStatus & PORT_STAT_ENABLE) {
@@ -246,6 +249,14 @@ static void usb_hub_detach(USBPort *port1)
     }
 }
 
+static void usb_hub_child_detach(USBPort *port1, USBDevice *child)
+{
+    USBHubState *s = port1->opaque;
+
+    /* Pass along upstream */
+    s->dev.port->ops->child_detach(s->dev.port, child);
+}
+
 static void usb_hub_wakeup(USBPort *port1)
 {
     USBHubState *s = port1->opaque;
@@ -537,6 +548,7 @@ static void usb_hub_handle_destroy(USBDevice *dev)
 static USBPortOps usb_hub_port_ops = {
     .attach = usb_hub_attach,
     .detach = usb_hub_detach,
+    .child_detach = usb_hub_child_detach,
     .wakeup = usb_hub_wakeup,
     .complete = usb_hub_complete,
 };
diff --git a/hw/usb-musb.c b/hw/usb-musb.c
index 580bdc8..035dda8 100644
--- a/hw/usb-musb.c
+++ b/hw/usb-musb.c
@@ -261,17 +261,18 @@
 
 static void musb_attach(USBPort *port);
 static void musb_detach(USBPort *port);
+static void musb_child_detach(USBPort *port, USBDevice *child);
 static void musb_schedule_cb(USBPort *port, USBPacket *p);
-static void musb_device_destroy(USBBus *bus, USBDevice *dev);
+static void musb_async_cancel_device(MUSBState *s, USBDevice *dev);
 
 static USBPortOps musb_port_ops = {
     .attach = musb_attach,
     .detach = musb_detach,
+    .child_detach = musb_child_detach,
     .complete = musb_schedule_cb,
 };
 
 static USBBusOps musb_bus_ops = {
-    .device_destroy = musb_device_destroy,
 };
 
 typedef struct MUSBPacket MUSBPacket;
@@ -497,10 +498,19 @@ static void musb_detach(USBPort *port)
 {
     MUSBState *s = (MUSBState *) port->opaque;
 
+    musb_async_cancel_device(s, port->dev);
+
     musb_intr_set(s, musb_irq_disconnect, 1);
     musb_session_update(s, 1, s->session);
 }
 
+static void musb_child_detach(USBPort *port, USBDevice *child)
+{
+    MUSBState *s = (MUSBState *) port->opaque;
+
+    musb_async_cancel_device(s, child);
+}
+
 static void musb_cb_tick0(void *opaque)
 {
     MUSBEndPoint *ep = (MUSBEndPoint *) opaque;
@@ -782,9 +792,8 @@ static void musb_rx_packet_complete(USBPacket *packey, void *opaque)
     musb_rx_intr_set(s, epnum, 1);
 }
 
-static void musb_device_destroy(USBBus *bus, USBDevice *dev)
+static void musb_async_cancel_device(MUSBState *s, USBDevice *dev)
 {
-    MUSBState *s = container_of(bus, MUSBState, bus);
     int ep, dir;
 
     for (ep = 0; ep < 16; ep++) {
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index bd92c31..46f0bcb 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -124,6 +124,7 @@ struct ohci_hcca {
 };
 
 static void ohci_bus_stop(OHCIState *ohci);
+static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev);
 
 /* Bitfields for the first word of an Endpoint Desciptor.  */
 #define OHCI_ED_FA_SHIFT  0
@@ -351,6 +352,8 @@ static void ohci_detach(USBPort *port1)
     OHCIPort *port = &s->rhport[port1->index];
     uint32_t old_state = port->ctrl;
 
+    ohci_async_cancel_device(s, port1->dev);
+
     /* set connect status */
     if (port->ctrl & OHCI_PORT_CCS) {
         port->ctrl &= ~OHCI_PORT_CCS;
@@ -392,6 +395,13 @@ static void ohci_wakeup(USBPort *port1)
     ohci_set_interrupt(s, intr);
 }
 
+static void ohci_child_detach(USBPort *port1, USBDevice *child)
+{
+    OHCIState *s = port1->opaque;
+
+    ohci_async_cancel_device(s, child);
+}
+
 /* Reset the controller */
 static void ohci_reset(void *opaque)
 {
@@ -1673,10 +1683,8 @@ static void ohci_mem_write(void *ptr, target_phys_addr_t addr, uint32_t val)
     }
 }
 
-static void ohci_device_destroy(USBBus *bus, USBDevice *dev)
+static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev)
 {
-    OHCIState *ohci = container_of(bus, OHCIState, bus);
-
     if (ohci->async_td && ohci->usb_packet.owner == dev) {
         usb_cancel_packet(&ohci->usb_packet);
         ohci->async_td = 0;
@@ -1700,12 +1708,12 @@ static CPUWriteMemoryFunc * const ohci_writefn[3]={
 static USBPortOps ohci_port_ops = {
     .attach = ohci_attach,
     .detach = ohci_detach,
+    .child_detach = ohci_child_detach,
     .wakeup = ohci_wakeup,
     .complete = ohci_async_complete_packet,
 };
 
 static USBBusOps ohci_bus_ops = {
-    .device_destroy = ohci_device_destroy,
 };
 
 static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index ab635f6..a46d61a 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -606,6 +606,8 @@ static void uhci_detach(USBPort *port1)
     UHCIState *s = port1->opaque;
     UHCIPort *port = &s->ports[port1->index];
 
+    uhci_async_cancel_device(s, port1->dev);
+
     /* set connect status */
     if (port->ctrl & UHCI_PORT_CCS) {
         port->ctrl &= ~UHCI_PORT_CCS;
@@ -620,6 +622,13 @@ static void uhci_detach(USBPort *port1)
     uhci_resume(s);
 }
 
+static void uhci_child_detach(USBPort *port1, USBDevice *child)
+{
+    UHCIState *s = port1->opaque;
+
+    uhci_async_cancel_device(s, child);
+}
+
 static void uhci_wakeup(USBPort *port1)
 {
     UHCIState *s = port1->opaque;
@@ -1095,22 +1104,15 @@ static void uhci_map(PCIDevice *pci_dev, int region_num,
     register_ioport_read(addr, 32, 1, uhci_ioport_readb, s);
 }
 
-static void uhci_device_destroy(USBBus *bus, USBDevice *dev)
-{
-    UHCIState *s = container_of(bus, UHCIState, bus);
-
-    uhci_async_cancel_device(s, dev);
-}
-
 static USBPortOps uhci_port_ops = {
     .attach = uhci_attach,
     .detach = uhci_detach,
+    .child_detach = uhci_child_detach,
     .wakeup = uhci_wakeup,
     .complete = uhci_async_complete,
 };
 
 static USBBusOps uhci_bus_ops = {
-    .device_destroy = uhci_device_destroy,
 };
 
 static int usb_uhci_common_initfn(PCIDevice *dev)
diff --git a/hw/usb.h b/hw/usb.h
index 65f45a0..ded2de2 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -252,6 +252,11 @@ struct USBDeviceInfo {
 typedef struct USBPortOps {
     void (*attach)(USBPort *port);
     void (*detach)(USBPort *port);
+    /*
+     * This gets called when a device downstream from the device attached to
+     * the port (iow attached through a hub) gets detached.
+     */
+    void (*child_detach)(USBPort *port, USBDevice *child);
     void (*wakeup)(USBPort *port);
     /*
      * Note that port->dev will be different then the device from which
@@ -351,7 +356,6 @@ struct USBBus {
 struct USBBusOps {
     int (*register_companion)(USBBus *bus, USBPort *ports[],
                               uint32_t portcount, uint32_t firstport);
-    void (*device_destroy)(USBBus *bus, USBDevice *dev);
 };
 
 void usb_bus_new(USBBus *bus, USBBusOps *ops, DeviceState *host);
commit d47e59b8b8adc96a2052f7e004cb12b6ff62edd9
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Tue Jun 21 11:52:28 2011 +0200

    usb: Make port wakeup and complete ops take a USBPort instead of a Device
    
    This makes them consistent with the attach and detach ops, and in general
    it makes sense to make portops take a port as argument. This also makes
    adding support for a companion controller easier / cleaner.
    
    [ kraxel: fix usb-musb.c build ]
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index 88cb2c2..428c90b 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -1111,7 +1111,7 @@ static int ehci_buffer_rw(EHCIQueue *q, int bytes, int rw)
     return 0;
 }
 
-static void ehci_async_complete_packet(USBDevice *dev, USBPacket *packet)
+static void ehci_async_complete_packet(USBPort *port, USBPacket *packet)
 {
     EHCIQueue *q = container_of(packet, EHCIQueue, packet);
 
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 6e2a358..d324bba 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -246,10 +246,10 @@ static void usb_hub_detach(USBPort *port1)
     }
 }
 
-static void usb_hub_wakeup(USBDevice *dev)
+static void usb_hub_wakeup(USBPort *port1)
 {
-    USBHubState *s = dev->port->opaque;
-    USBHubPort *port = &s->ports[dev->port->index];
+    USBHubState *s = port1->opaque;
+    USBHubPort *port = &s->ports[port1->index];
 
     if (port->wPortStatus & PORT_STAT_SUSPEND) {
         port->wPortChange |= PORT_STAT_C_SUSPEND;
@@ -257,9 +257,9 @@ static void usb_hub_wakeup(USBDevice *dev)
     }
 }
 
-static void usb_hub_complete(USBDevice *dev, USBPacket *packet)
+static void usb_hub_complete(USBPort *port, USBPacket *packet)
 {
-    USBHubState *s = dev->port->opaque;
+    USBHubState *s = port->opaque;
 
     /*
      * Just pass it along upstream for now.
diff --git a/hw/usb-musb.c b/hw/usb-musb.c
index 84e6017..580bdc8 100644
--- a/hw/usb-musb.c
+++ b/hw/usb-musb.c
@@ -261,7 +261,7 @@
 
 static void musb_attach(USBPort *port);
 static void musb_detach(USBPort *port);
-static void musb_schedule_cb(USBDevice *dev, USBPacket *p);
+static void musb_schedule_cb(USBPort *port, USBPacket *p);
 static void musb_device_destroy(USBBus *bus, USBDevice *dev);
 
 static USBPortOps musb_port_ops = {
@@ -517,7 +517,7 @@ static void musb_cb_tick1(void *opaque)
 
 #define musb_cb_tick	(dir ? musb_cb_tick1 : musb_cb_tick0)
 
-static void musb_schedule_cb(USBDevice *dev, USBPacket *packey)
+static void musb_schedule_cb(USBPort *port, USBPacket *packey)
 {
     MUSBPacket *p = container_of(packey, MUSBPacket, p);
     MUSBEndPoint *ep = p->ep;
@@ -615,7 +615,7 @@ static void musb_packet(MUSBState *s, MUSBEndPoint *ep,
     }
 
     ep->status[dir] = ret;
-    musb_schedule_cb(s->port.dev, &ep->packey[dir].p);
+    musb_schedule_cb(&s->port, &ep->packey[dir].p);
 }
 
 static void musb_tx_packet_complete(USBPacket *packey, void *opaque)
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 95e4623..bd92c31 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -367,15 +367,13 @@ static void ohci_detach(USBPort *port1)
         ohci_set_interrupt(s, OHCI_INTR_RHSC);
 }
 
-static void ohci_wakeup(USBDevice *dev)
+static void ohci_wakeup(USBPort *port1)
 {
-    USBBus *bus = usb_bus_from_device(dev);
-    OHCIState *s = container_of(bus, OHCIState, bus);
-    int portnum = dev->port->index;
-    OHCIPort *port = &s->rhport[portnum];
+    OHCIState *s = port1->opaque;
+    OHCIPort *port = &s->rhport[port1->index];
     uint32_t intr = 0;
     if (port->ctrl & OHCI_PORT_PSS) {
-        DPRINTF("usb-ohci: port %d: wakeup\n", portnum);
+        DPRINTF("usb-ohci: port %d: wakeup\n", port1->index);
         port->ctrl |= OHCI_PORT_PSSC;
         port->ctrl &= ~OHCI_PORT_PSS;
         intr = OHCI_INTR_RHSC;
@@ -602,7 +600,7 @@ static void ohci_copy_iso_td(OHCIState *ohci,
 
 static void ohci_process_lists(OHCIState *ohci, int completion);
 
-static void ohci_async_complete_packet(USBDevice *dev, USBPacket *packet)
+static void ohci_async_complete_packet(USBPort *port, USBPacket *packet)
 {
     OHCIState *ohci = container_of(packet, OHCIState, usb_packet);
 #ifdef DEBUG_PACKET
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index fd25d2a..ab635f6 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -620,11 +620,10 @@ static void uhci_detach(USBPort *port1)
     uhci_resume(s);
 }
 
-static void uhci_wakeup(USBDevice *dev)
+static void uhci_wakeup(USBPort *port1)
 {
-    USBBus *bus = usb_bus_from_device(dev);
-    UHCIState *s = container_of(bus, UHCIState, bus);
-    UHCIPort *port = s->ports + dev->port->index;
+    UHCIState *s = port1->opaque;
+    UHCIPort *port = &s->ports[port1->index];
 
     if (port->ctrl & UHCI_PORT_SUSPEND && !(port->ctrl & UHCI_PORT_RD)) {
         port->ctrl |= UHCI_PORT_RD;
@@ -657,7 +656,7 @@ static int uhci_broadcast_packet(UHCIState *s, USBPacket *p)
     return ret;
 }
 
-static void uhci_async_complete(USBDevice *dev, USBPacket *packet);
+static void uhci_async_complete(USBPort *port, USBPacket *packet);
 static void uhci_process_frame(UHCIState *s);
 
 /* return -1 if fatal error (frame must be stopped)
@@ -849,7 +848,7 @@ done:
     return len;
 }
 
-static void uhci_async_complete(USBDevice *dev, USBPacket *packet)
+static void uhci_async_complete(USBPort *port, USBPacket *packet)
 {
     UHCIAsync *async = container_of(packet, UHCIAsync, packet);
     UHCIState *s = async->uhci;
diff --git a/hw/usb.c b/hw/usb.c
index 4a39cbc..735ffd1 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -52,7 +52,7 @@ void usb_attach(USBPort *port, USBDevice *dev)
 void usb_wakeup(USBDevice *dev)
 {
     if (dev->remote_wakeup && dev->port && dev->port->ops->wakeup) {
-        dev->port->ops->wakeup(dev);
+        dev->port->ops->wakeup(dev->port);
     }
 }
 
@@ -335,7 +335,7 @@ void usb_packet_complete(USBDevice *dev, USBPacket *p)
 {
     /* Note: p->owner != dev is possible in case dev is a hub */
     assert(p->owner != NULL);
-    dev->port->ops->complete(dev, p);
+    dev->port->ops->complete(dev->port, p);
     p->owner = NULL;
 }
 
diff --git a/hw/usb.h b/hw/usb.h
index a5f2efa..65f45a0 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -252,8 +252,13 @@ struct USBDeviceInfo {
 typedef struct USBPortOps {
     void (*attach)(USBPort *port);
     void (*detach)(USBPort *port);
-    void (*wakeup)(USBDevice *dev);
-    void (*complete)(USBDevice *dev, USBPacket *p);
+    void (*wakeup)(USBPort *port);
+    /*
+     * Note that port->dev will be different then the device from which
+     * the packet originated when a hub is involved, if you want the orginating
+     * device use p->owner
+     */
+    void (*complete)(USBPort *port, USBPacket *p);
 } USBPortOps;
 
 /* USB port on which a device can be connected */
commit ae60fea97c78e7f855794f2770517244d93def73
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Jun 24 11:29:56 2011 +0200

    usb: Add a register_companion USB bus op.
    
    This is a preparation patch for adding support for USB companion controllers.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index e37e8a2..b511bac 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -160,6 +160,37 @@ void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
     bus->nfree++;
 }
 
+int usb_register_companion(const char *masterbus, USBPort *ports[],
+                           uint32_t portcount, uint32_t firstport,
+                           void *opaque, USBPortOps *ops, int speedmask)
+{
+    USBBus *bus;
+    int i;
+
+    QTAILQ_FOREACH(bus, &busses, next) {
+        if (strcmp(bus->qbus.name, masterbus) == 0) {
+            break;
+        }
+    }
+
+    if (!bus || !bus->ops->register_companion) {
+        qerror_report(QERR_INVALID_PARAMETER_VALUE, "masterbus",
+                      "an USB masterbus");
+        if (bus) {
+            error_printf_unless_qmp(
+                "USB bus '%s' does not allow companion controllers\n",
+                masterbus);
+        }
+        return -1;
+    }
+
+    for (i = 0; i < portcount; i++) {
+        usb_fill_port(ports[i], opaque, i, ops, speedmask);
+    }
+
+    return bus->ops->register_companion(bus, ports, portcount, firstport);
+}
+
 void usb_port_location(USBPort *downstream, USBPort *upstream, int portnr)
 {
     if (upstream) {
diff --git a/hw/usb.h b/hw/usb.h
index 076e2ff..a5f2efa 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -344,6 +344,8 @@ struct USBBus {
 };
 
 struct USBBusOps {
+    int (*register_companion)(USBBus *bus, USBPort *ports[],
+                              uint32_t portcount, uint32_t firstport);
     void (*device_destroy)(USBBus *bus, USBDevice *dev);
 };
 
@@ -356,6 +358,9 @@ USBDevice *usb_create_simple(USBBus *bus, const char *name);
 USBDevice *usbdevice_create(const char *cmdline);
 void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
                        USBPortOps *ops, int speedmask);
+int usb_register_companion(const char *masterbus, USBPort *ports[],
+                           uint32_t portcount, uint32_t firstport,
+                           void *opaque, USBPortOps *ops, int speedmask);
 void usb_port_location(USBPort *downstream, USBPort *upstream, int portnr);
 void usb_unregister_port(USBBus *bus, USBPort *port);
 int usb_device_attach(USBDevice *dev);
commit 3631e6c8c263528ca159707b9255117a2c3bb175
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Thu Jun 30 12:05:19 2011 +0200

    usb: Move (initial) call of usb_port_location to usb_fill_port
    
    Cleanup / preparation patch for companion controller support. Note that
    as a "side-effect" this patch also fixes the milkymist-softusb controller
    not having a port_location set for its ports.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index 776974e..e37e8a2 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -149,6 +149,7 @@ static void usb_fill_port(USBPort *port, void *opaque, int index,
     port->index = index;
     port->ops = ops;
     port->speedmask = speedmask;
+    usb_port_location(port, NULL, index + 1);
 }
 
 void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index 91fb7de..88cb2c2 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -2206,7 +2206,6 @@ static int usb_ehci_initfn(PCIDevice *dev)
     for(i = 0; i < NB_PORTS; i++) {
         usb_register_port(&s->bus, &s->ports[i], s, i, &ehci_port_ops,
                           USB_SPEED_MASK_HIGH);
-        usb_port_location(&s->ports[i], NULL, i+1);
         s->ports[i].dev = 0;
     }
 
diff --git a/hw/usb-musb.c b/hw/usb-musb.c
index d15971f..84e6017 100644
--- a/hw/usb-musb.c
+++ b/hw/usb-musb.c
@@ -369,7 +369,6 @@ struct MUSBState *musb_init(qemu_irq *irqs)
     usb_bus_new(&s->bus, &musb_bus_ops, NULL /* FIXME */);
     usb_register_port(&s->bus, &s->port, s, 0, &musb_port_ops,
                       USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
-    usb_port_location(&s->port, NULL, 1);
 
     return s;
 }
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 1c29b9f..95e4623 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -1742,7 +1742,6 @@ static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
     for (i = 0; i < num_ports; i++) {
         usb_register_port(&ohci->bus, &ohci->rhport[i].port, ohci, i, &ohci_port_ops,
                           USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
-        usb_port_location(&ohci->rhport[i].port, NULL, i+1);
     }
 
     ohci->async_td = 0;
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 405fa7b..fd25d2a 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -1129,7 +1129,6 @@ static int usb_uhci_common_initfn(PCIDevice *dev)
     for(i = 0; i < NB_PORTS; i++) {
         usb_register_port(&s->bus, &s->ports[i].port, s, i, &uhci_port_ops,
                           USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
-        usb_port_location(&s->ports[i].port, NULL, i+1);
     }
     s->frame_timer = qemu_new_timer_ns(vm_clock, uhci_frame_timer, s);
     s->num_ports_vmstate = NB_PORTS;
commit 090ac6425accf5d87be5ff8087080c876a2904e5
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Thu Jun 30 11:57:57 2011 +0200

    usb: Add a usb_fill_port helper function
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index 2abce12..776974e 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -140,8 +140,8 @@ USBDevice *usb_create_simple(USBBus *bus, const char *name)
     return dev;
 }
 
-void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
-                       USBPortOps *ops, int speedmask)
+static void usb_fill_port(USBPort *port, void *opaque, int index,
+                          USBPortOps *ops, int speedmask)
 {
     port->opaque = opaque;
     port->index = index;
@@ -149,6 +149,12 @@ void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
     port->index = index;
     port->ops = ops;
     port->speedmask = speedmask;
+}
+
+void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
+                       USBPortOps *ops, int speedmask)
+{
+    usb_fill_port(port, opaque, index, ops, speedmask);
     QTAILQ_INSERT_TAIL(&bus->free, port, next);
     bus->nfree++;
 }
commit 000eb4fa525d0b9b2d2b2a2ad4925863af60e5f7
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Jun 14 12:24:04 2011 +0100

    hw/usb-musb.c: Don't misuse usb_packet_complete()
    
    In musb_packet() handle final processing of non-asynchronous
    USB packets by directly calling musb_schedule_cb() rather than
    going through usb_packet_complete(). The latter will trigger
    an assertion because the packet doesn't belong to a device.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-musb.c b/hw/usb-musb.c
index 21f35af..d15971f 100644
--- a/hw/usb-musb.c
+++ b/hw/usb-musb.c
@@ -616,7 +616,7 @@ static void musb_packet(MUSBState *s, MUSBEndPoint *ep,
     }
 
     ep->status[dir] = ret;
-    usb_packet_complete(s->port.dev, &ep->packey[dir].p);
+    musb_schedule_cb(s->port.dev, &ep->packey[dir].p);
 }
 
 static void musb_tx_packet_complete(USBPacket *packey, void *opaque)
commit c925400ba83bd57bf560e071f400012248f1644a
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Mon Jul 4 14:43:58 2011 +0200

    ide: Initialise buffers with zeros
    
    Just in case there's still a way how a guest can read out buffers when it's not
    supposed to, let's zero the buffers during initialisation so that we don't leak
    information to the guest.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Markus Armbruster <armbru at redhat.com>

diff --git a/hw/ide/core.c b/hw/ide/core.c
index a29ae9f..d145b19 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -1789,9 +1789,13 @@ static void ide_init1(IDEBus *bus, int unit)
     s->unit = unit;
     s->drive_serial = drive_serial++;
     /* we need at least 2k alignment for accessing CDROMs using O_DIRECT */
-    s->io_buffer = qemu_memalign(2048, IDE_DMA_BUF_SECTORS*512 + 4);
     s->io_buffer_total_len = IDE_DMA_BUF_SECTORS*512 + 4;
+    s->io_buffer = qemu_memalign(2048, s->io_buffer_total_len);
+    memset(s->io_buffer, 0, s->io_buffer_total_len);
+
     s->smart_selftest_data = qemu_blockalign(s->bs, 512);
+    memset(s->smart_selftest_data, 0, 512);
+
     s->sector_write_timer = qemu_new_timer_ns(vm_clock,
                                            ide_sector_write_timer_cb, s);
 }
commit 40c4ed3f95f0b2ffa0848df0fc311556bb7472a1
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Mon Jul 4 14:07:50 2011 +0200

    ide: Ignore reads during PIO in and writes during PIO out
    
    This fixes https://bugs.launchpad.net/qemu/+bug/786209:
    
        When the DRQ_STAT bit is set, the IDE core permits both data reads
        and data writes, regardless of whether the current transfer was
        initiated as a read or write.
    
        This potentially leaks uninitialized host memory into the guest,
        if, before doing anything else to an IDE device, the guest begins a
        write transaction (e.g. WIN_WRITE), but then *reads* from the IO
        port instead of writing to it.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Markus Armbruster <armbru at redhat.com>

diff --git a/hw/ide/core.c b/hw/ide/core.c
index ca17a43..a29ae9f 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -56,6 +56,7 @@ static const int smart_attributes[][12] = {
 };
 
 static int ide_handle_rw_error(IDEState *s, int error, int op);
+static void ide_dummy_transfer_stop(IDEState *s);
 
 static void padstr(char *str, const char *src, int len)
 {
@@ -1532,15 +1533,36 @@ void ide_cmd_write(void *opaque, uint32_t addr, uint32_t val)
     bus->cmd = val;
 }
 
+/*
+ * Returns true if the running PIO transfer is a PIO out (i.e. data is
+ * transferred from the device to the guest), false if it's a PIO in
+ */
+static bool ide_is_pio_out(IDEState *s)
+{
+    if (s->end_transfer_func == ide_sector_write ||
+        s->end_transfer_func == ide_atapi_cmd) {
+        return false;
+    } else if (s->end_transfer_func == ide_sector_read ||
+               s->end_transfer_func == ide_transfer_stop ||
+               s->end_transfer_func == ide_atapi_cmd_reply_end ||
+               s->end_transfer_func == ide_dummy_transfer_stop) {
+        return true;
+    }
+
+    abort();
+}
+
 void ide_data_writew(void *opaque, uint32_t addr, uint32_t val)
 {
     IDEBus *bus = opaque;
     IDEState *s = idebus_active_if(bus);
     uint8_t *p;
 
-    /* PIO data access allowed only when DRQ bit is set */
-    if (!(s->status & DRQ_STAT))
+    /* PIO data access allowed only when DRQ bit is set. The result of a write
+     * during PIO out is indeterminate, just ignore it. */
+    if (!(s->status & DRQ_STAT) || ide_is_pio_out(s)) {
         return;
+    }
 
     p = s->data_ptr;
     *(uint16_t *)p = le16_to_cpu(val);
@@ -1557,9 +1579,11 @@ uint32_t ide_data_readw(void *opaque, uint32_t addr)
     uint8_t *p;
     int ret;
 
-    /* PIO data access allowed only when DRQ bit is set */
-    if (!(s->status & DRQ_STAT))
+    /* PIO data access allowed only when DRQ bit is set. The result of a read
+     * during PIO in is indeterminate, return 0 and don't move forward. */
+    if (!(s->status & DRQ_STAT) || !ide_is_pio_out(s)) {
         return 0;
+    }
 
     p = s->data_ptr;
     ret = cpu_to_le16(*(uint16_t *)p);
@@ -1576,9 +1600,11 @@ void ide_data_writel(void *opaque, uint32_t addr, uint32_t val)
     IDEState *s = idebus_active_if(bus);
     uint8_t *p;
 
-    /* PIO data access allowed only when DRQ bit is set */
-    if (!(s->status & DRQ_STAT))
+    /* PIO data access allowed only when DRQ bit is set. The result of a write
+     * during PIO out is indeterminate, just ignore it. */
+    if (!(s->status & DRQ_STAT) || ide_is_pio_out(s)) {
         return;
+    }
 
     p = s->data_ptr;
     *(uint32_t *)p = le32_to_cpu(val);
@@ -1595,9 +1621,11 @@ uint32_t ide_data_readl(void *opaque, uint32_t addr)
     uint8_t *p;
     int ret;
 
-    /* PIO data access allowed only when DRQ bit is set */
-    if (!(s->status & DRQ_STAT))
+    /* PIO data access allowed only when DRQ bit is set. The result of a read
+     * during PIO in is indeterminate, return 0 and don't move forward. */
+    if (!(s->status & DRQ_STAT) || !ide_is_pio_out(s)) {
         return 0;
+    }
 
     p = s->data_ptr;
     ret = cpu_to_le32(*(uint32_t *)p);
commit e7ff8f0e0c03853c5018d683b28b338b9738588a
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Fri Jul 1 10:46:13 2011 -0300

    block: drive_init(): Improve CHS setting error message
    
    The current message doesn't clearly communicate the error cause.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Reviewed-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index 470be71..a97a801 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -310,7 +310,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
 	    media = MEDIA_DISK;
 	} else if (!strcmp(buf, "cdrom")) {
             if (cyls || secs || heads) {
-                error_report("'%s' invalid physical CHS format", buf);
+                error_report("CHS can't be set with media=%s", buf);
 	        return NULL;
             }
 	    media = MEDIA_CDROM;
commit 2d3999fe13b5e4663fd8ffc3661b1ffd44130e55
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Fri Jul 1 10:46:12 2011 -0300

    block: drive_init(): Simplify interface type setting
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Reviewed-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index 7d579d6..470be71 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -240,14 +240,6 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
     int ret;
 
     translation = BIOS_ATA_TRANSLATION_AUTO;
-
-    if (default_to_scsi) {
-        type = IF_SCSI;
-        pstrcpy(devname, sizeof(devname), "scsi");
-    } else {
-        type = IF_IDE;
-        pstrcpy(devname, sizeof(devname), "ide");
-    }
     media = MEDIA_DISK;
 
     /* extract parameters */
@@ -273,7 +265,11 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
             error_report("unsupported bus type '%s'", buf);
             return NULL;
 	}
+    } else {
+        type = default_to_scsi ? IF_SCSI : IF_IDE;
+        pstrcpy(devname, sizeof(devname), if_name[type]);
     }
+
     max_devs = if_max_devs[type];
 
     if (cyls || heads || secs) {
commit a8686a9b2b347d0619141e950221c4d6d0311d0b
Author: Markus Armbruster <armbru at redhat.com>
Date:   Mon Jun 20 11:35:18 2011 +0200

    virtio-blk: Turn drive serial into a qdev property
    
    It needs to be a qdev property, because it belongs to the drive's
    guest part.  Precedence: commit a0fef654 and 6ced55a5.
    
    Bonus: info qtree now shows the serial number.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c
index d4a12f7..2bf4821 100644
--- a/hw/s390-virtio-bus.c
+++ b/hw/s390-virtio-bus.c
@@ -128,7 +128,8 @@ static int s390_virtio_blk_init(VirtIOS390Device *dev)
 {
     VirtIODevice *vdev;
 
-    vdev = virtio_blk_init((DeviceState *)dev, &dev->block);
+    vdev = virtio_blk_init((DeviceState *)dev, &dev->block,
+                           &dev->block_serial);
     if (!vdev) {
         return -1;
     }
@@ -355,6 +356,7 @@ static VirtIOS390DeviceInfo s390_virtio_blk = {
     .qdev.size = sizeof(VirtIOS390Device),
     .qdev.props = (Property[]) {
         DEFINE_BLOCK_PROPERTIES(VirtIOS390Device, block),
+        DEFINE_PROP_STRING("serial", VirtIOS390Device, block_serial),
         DEFINE_PROP_END_OF_LIST(),
     },
 };
diff --git a/hw/s390-virtio-bus.h b/hw/s390-virtio-bus.h
index 0c412d0..f1bece7 100644
--- a/hw/s390-virtio-bus.h
+++ b/hw/s390-virtio-bus.h
@@ -42,6 +42,7 @@ typedef struct VirtIOS390Device {
     uint8_t feat_len;
     VirtIODevice *vdev;
     BlockConf block;
+    char *block_serial;
     NICConf nic;
     uint32_t host_features;
     virtio_serial_conf serial;
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 91e0394..6471ac8 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -28,8 +28,8 @@ typedef struct VirtIOBlock
     void *rq;
     QEMUBH *bh;
     BlockConf *conf;
+    char *serial;
     unsigned short sector_mask;
-    char sn[BLOCK_SERIAL_STRLEN];
     DeviceState *qdev;
 } VirtIOBlock;
 
@@ -362,8 +362,13 @@ static void virtio_blk_handle_request(VirtIOBlockReq *req,
     } else if (type & VIRTIO_BLK_T_GET_ID) {
         VirtIOBlock *s = req->dev;
 
-        memcpy(req->elem.in_sg[0].iov_base, s->sn,
-               MIN(req->elem.in_sg[0].iov_len, sizeof(s->sn)));
+        /*
+         * NB: per existing s/n string convention the string is
+         * terminated by '\0' only when shorter than buffer.
+         */
+        strncpy(req->elem.in_sg[0].iov_base,
+                s->serial ? s->serial : "",
+                MIN(req->elem.in_sg[0].iov_len, VIRTIO_BLK_ID_BYTES));
         virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
     } else if (type & VIRTIO_BLK_T_OUT) {
         qemu_iovec_init_external(&req->qiov, &req->elem.out_sg[1],
@@ -531,7 +536,8 @@ static void virtio_blk_change_cb(void *opaque, int reason)
     }
 }
 
-VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf)
+VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf,
+                              char **serial)
 {
     VirtIOBlock *s;
     int cylinders, heads, secs;
@@ -547,6 +553,14 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf)
         return NULL;
     }
 
+    if (!*serial) {
+        /* try to fall back to value set with legacy -drive serial=... */
+        dinfo = drive_get_by_blockdev(conf->bs);
+        if (*dinfo->serial) {
+            *serial = strdup(dinfo->serial);
+        }
+    }
+
     s = (VirtIOBlock *)virtio_common_init("virtio-blk", VIRTIO_ID_BLOCK,
                                           sizeof(struct virtio_blk_config),
                                           sizeof(VirtIOBlock));
@@ -556,16 +570,11 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf)
     s->vdev.reset = virtio_blk_reset;
     s->bs = conf->bs;
     s->conf = conf;
+    s->serial = *serial;
     s->rq = NULL;
     s->sector_mask = (s->conf->logical_block_size / BDRV_SECTOR_SIZE) - 1;
     bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs);
 
-    /* NB: per existing s/n string convention the string is terminated
-     * by '\0' only when less than sizeof (s->sn)
-     */
-    dinfo = drive_get_by_blockdev(s->bs);
-    strncpy(s->sn, dinfo->serial, sizeof (s->sn));
-
     s->vq = virtio_add_queue(&s->vdev, 128, virtio_blk_handle_output);
 
     qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s);
diff --git a/hw/virtio-blk.h b/hw/virtio-blk.h
index fff46da..5645d2b 100644
--- a/hw/virtio-blk.h
+++ b/hw/virtio-blk.h
@@ -34,6 +34,8 @@
 #define VIRTIO_BLK_F_WCACHE     9       /* write cache enabled */
 #define VIRTIO_BLK_F_TOPOLOGY   10      /* Topology information is available */
 
+#define VIRTIO_BLK_ID_BYTES     20      /* ID string length */
+
 struct virtio_blk_config
 {
     uint64_t capacity;
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index b3e7ba5..d685243 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -700,7 +700,8 @@ static int virtio_blk_init_pci(PCIDevice *pci_dev)
         proxy->class_code != PCI_CLASS_STORAGE_OTHER)
         proxy->class_code = PCI_CLASS_STORAGE_SCSI;
 
-    vdev = virtio_blk_init(&pci_dev->qdev, &proxy->block);
+    vdev = virtio_blk_init(&pci_dev->qdev, &proxy->block,
+                           &proxy->block_serial);
     if (!vdev) {
         return -1;
     }
@@ -805,6 +806,7 @@ static PCIDeviceInfo virtio_info[] = {
         .qdev.props = (Property[]) {
             DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
             DEFINE_BLOCK_PROPERTIES(VirtIOPCIProxy, block),
+            DEFINE_PROP_STRING("serial", VirtIOPCIProxy, block_serial),
             DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
                             VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
             DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
diff --git a/hw/virtio-pci.h b/hw/virtio-pci.h
index b518917..1f0de56 100644
--- a/hw/virtio-pci.h
+++ b/hw/virtio-pci.h
@@ -26,6 +26,7 @@ typedef struct {
     uint32_t class_code;
     uint32_t nvectors;
     BlockConf block;
+    char *block_serial;
     NICConf nic;
     uint32_t host_features;
 #ifdef CONFIG_LINUX
diff --git a/hw/virtio.h b/hw/virtio.h
index 69e6bb1..0fd0bb0 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -197,7 +197,8 @@ void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding,
                         void *opaque);
 
 /* Base devices.  */
-VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf);
+VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf,
+                              char **serial);
 struct virtio_net_conf;
 VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
                               struct virtio_net_conf *net);
commit 343f85685ce3f9613c13e4d0f884698194b6a4f6
Author: Johannes Stezenbach <js at sig21.net>
Date:   Wed Jun 29 16:25:17 2011 +0200

    block/raw-posix: Linux compat-ioctl warning workaround
    
    On Linux x86_64 host with 32bit userspace, running
    qemu or even just "qemu-img create -f qcow2 some.img 1G"
    causes a kernel warning:
    
    ioctl32(qemu-img:5296): Unknown cmd fd(3) cmd(00005326){t:'S';sz:0} arg(7fffffff) on some.img
    ioctl32(qemu-img:5296): Unknown cmd fd(3) cmd(801c0204){t:02;sz:28} arg(fff77350) on some.img
    
    ioctl 00005326 is CDROM_DRIVE_STATUS,
    ioctl 801c0204 is FDGETPRM.
    
    The warning appears because the Linux compat-ioctl handler for these
    ioctls only applies to block devices, while qemu also uses the ioctls on
    plain files.  Work around by calling fstat() the ensure the ioctls are
    only used on block devices.
    
    Signed-off-by: Johannes Stezenbach <js at sig21.net>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/raw-posix.c b/block/raw-posix.c
index 4cd7d7a..34b64aa 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -46,6 +46,8 @@
 #include <sys/dkio.h>
 #endif
 #ifdef __linux__
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <sys/ioctl.h>
 #include <sys/param.h>
 #include <linux/cdrom.h>
@@ -1188,6 +1190,7 @@ static int floppy_probe_device(const char *filename)
     int fd, ret;
     int prio = 0;
     struct floppy_struct fdparam;
+    struct stat st;
 
     if (strstart(filename, "/dev/fd", NULL))
         prio = 50;
@@ -1196,12 +1199,17 @@ static int floppy_probe_device(const char *filename)
     if (fd < 0) {
         goto out;
     }
+    ret = fstat(fd, &st);
+    if (ret == -1 || !S_ISBLK(st.st_mode)) {
+        goto outc;
+    }
 
     /* Attempt to detect via a floppy specific ioctl */
     ret = ioctl(fd, FDGETPRM, &fdparam);
     if (ret >= 0)
         prio = 100;
 
+outc:
     close(fd);
 out:
     return prio;
@@ -1290,17 +1298,23 @@ static int cdrom_probe_device(const char *filename)
 {
     int fd, ret;
     int prio = 0;
+    struct stat st;
 
     fd = open(filename, O_RDONLY | O_NONBLOCK);
     if (fd < 0) {
         goto out;
     }
+    ret = fstat(fd, &st);
+    if (ret == -1 || !S_ISBLK(st.st_mode)) {
+        goto outc;
+    }
 
     /* Attempt to detect via a CDROM specific ioctl */
     ret = ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
     if (ret >= 0)
         prio = 100;
 
+outc:
     close(fd);
 out:
     return prio;
commit 661a0f712b7c5b78408d85ba8b7f47ce44f395c0
Author: Federico Simoncelli <fsimonce at redhat.com>
Date:   Mon Jun 20 12:48:19 2011 -0400

    qemu-img: Add cache command line option
    
    qemu-img currently writes disk images using writeback and filling
    up the cache buffers which are then flushed by the kernel preventing
    other processes from accessing the storage.
    This is particularly bad in cluster environments where time-based
    algorithms might be in place and accessing the storage within
    certain timeouts is critical.
    This patch adds the option to choose a cache method when writing
    disk images.
    
    Signed-off-by: Federico Simoncelli <fsimonce at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
index 3072d38..2b70618 100644
--- a/qemu-img-cmds.hx
+++ b/qemu-img-cmds.hx
@@ -22,13 +22,13 @@ STEXI
 ETEXI
 
 DEF("commit", img_commit,
-    "commit [-f fmt] filename")
+    "commit [-f fmt] [-t cache] filename")
 STEXI
 @item commit [-f @var{fmt}] @var{filename}
 ETEXI
 
 DEF("convert", img_convert,
-    "convert [-c] [-p] [-f fmt] [-O output_fmt] [-o options] [-s snapshot_name] filename [filename2 [...]] output_filename")
+    "convert [-c] [-p] [-f fmt] [-t cache] [-O output_fmt] [-o options] [-s snapshot_name] filename [filename2 [...]] output_filename")
 STEXI
 @item convert [-c] [-f @var{fmt}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] @var{filename} [@var{filename2} [...]] @var{output_filename}
 ETEXI
@@ -46,7 +46,7 @@ STEXI
 ETEXI
 
 DEF("rebase", img_rebase,
-    "rebase [-f fmt] [-p] [-u] -b backing_file [-F backing_fmt] filename")
+    "rebase [-f fmt] [-t cache] [-p] [-u] -b backing_file [-F backing_fmt] filename")
 STEXI
 @item rebase [-f @var{fmt}] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename}
 ETEXI
diff --git a/qemu-img.c b/qemu-img.c
index 32628b3..54137a4 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -40,6 +40,7 @@ typedef struct img_cmd_t {
 
 /* Default to cache=writeback as data integrity is not important for qemu-tcg. */
 #define BDRV_O_FLAGS BDRV_O_CACHE_WB
+#define BDRV_DEFAULT_CACHE "writeback"
 
 static void format_print(void *opaque, const char *name)
 {
@@ -64,6 +65,8 @@ static void help(void)
            "Command parameters:\n"
            "  'filename' is a disk image filename\n"
            "  'fmt' is the disk image format. It is guessed automatically in most cases\n"
+           "  'cache' is the cache mode used to write the output disk image, the valid\n"
+           "    options are: 'none', 'writeback' (default), 'writethrough' and 'unsafe'\n"
            "  'size' is the disk image size in bytes. Optional suffixes\n"
            "    'k' or 'K' (kilobyte, 1024), 'M' (megabyte, 1024k), 'G' (gigabyte, 1024M)\n"
            "    and T (terabyte, 1024G) are supported. 'b' is ignored.\n"
@@ -180,6 +183,27 @@ static int read_password(char *buf, int buf_size)
 }
 #endif
 
+static int set_cache_flag(const char *mode, int *flags)
+{
+    *flags &= ~BDRV_O_CACHE_MASK;
+
+    if (!strcmp(mode, "none") || !strcmp(mode, "off")) {
+        *flags |= BDRV_O_CACHE_WB;
+        *flags |= BDRV_O_NOCACHE;
+    } else if (!strcmp(mode, "writeback")) {
+        *flags |= BDRV_O_CACHE_WB;
+    } else if (!strcmp(mode, "unsafe")) {
+        *flags |= BDRV_O_CACHE_WB;
+        *flags |= BDRV_O_NO_FLUSH;
+    } else if (!strcmp(mode, "writethrough")) {
+        /* this is the default */
+    } else {
+        return -1;
+    }
+
+    return 0;
+}
+
 static int print_block_option_help(const char *filename, const char *fmt)
 {
     BlockDriver *drv, *proto_drv;
@@ -441,13 +465,14 @@ static int img_check(int argc, char **argv)
 
 static int img_commit(int argc, char **argv)
 {
-    int c, ret;
-    const char *filename, *fmt;
+    int c, ret, flags;
+    const char *filename, *fmt, *cache;
     BlockDriverState *bs;
 
     fmt = NULL;
+    cache = BDRV_DEFAULT_CACHE;
     for(;;) {
-        c = getopt(argc, argv, "f:h");
+        c = getopt(argc, argv, "f:ht:");
         if (c == -1) {
             break;
         }
@@ -459,6 +484,9 @@ static int img_commit(int argc, char **argv)
         case 'f':
             fmt = optarg;
             break;
+        case 't':
+            cache = optarg;
+            break;
         }
     }
     if (optind >= argc) {
@@ -466,7 +494,14 @@ static int img_commit(int argc, char **argv)
     }
     filename = argv[optind++];
 
-    bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR);
+    flags = BDRV_O_RDWR;
+    ret = set_cache_flag(cache, &flags);
+    if (ret < 0) {
+        error_report("Invalid cache option: %s", cache);
+        return -1;
+    }
+
+    bs = bdrv_new_open(filename, fmt, flags);
     if (!bs) {
         return 1;
     }
@@ -591,8 +626,8 @@ static int compare_sectors(const uint8_t *buf1, const uint8_t *buf2, int n,
 static int img_convert(int argc, char **argv)
 {
     int c, ret = 0, n, n1, bs_n, bs_i, compress, cluster_size, cluster_sectors;
-    int progress = 0;
-    const char *fmt, *out_fmt, *out_baseimg, *out_filename;
+    int progress = 0, flags;
+    const char *fmt, *out_fmt, *cache, *out_baseimg, *out_filename;
     BlockDriver *drv, *proto_drv;
     BlockDriverState **bs = NULL, *out_bs = NULL;
     int64_t total_sectors, nb_sectors, sector_num, bs_offset;
@@ -608,10 +643,11 @@ static int img_convert(int argc, char **argv)
 
     fmt = NULL;
     out_fmt = "raw";
+    cache = "unsafe";
     out_baseimg = NULL;
     compress = 0;
     for(;;) {
-        c = getopt(argc, argv, "f:O:B:s:hce6o:p");
+        c = getopt(argc, argv, "f:O:B:s:hce6o:pt:");
         if (c == -1) {
             break;
         }
@@ -649,6 +685,9 @@ static int img_convert(int argc, char **argv)
         case 'p':
             progress = 1;
             break;
+        case 't':
+            cache = optarg;
+            break;
         }
     }
 
@@ -779,8 +818,14 @@ static int img_convert(int argc, char **argv)
         goto out;
     }
 
-    out_bs = bdrv_new_open(out_filename, out_fmt,
-        BDRV_O_FLAGS | BDRV_O_RDWR | BDRV_O_NO_FLUSH);
+    flags = BDRV_O_RDWR;
+    ret = set_cache_flag(cache, &flags);
+    if (ret < 0) {
+        error_report("Invalid cache option: %s", cache);
+        return -1;
+    }
+
+    out_bs = bdrv_new_open(out_filename, out_fmt, flags);
     if (!out_bs) {
         ret = -1;
         goto out;
@@ -1225,18 +1270,18 @@ static int img_rebase(int argc, char **argv)
     BlockDriverState *bs, *bs_old_backing = NULL, *bs_new_backing = NULL;
     BlockDriver *old_backing_drv, *new_backing_drv;
     char *filename;
-    const char *fmt, *out_basefmt, *out_baseimg;
+    const char *fmt, *cache, *out_basefmt, *out_baseimg;
     int c, flags, ret;
     int unsafe = 0;
     int progress = 0;
 
     /* Parse commandline parameters */
     fmt = NULL;
+    cache = BDRV_DEFAULT_CACHE;
     out_baseimg = NULL;
     out_basefmt = NULL;
-
     for(;;) {
-        c = getopt(argc, argv, "uhf:F:b:p");
+        c = getopt(argc, argv, "uhf:F:b:pt:");
         if (c == -1) {
             break;
         }
@@ -1260,6 +1305,9 @@ static int img_rebase(int argc, char **argv)
         case 'p':
             progress = 1;
             break;
+        case 't':
+            cache = optarg;
+            break;
         }
     }
 
@@ -1271,13 +1319,19 @@ static int img_rebase(int argc, char **argv)
     qemu_progress_init(progress, 2.0);
     qemu_progress_print(0, 100);
 
+    flags = BDRV_O_RDWR | (unsafe ? BDRV_O_NO_BACKING : 0);
+    ret = set_cache_flag(cache, &flags);
+    if (ret < 0) {
+        error_report("Invalid cache option: %s", cache);
+        return -1;
+    }
+
     /*
      * Open the images.
      *
      * Ignore the old backing file for unsafe rebase in case we want to correct
      * the reference to a renamed or moved backing file.
      */
-    flags = BDRV_O_FLAGS | BDRV_O_RDWR | (unsafe ? BDRV_O_NO_BACKING : 0);
     bs = bdrv_new_open(filename, fmt, flags);
     if (!bs) {
         return 1;
commit 02854532c215872b2af5ed48af93b7a309de1b1b
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Jun 28 13:41:07 2011 +0200

    Documentation: Remove outdated host_device note
    
    People shouldn't explicitly specify host_device any more. raw is doing the
    Right Thing.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qemu-img.texi b/qemu-img.texi
index ced64a4..526474c 100644
--- a/qemu-img.texi
+++ b/qemu-img.texi
@@ -173,12 +173,6 @@ Linux or NTFS on Windows), then only the written sectors will reserve
 space. Use @code{qemu-img info} to know the real size used by the
 image or @code{ls -ls} on Unix/Linux.
 
- at item host_device
-
-Host device format. This format should be used instead of raw when
-converting to block devices or other devices where "holes" are not
-supported.
-
 @item qcow2
 QEMU image format, the most versatile format. Use it to have smaller
 images (useful if your filesystem does not supports holes, for example
commit 9312805d33e8b106bae356d13a8071fb37d75554
Author: Vasily Khoruzhick <anarsoul at gmail.com>
Date:   Fri Jun 17 13:04:36 2011 +0300

    pxa2xx_lcd: add proper rotation support
    
    Until now, pxa2xx_lcd only supported 90deg rotation, but
    some machines (for example Zipit Z2) needs 270deg rotation.
    
    Signed-off-by: Vasily Khoruzhick <anarsoul at gmail.com>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/framebuffer.c b/hw/framebuffer.c
index 24cdf25..56cf16e 100644
--- a/hw/framebuffer.c
+++ b/hw/framebuffer.c
@@ -78,6 +78,9 @@ void framebuffer_update_display(
     dest = ds_get_data(ds);
     if (dest_col_pitch < 0)
         dest -= dest_col_pitch * (cols - 1);
+    if (dest_row_pitch < 0) {
+        dest -= dest_row_pitch * (rows - 1);
+    }
     first = -1;
     addr = pd;
 
diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c
index e524802..a5f8c51 100644
--- a/hw/pxa2xx_lcd.c
+++ b/hw/pxa2xx_lcd.c
@@ -665,7 +665,7 @@ static void pxa2xx_palette_parse(PXA2xxLCDState *s, int ch, int bpp)
     }
 }
 
-static void pxa2xx_lcdc_dma0_redraw_horiz(PXA2xxLCDState *s,
+static void pxa2xx_lcdc_dma0_redraw_rot0(PXA2xxLCDState *s,
                 target_phys_addr_t addr, int *miny, int *maxy)
 {
     int src_width, dest_width;
@@ -692,7 +692,7 @@ static void pxa2xx_lcdc_dma0_redraw_horiz(PXA2xxLCDState *s,
                                fn, s->dma_ch[0].palette, miny, maxy);
 }
 
-static void pxa2xx_lcdc_dma0_redraw_vert(PXA2xxLCDState *s,
+static void pxa2xx_lcdc_dma0_redraw_rot90(PXA2xxLCDState *s,
                target_phys_addr_t addr, int *miny, int *maxy)
 {
     int src_width, dest_width;
@@ -720,6 +720,67 @@ static void pxa2xx_lcdc_dma0_redraw_vert(PXA2xxLCDState *s,
                                miny, maxy);
 }
 
+static void pxa2xx_lcdc_dma0_redraw_rot180(PXA2xxLCDState *s,
+                target_phys_addr_t addr, int *miny, int *maxy)
+{
+    int src_width, dest_width;
+    drawfn fn = NULL;
+    if (s->dest_width) {
+        fn = s->line_fn[s->transp][s->bpp];
+    }
+    if (!fn) {
+        return;
+    }
+
+    src_width = (s->xres + 3) & ~3;     /* Pad to a 4 pixels multiple */
+    if (s->bpp == pxa_lcdc_19pbpp || s->bpp == pxa_lcdc_18pbpp) {
+        src_width *= 3;
+    } else if (s->bpp > pxa_lcdc_16bpp) {
+        src_width *= 4;
+    } else if (s->bpp > pxa_lcdc_8bpp) {
+        src_width *= 2;
+    }
+
+    dest_width = s->xres * s->dest_width;
+    *miny = 0;
+    framebuffer_update_display(s->ds,
+                               addr, s->xres, s->yres,
+                               src_width, -dest_width, -s->dest_width,
+                               s->invalidated,
+                               fn, s->dma_ch[0].palette, miny, maxy);
+}
+
+static void pxa2xx_lcdc_dma0_redraw_rot270(PXA2xxLCDState *s,
+               target_phys_addr_t addr, int *miny, int *maxy)
+{
+    int src_width, dest_width;
+    drawfn fn = NULL;
+    if (s->dest_width) {
+        fn = s->line_fn[s->transp][s->bpp];
+    }
+    if (!fn) {
+        return;
+    }
+
+    src_width = (s->xres + 3) & ~3;     /* Pad to a 4 pixels multiple */
+    if (s->bpp == pxa_lcdc_19pbpp || s->bpp == pxa_lcdc_18pbpp) {
+        src_width *= 3;
+    } else if (s->bpp > pxa_lcdc_16bpp) {
+        src_width *= 4;
+    } else if (s->bpp > pxa_lcdc_8bpp) {
+        src_width *= 2;
+    }
+
+    dest_width = s->yres * s->dest_width;
+    *miny = 0;
+    framebuffer_update_display(s->ds,
+                               addr, s->xres, s->yres,
+                               src_width, -s->dest_width, dest_width,
+                               s->invalidated,
+                               fn, s->dma_ch[0].palette,
+                               miny, maxy);
+}
+
 static void pxa2xx_lcdc_resize(PXA2xxLCDState *s)
 {
     int width, height;
@@ -730,10 +791,11 @@ static void pxa2xx_lcdc_resize(PXA2xxLCDState *s)
     height = LCCR2_LPP(s->control[2]) + 1;
 
     if (width != s->xres || height != s->yres) {
-        if (s->orientation)
+        if (s->orientation == 90 || s->orientation == 270) {
             qemu_console_resize(s->ds, height, width);
-        else
+        } else {
             qemu_console_resize(s->ds, width, height);
+        }
         s->invalidated = 1;
         s->xres = width;
         s->yres = height;
@@ -797,10 +859,24 @@ static void pxa2xx_update_display(void *opaque)
     }
 
     if (miny >= 0) {
-        if (s->orientation)
-            dpy_update(s->ds, miny, 0, maxy - miny, s->xres);
-        else
-            dpy_update(s->ds, 0, miny, s->xres, maxy - miny);
+        switch (s->orientation) {
+        case 0:
+            dpy_update(s->ds, 0, miny, s->xres, maxy - miny + 1);
+            break;
+        case 90:
+            dpy_update(s->ds, miny, 0, maxy - miny + 1, s->xres);
+            break;
+        case 180:
+            maxy = s->yres - maxy - 1;
+            miny = s->yres - miny - 1;
+            dpy_update(s->ds, 0, maxy, s->xres, miny - maxy + 1);
+            break;
+        case 270:
+            maxy = s->yres - maxy - 1;
+            miny = s->yres - miny - 1;
+            dpy_update(s->ds, maxy, 0, miny - maxy + 1, s->xres);
+            break;
+        }
     }
     pxa2xx_lcdc_int_update(s);
 
@@ -822,10 +898,19 @@ static void pxa2xx_lcdc_orientation(void *opaque, int angle)
 {
     PXA2xxLCDState *s = (PXA2xxLCDState *) opaque;
 
-    if (angle) {
-        s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_vert;
-    } else {
-        s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_horiz;
+    switch (angle) {
+    case 0:
+        s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_rot0;
+        break;
+    case 90:
+        s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_rot90;
+        break;
+    case 180:
+        s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_rot180;
+        break;
+    case 270:
+        s->dma_ch[0].redraw = pxa2xx_lcdc_dma0_redraw_rot270;
+        break;
     }
 
     s->orientation = angle;
diff --git a/input.c b/input.c
index 5664d3a..f0a02e7 100644
--- a/input.c
+++ b/input.c
@@ -148,7 +148,7 @@ void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
     QEMUPutMouseEntry *entry;
     QEMUPutMouseEvent *mouse_event;
     void *mouse_event_opaque;
-    int width;
+    int width, height;
 
     if (QTAILQ_EMPTY(&mouse_handlers)) {
         return;
@@ -160,15 +160,31 @@ void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
     mouse_event_opaque = entry->qemu_put_mouse_event_opaque;
 
     if (mouse_event) {
-        if (graphic_rotate) {
-            if (entry->qemu_put_mouse_event_absolute) {
-                width = 0x7fff;
-            } else {
-                width = graphic_width - 1;
-            }
-            mouse_event(mouse_event_opaque, width - dy, dx, dz, buttons_state);
+        if (entry->qemu_put_mouse_event_absolute) {
+            width = 0x7fff;
+            height = 0x7fff;
         } else {
-            mouse_event(mouse_event_opaque, dx, dy, dz, buttons_state);
+            width = graphic_width - 1;
+            height = graphic_height - 1;
+        }
+
+        switch (graphic_rotate) {
+        case 0:
+            mouse_event(mouse_event_opaque,
+                        dx, dy, dz, buttons_state);
+            break;
+        case 90:
+            mouse_event(mouse_event_opaque,
+                        width - dy, dx, dz, buttons_state);
+            break;
+        case 180:
+            mouse_event(mouse_event_opaque,
+                        width - dx, height - dy, dz, buttons_state);
+            break;
+        case 270:
+            mouse_event(mouse_event_opaque,
+                        dy, height - dx, dz, buttons_state);
+            break;
         }
     }
 }
diff --git a/qemu-options.hx b/qemu-options.hx
index 37e54ee..e6d7adc 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -787,6 +787,15 @@ STEXI
 Rotate graphical output 90 deg left (only PXA LCD).
 ETEXI
 
+DEF("rotate", HAS_ARG, QEMU_OPTION_rotate,
+    "-rotate <deg>   rotate graphical output some deg left (only PXA LCD)\n",
+    QEMU_ARCH_ALL)
+STEXI
+ at item -rotate
+ at findex -rotate
+Rotate graphical output some deg left (only PXA LCD).
+ETEXI
+
 DEF("vga", HAS_ARG, QEMU_OPTION_vga,
     "-vga [std|cirrus|vmware|qxl|xenfb|none]\n"
     "                select video card type\n", QEMU_ARCH_ALL)
diff --git a/vl.c b/vl.c
index 52402a2..fcd7395 100644
--- a/vl.c
+++ b/vl.c
@@ -2300,7 +2300,16 @@ int main(int argc, char **argv, char **envp)
 #endif
                 break;
             case QEMU_OPTION_portrait:
-                graphic_rotate = 1;
+                graphic_rotate = 90;
+                break;
+            case QEMU_OPTION_rotate:
+                graphic_rotate = strtol(optarg, (char **) &optarg, 10);
+                if (graphic_rotate != 0 && graphic_rotate != 90 &&
+                    graphic_rotate != 180 && graphic_rotate != 270) {
+                    fprintf(stderr,
+                        "qemu: only 90, 180, 270 deg rotation is available\n");
+                    exit(1);
+                }
                 break;
             case QEMU_OPTION_kernel:
                 kernel_filename = optarg;
commit 462a8bc6468912b79629f20f18798558342ce315
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Thu Jun 23 17:53:48 2011 +0200

    arm: Add const attribute to some arm_boot_info pointers
    
    Parameter 'info' is const, so add the missing attribute.
    
    v2:
    Add 'const' to the local variable info in do_cpu_reset() and to
    the boot_info field in CPUARMState (suggested by Peter Maydell).
    
    Cc: Andrzej Zaborowski <balrogg at gmail.com>
    Cc: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/arm-misc.h b/hw/arm-misc.h
index 010acb4..9aeeaea 100644
--- a/hw/arm-misc.h
+++ b/hw/arm-misc.h
@@ -31,7 +31,7 @@ struct arm_boot_info {
     target_phys_addr_t smp_priv_base;
     int nb_cpus;
     int board_id;
-    int (*atag_board)(struct arm_boot_info *info, void *p);
+    int (*atag_board)(const struct arm_boot_info *info, void *p);
     /* Used internally by arm_boot.c */
     int is_linux;
     target_phys_addr_t initrd_size;
diff --git a/hw/arm_boot.c b/hw/arm_boot.c
index bfac982..e021576 100644
--- a/hw/arm_boot.c
+++ b/hw/arm_boot.c
@@ -49,7 +49,7 @@ static uint32_t smpboot[] = {
     p += 4;                       \
 } while (0)
 
-static void set_kernel_args(struct arm_boot_info *info,
+static void set_kernel_args(const struct arm_boot_info *info,
                 int initrd_size, target_phys_addr_t base)
 {
     target_phys_addr_t p;
@@ -102,7 +102,7 @@ static void set_kernel_args(struct arm_boot_info *info,
     WRITE_WORD(p, 0);
 }
 
-static void set_kernel_args_old(struct arm_boot_info *info,
+static void set_kernel_args_old(const struct arm_boot_info *info,
                 int initrd_size, target_phys_addr_t base)
 {
     target_phys_addr_t p;
@@ -178,7 +178,7 @@ static void set_kernel_args_old(struct arm_boot_info *info,
 static void do_cpu_reset(void *opaque)
 {
     CPUState *env = opaque;
-    struct arm_boot_info *info = env->boot_info;
+    const struct arm_boot_info *info = env->boot_info;
 
     cpu_reset(env);
     if (info) {
diff --git a/hw/nseries.c b/hw/nseries.c
index 2f6f473..2f84f53 100644
--- a/hw/nseries.c
+++ b/hw/nseries.c
@@ -1254,12 +1254,12 @@ static int n8x0_atag_setup(void *p, int model)
     return (void *) w - p;
 }
 
-static int n800_atag_setup(struct arm_boot_info *info, void *p)
+static int n800_atag_setup(const struct arm_boot_info *info, void *p)
 {
     return n8x0_atag_setup(p, 800);
 }
 
-static int n810_atag_setup(struct arm_boot_info *info, void *p)
+static int n810_atag_setup(const struct arm_boot_info *info, void *p)
 {
     return n8x0_atag_setup(p, 810);
 }
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 116131e..1022a03 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -221,7 +221,7 @@ typedef struct CPUARMState {
         void *opaque;
     } cp[15];
     void *nvic;
-    struct arm_boot_info *boot_info;
+    const struct arm_boot_info *boot_info;
 } CPUARMState;
 
 CPUARMState *cpu_arm_init(const char *cpu_model);
commit a3d14054d727efb8ff4c5060a4c3171bae2046ef
Author: Alon Levy <alevy at redhat.com>
Date:   Wed Jun 29 13:57:11 2011 +0200

    qxl: allow QXL_IO_LOG also in vga
    
    The driver may change us to vga mode and still issue a QXL_IO_LOG,
    which we can easily support.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl.c b/hw/qxl.c
index 848c90f..0b9a4c7 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -943,6 +943,7 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
     case QXL_IO_MEMSLOT_DEL:
     case QXL_IO_CREATE_PRIMARY:
     case QXL_IO_UPDATE_IRQ:
+    case QXL_IO_LOG:
         break;
     default:
         if (d->mode == QXL_MODE_NATIVE || d->mode == QXL_MODE_COMPAT)
commit 81144d1a3675faf3c314ff2c7a369f809361d3ed
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Jun 24 12:23:44 2011 +0200

    qxl: put QXL_IO_UPDATE_IRQ into vgamode whitelist
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl.c b/hw/qxl.c
index 5e49536..848c90f 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -942,6 +942,7 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
     case QXL_IO_MEMSLOT_ADD:
     case QXL_IO_MEMSLOT_DEL:
     case QXL_IO_CREATE_PRIMARY:
+    case QXL_IO_UPDATE_IRQ:
         break;
     default:
         if (d->mode == QXL_MODE_NATIVE || d->mode == QXL_MODE_COMPAT)
commit 868379ce6994a72c617fbc29bcc95e8166833400
Author: Yonit Halperin <yhalperi at redhat.com>
Date:   Mon Jul 4 15:08:01 2011 +0300

    qxl: make sure primary surface is saved on migration
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl.c b/hw/qxl.c
index d55b68d..5e49536 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1184,11 +1184,14 @@ static void qxl_vm_change_state_handler(void *opaque, int running, int reason)
     qemu_spice_vm_change_state_handler(&qxl->ssd, running, reason);
 
     if (!running && qxl->mode == QXL_MODE_NATIVE) {
-        /* dirty all vram (which holds surfaces) to make sure it is saved */
+        /* dirty all vram (which holds surfaces) and devram (primary surface)
+         * to make sure they are saved */
         /* FIXME #1: should go out during "live" stage */
         /* FIXME #2: we only need to save the areas which are actually used */
-        ram_addr_t addr = qxl->vram_offset;
-        qxl_set_dirty(addr, addr + qxl->vram_size);
+        ram_addr_t vram_addr = qxl->vram_offset;
+        ram_addr_t surface0_addr = qxl->vga.vram_offset + qxl->shadow_rom.draw_area_offset;
+        qxl_set_dirty(vram_addr, vram_addr + qxl->vram_size);
+        qxl_set_dirty(surface0_addr, surface0_addr + qxl->shadow_rom.surface0_area_size);
     }
 }
 
commit 6ebebb551ad1a5c4e24d3fccd246c5111450c1b3
Author: Alon Levy <alevy at redhat.com>
Date:   Wed Jun 29 13:57:15 2011 +0200

    qxl: add dev id to guest prints
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl.c b/hw/qxl.c
index 3722f55..d55b68d 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -985,7 +985,8 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
         break;
     case QXL_IO_LOG:
         if (d->guestdebug) {
-            fprintf(stderr, "qxl/guest: %s", d->ram->log_buf);
+            fprintf(stderr, "qxl/guest-%d: %ld: %s", d->id,
+                    qemu_get_clock_ns(vm_clock), d->ram->log_buf);
         }
         break;
     case QXL_IO_RESET:
commit 1f0ff2fb99eb5043ea38474c961e0fb9f6ff8a63
Author: Alon Levy <alevy at redhat.com>
Date:   Wed Jun 29 13:57:13 2011 +0200

    qxl-logger: add timestamp to command log
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl-logger.c b/hw/qxl-logger.c
index 76f43e6..74cadba 100644
--- a/hw/qxl-logger.c
+++ b/hw/qxl-logger.c
@@ -19,6 +19,7 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "qemu-timer.h"
 #include "qxl.h"
 
 static const char *qxl_type[] = {
@@ -223,7 +224,8 @@ void qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext)
     if (!qxl->cmdlog) {
         return;
     }
-    fprintf(stderr, "qxl-%d/%s:", qxl->id, ring);
+    fprintf(stderr, "%ld qxl-%d/%s:", qemu_get_clock_ns(vm_clock),
+            qxl->id, ring);
     fprintf(stderr, " cmd @ 0x%" PRIx64 " %s%s", ext->cmd.data,
             qxl_name(qxl_type, ext->cmd.type),
             compat ? "(compat)" : "");
commit 5b77870ce0edde6cf6dd242fa892e28f5c87b4fd
Author: Alon Levy <alevy at redhat.com>
Date:   Fri Jun 24 15:02:47 2011 +0200

    qxl: interface_get_command: fix reported mode
    
    report correct mode when in undefined mode.
    introduces qxl_mode_to_string(), and uses it in other places too.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl.c b/hw/qxl.c
index e95d6f7..3722f55 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -336,6 +336,21 @@ static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info)
     info->n_surfaces = NUM_SURFACES;
 }
 
+static const char *qxl_mode_to_string(int mode)
+{
+    switch (mode) {
+    case QXL_MODE_COMPAT:
+        return "compat";
+    case QXL_MODE_NATIVE:
+        return "native";
+    case QXL_MODE_UNDEFINED:
+        return "undefined";
+    case QXL_MODE_VGA:
+        return "vga";
+    }
+    return "INVALID";
+}
+
 /* called from spice server thread context only */
 static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
 {
@@ -358,18 +373,19 @@ static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
         }
         qemu_mutex_unlock(&qxl->ssd.lock);
         if (ret) {
+            dprint(qxl, 2, "%s %s\n", __FUNCTION__, qxl_mode_to_string(qxl->mode));
             qxl_log_command(qxl, "vga", ext);
         }
         return ret;
     case QXL_MODE_COMPAT:
     case QXL_MODE_NATIVE:
     case QXL_MODE_UNDEFINED:
-        dprint(qxl, 2, "%s: %s\n", __FUNCTION__,
-               qxl->cmdflags ? "compat" : "native");
+        dprint(qxl, 4, "%s: %s\n", __FUNCTION__, qxl_mode_to_string(qxl->mode));
         ring = &qxl->ram->cmd_ring;
         if (SPICE_RING_IS_EMPTY(ring)) {
             return false;
         }
+        dprint(qxl, 2, "%s: %s\n", __FUNCTION__, qxl_mode_to_string(qxl->mode));
         SPICE_RING_CONS_ITEM(ring, cmd);
         ext->cmd      = *cmd;
         ext->group_id = MEMSLOT_GROUP_GUEST;
@@ -993,7 +1009,7 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
         break;
     case QXL_IO_DESTROY_PRIMARY:
         PANIC_ON(val != 0);
-        dprint(d, 1, "QXL_IO_DESTROY_PRIMARY\n");
+        dprint(d, 1, "QXL_IO_DESTROY_PRIMARY (%s)\n", qxl_mode_to_string(d->mode));
         qxl_destroy_primary(d);
         break;
     case QXL_IO_DESTROY_SURFACE_WAIT:
@@ -1368,7 +1384,8 @@ static int qxl_post_load(void *opaque, int version)
 
     d->modes = (QXLModes*)((uint8_t*)d->rom + d->rom->modes_offset);
 
-    dprint(d, 1, "%s: restore mode\n", __FUNCTION__);
+    dprint(d, 1, "%s: restore mode (%s)\n", __FUNCTION__,
+        qxl_mode_to_string(d->mode));
     newmode = d->mode;
     d->mode = QXL_MODE_UNDEFINED;
     switch (newmode) {
commit 22795174a37e02200944c0d093d518e832650686
Author: Alon Levy <alevy at redhat.com>
Date:   Wed Jun 15 20:44:38 2011 +0200

    qxl: set mm_time in vga update
    
    This fixes a problem where on windows 7 startup phase, before the qxl driver
    is loaded, the drawables are sufficiently large and video like to trigger a
    stream, but the lack of a filled mm time field triggers a warning in spice-gtk.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/ui/spice-display.c b/ui/spice-display.c
index 15f0704..feeee73 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -70,6 +70,7 @@ static SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
     QXLCommand *cmd;
     uint8_t *src, *dst;
     int by, bw, bh;
+    struct timespec time_space;
 
     if (qemu_spice_rect_is_empty(&ssd->dirty)) {
         return NULL;
@@ -96,6 +97,10 @@ static SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
     drawable->surfaces_dest[0] = -1;
     drawable->surfaces_dest[1] = -1;
     drawable->surfaces_dest[2] = -1;
+    clock_gettime(CLOCK_MONOTONIC, &time_space);
+    /* time in milliseconds from epoch. */
+    drawable->mm_time = time_space.tv_sec * 1000
+                      + time_space.tv_nsec / 1000 / 1000;
 
     drawable->u.copy.rop_descriptor  = SPICE_ROPD_OP_PUT;
     drawable->u.copy.src_bitmap      = (intptr_t)image;
commit fba810f1f67b411c209aa0e3d90724127cbd9c0f
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Jun 15 13:11:33 2011 +0200

    spice: catch spice server initialization failures.
    
    When the spice server initialization fails report this and exit instead
    of ignoring the error.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/ui/spice-core.c b/ui/spice-core.c
index dd9905b..e142452 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -602,7 +602,10 @@ void qemu_spice_init(void)
 
     qemu_opt_foreach(opts, add_channel, NULL, 0);
 
-    spice_server_init(spice_server, &core_interface);
+    if (0 != spice_server_init(spice_server, &core_interface)) {
+        fprintf(stderr, "failed to initialize spice server");
+        exit(1);
+    };
     using_spice = 1;
 
     migration_state.notify = migration_state_notifier;
commit 638f4e47798725cef2a5ae5bf83d508fbde36605
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Jun 29 15:45:16 2011 +0200

    qxl: device id fixup
    
    Move device ID to PCIDeviceInfo.
    Remove support for the unused unstable device ID.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl.c b/hw/qxl.c
index 16316f2..e95d6f7 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1207,7 +1207,6 @@ static DisplayChangeListener display_listener = {
 static int qxl_init_common(PCIQXLDevice *qxl)
 {
     uint8_t* config = qxl->pci.config;
-    uint32_t pci_device_id;
     uint32_t pci_device_rev;
     uint32_t io_size;
 
@@ -1218,20 +1217,14 @@ static int qxl_init_common(PCIQXLDevice *qxl)
 
     switch (qxl->revision) {
     case 1: /* spice 0.4 -- qxl-1 */
-        pci_device_id  = QXL_DEVICE_ID_STABLE;
         pci_device_rev = QXL_REVISION_STABLE_V04;
         break;
     case 2: /* spice 0.6 -- qxl-2 */
-        pci_device_id  = QXL_DEVICE_ID_STABLE;
+    default:
         pci_device_rev = QXL_REVISION_STABLE_V06;
         break;
-    default: /* experimental */
-        pci_device_id  = QXL_DEVICE_ID_DEVEL;
-        pci_device_rev = 1;
-        break;
     }
 
-    pci_config_set_device_id(config, pci_device_id);
     pci_set_byte(&config[PCI_REVISION_ID], pci_device_rev);
     pci_set_byte(&config[PCI_INTERRUPT_PIN], 1);
 
@@ -1492,6 +1485,7 @@ static PCIDeviceInfo qxl_info_primary = {
     .config_write = qxl_write_config,
     .romfile      = "vgabios-qxl.bin",
     .vendor_id    = REDHAT_PCI_VENDOR_ID,
+    .device_id    = QXL_DEVICE_ID_STABLE,
     .class_id     = PCI_CLASS_DISPLAY_VGA,
     .qdev.props = (Property[]) {
         DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size, 64 * 1024 * 1024),
@@ -1512,6 +1506,7 @@ static PCIDeviceInfo qxl_info_secondary = {
     .qdev.vmsd    = &qxl_vmstate,
     .init         = qxl_init_secondary,
     .vendor_id    = REDHAT_PCI_VENDOR_ID,
+    .device_id    = QXL_DEVICE_ID_STABLE,
     .class_id     = PCI_CLASS_DISPLAY_OTHER,
     .qdev.props = (Property[]) {
         DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size, 64 * 1024 * 1024),


More information about the Spice-commits mailing list