All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13
@ 2017-12-06 19:15 Michael Roth
  2017-12-06 19:15 ` [Qemu-devel] [PATCH 01/55] hw/ppc: CAS reset on early device hotplug Michael Roth
                   ` (54 more replies)
  0 siblings, 55 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable

Hi everyone,                                                                                              

The following new patches are queued for QEMU stable v2.10.2:

  https://github.com/mdroth/qemu/commits/stable-2.10-staging

The release is planned for 2017-12-18:

  https://wiki.qemu.org/Planning/2.10

Please respond here or CC qemu-stable@nongnu.org on any patches you
think should be included in the release.

Testing/feedback is greatly appreciated.

Thanks!

----------------------------------------------------------------

The following changes since commit 7851197b812b383ae1208c5d86391c5179c8209d:

  Update version for 2.10.1 release (2017-10-02 12:42:58 -0500)

are available in the git repository at:

  git://github.com/mdroth/qemu.git stable-2.10-staging

for you to fetch changes up to 9c7714afd7b574245c86c6bad40ecbcc2992aeec:

  vga: handle cirrus vbe mode wraparounds. (2017-12-06 13:01:53 -0600)

----------------------------------------------------------------
Alexey Kardashevskiy (16):
      exec: Explicitly export target AS from address_space_translate_internal
      memory: Open code FlatView rendering
      memory: Move FlatView allocation to a helper
      memory: Move AddressSpaceDispatch from AddressSpace to FlatView
      memory: Remove AddressSpace pointer from AddressSpaceDispatch
      memory: Switch memory from using AddressSpace to FlatView
      memory: Cleanup after switching to FlatView
      memory: Rename mem_begin/mem_commit/mem_add helpers
      memory: Store physical root MR in FlatView
      memory: Alloc dispatch tree where topology is generared
      memory: Move address_space_update_ioeventfds
      memory: Share FlatView's and dispatch trees between address spaces
      memory: Do not allocate FlatView in address_space_init
      memory: Get rid of address_space_init_shareable
      memory: Create FlatView directly
      memory: Share special empty FlatView

Daniel Henrique Barboza (2):
      hw/ppc: CAS reset on early device hotplug
      hw/ppc: clear pending_events on machine reset

Daniel P. Berrange (1):
      io: monitor encoutput buffer size from websocket GSource

Eric Auger (1):
      hw/intc/arm_gicv3_its: Don't abort on table save failure

Eric Blake (6):
      block: Perform copy-on-read in loop
      nbd/client: Use error_prepend() correctly
      nbd/server: CVE-2017-15119 Reject options larger than 32M
      nbd/server: CVE-2017-15118 Stack smash on large export name
      nbd-client: Refuse read-only client with BDRV_O_RDWR
      nbd/client: Don't hard-disconnect on ESHUTDOWN from server

Gerd Hoffmann (2):
      vga: drop line_offset variable
      vga: handle cirrus vbe mode wraparounds.

Greg Kurz (3):
      ppc: fix setting of compat mode
      spapr: reset DRCs after devices
      vhost: fix error check in vhost_verify_ring_mappings()

Jason Wang (1):
      virtio-net: don't touch virtqueue if vm is stopped

Jens Freimann (2):
      net/socket: fix coverity issue
      net: fix check for number of parameters to -netdev socket

Jim Somerville (1):
      kvmclock: use the updated system_timer_msr

Max Reitz (4):
      qcow2: Fix unaligned preallocated truncation
      qcow2: Always execute preallocate() in a coroutine
      iotests: Add cluster_size=64k to 125
      util/stats64: Fix min/max comparisons

Maxime Coquelin (3):
      memory: fix off-by-one error in memory_region_notify_one()
      virtio: Add queue interface to restore avail index from vring used index
      vhost: restore avail index from vring used index on disconnection

Michael Olbrich (1):
      hw/sd: fix out-of-bounds check for multi block reads

Michael Roth (1):
      scripts/make-release: ship u-boot source as a tarball

Paolo Bonzini (4):
      memory: avoid "resurrection" of dead FlatViews
      memory: trace FlatView creation and destruction
      memory: seek FlatView sharing candidates among children subregions
      nios2: define tcg_env

Peter Lieven (1):
      block/nfs: fix nfs_client_open for filesize greater than 1TB

Peter Maydell (1):
      translate.c: Fix usermode big-endian AArch32 LDREXD and STREXD

Peter Xu (2):
      exec: add page_mask for flatview_do_translate
      exec: simplify address_space_get_iotlb_entry

Thomas Huth (1):
      hw/usb/bus: Remove bad object_unparent() from usb_try_create_simple()

Vladimir Sementsov-Ogievskiy (2):
      block/mirror: check backing in bdrv_mirror_top_flush
      nbd/server: fix nbd_negotiate_handle_info

 block/io.c                     | 118 ++++++----
 block/mirror.c                 |   4 +
 block/nbd-client.c             |   9 +
 block/nfs.c                    |   7 +-
 block/qcow2.c                  |  42 +++-
 cpus.c                         |   5 +-
 docs/devel/atomics.txt         |   1 +
 exec.c                         | 316 ++++++++++++++-------------
 hw/arm/armv7m.c                |   9 +-
 hw/display/vga.c               |  33 ++-
 hw/i386/kvm/clock.c            |   3 +-
 hw/intc/arm_gicv3_its_kvm.c    |   8 +-
 hw/intc/openpic_kvm.c          |   2 +-
 hw/net/virtio-net.c            |   3 +-
 hw/ppc/spapr.c                 |  48 ++++-
 hw/ppc/spapr_drc.c             |   9 +-
 hw/ppc/spapr_events.c          |  11 +
 hw/sd/sd.c                     |  12 +-
 hw/usb/bus.c                   |   4 +-
 hw/virtio/vhost.c              |  10 +-
 hw/virtio/virtio.c             |  10 +
 include/exec/memory-internal.h |  12 +-
 include/exec/memory.h          |  72 +++----
 include/hw/arm/armv7m.h        |   2 +-
 include/hw/ppc/spapr.h         |   1 +
 include/hw/ppc/spapr_drc.h     |   1 +
 include/hw/virtio/virtio.h     |   1 +
 include/qemu/atomic.h          |   8 +
 include/qemu/typedefs.h        |   1 +
 io/channel-websock.c           |   8 +-
 memory.c                       | 271 +++++++++++++++++------
 nbd/client.c                   |  56 +++--
 nbd/server.c                   |  13 +-
 net/socket.c                   |   6 +-
 scripts/make-release           |   4 +
 target/arm/cpu.c               |  15 +-
 target/arm/translate.c         |  39 +++-
 target/i386/cpu.c              |   5 +-
 target/nios2/translate.c       |   1 +
 target/ppc/compat.c            |   2 +-
 tests/qemu-iotests/058         |   8 +-
 tests/qemu-iotests/125         |   7 +-
 tests/qemu-iotests/125.out     | 480 ++++++++++++++++++++++++++++++++++++-----
 tests/qemu-iotests/140         |   4 +-
 tests/qemu-iotests/147         |   1 +
 trace-events                   |   3 +
 util/stats64.c                 |   4 +-
 47 files changed, 1220 insertions(+), 469 deletions(-)

^ permalink raw reply	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 01/55] hw/ppc: CAS reset on early device hotplug
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
@ 2017-12-06 19:15 ` Michael Roth
  2017-12-06 19:15 ` [Qemu-devel] [PATCH 02/55] hw/usb/bus: Remove bad object_unparent() from usb_try_create_simple() Michael Roth
                   ` (53 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Daniel Henrique Barboza, David Gibson

From: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com>

This patch is a follow up on the discussions made in patch
"hw/ppc: disable hotplug before CAS is completed" that can be
found at [1].

At this moment, we do not support CPU/memory hotplug in early
boot stages, before CAS. When a hotplug occurs, the event is logged
in an internal RTAS event log queue and an IRQ pulse is fired. In
regular conditions, the guest handles the interrupt by executing
check_exception, fetching the generated hotplug event and enabling
the device for use.

In early boot, this IRQ isn't caught (SLOF does not handle hotplug
events), leaving the event in the rtas event log queue. If the guest
executes check_exception due to another hotplug event, the re-assertion
of the IRQ ends up de-queuing the first hotplug event as well. In short,
a device hotplugged before CAS is considered coldplugged by SLOF.
This leads to device misbehavior and, in some cases, guest kernel
Ooops when trying to unplug the device.

A proper fix would be to turn every device hotplugged before CAS
as a colplugged device. This is not trivial to do with the current
code base though - the FDT is written in the guest memory at
ppc_spapr_reset and can't be retrieved without adding extra state
(fdt_size for example) that will need to managed and migrated. Adding
the hotplugged DT in the middle of CAS negotiation via the updated DT
tree works with CPU devs, but panics the guest kernel at boot. Additional
analysis would be necessary for LMBs and PCI devices. There are
questions to be made in QEMU/SLOF/kernel level about how we can make
this change in a sustainable way.

With Linux guests, a fix would be the kernel executing check_exception
at boot time, de-queueing the events that happened in early boot and
processing them. However, even if/when the newer kernels start
fetching these events at boot time, we need to take care of older
kernels that won't be doing that.

This patch works around the situation by issuing a CAS reset if a hotplugged
device is detected during CAS:

- the DRC conditions that warrant a CAS reset is the same as those that
triggers a DRC migration - the DRC must have a device attached and
the DRC state is not equal to its ready_state. With that in mind, this
patch makes use of 'spapr_drc_needed' to determine if a CAS reset
is needed.

- In the middle of CAS negotiations, the function
'spapr_hotplugged_dev_before_cas' goes through all the DRCs to see
if there are any DRC that requires a reset, using spapr_drc_needed. If
that happens, returns '1' in 'spapr_h_cas_compose_response' which will set
spapr->cas_reboot to true, causing the machine to reboot.

No changes are made for coldplug devices.

[1] http://lists.nongnu.org/archive/html/qemu-devel/2017-08/msg02855.html

Signed-off-by: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
(cherry picked from commit 10f12e6450407b18b4d5a6b50d3852dcfd7fff75)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 hw/ppc/spapr.c             | 26 +++++++++++++++++++++++++-
 hw/ppc/spapr_drc.c         |  2 +-
 include/hw/ppc/spapr_drc.h |  1 +
 3 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index cec441cbf4..cc3901a790 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -790,6 +790,26 @@ out:
     return ret;
 }
 
+static bool spapr_hotplugged_dev_before_cas(void)
+{
+    Object *drc_container, *obj;
+    ObjectProperty *prop;
+    ObjectPropertyIterator iter;
+
+    drc_container = container_get(object_get_root(), "/dr-connector");
+    object_property_iter_init(&iter, drc_container);
+    while ((prop = object_property_iter_next(&iter))) {
+        if (!strstart(prop->type, "link<", NULL)) {
+            continue;
+        }
+        obj = object_property_get_link(drc_container, prop->name, NULL);
+        if (spapr_drc_needed(obj)) {
+            return true;
+        }
+    }
+    return false;
+}
+
 int spapr_h_cas_compose_response(sPAPRMachineState *spapr,
                                  target_ulong addr, target_ulong size,
                                  sPAPROptionVector *ov5_updates)
@@ -797,9 +817,13 @@ int spapr_h_cas_compose_response(sPAPRMachineState *spapr,
     void *fdt, *fdt_skel;
     sPAPRDeviceTreeUpdateHeader hdr = { .version_id = 1 };
 
+    if (spapr_hotplugged_dev_before_cas()) {
+        return 1;
+    }
+
     size -= sizeof(hdr);
 
-    /* Create sceleton */
+    /* Create skeleton */
     fdt_skel = g_malloc0(size);
     _FDT((fdt_create(fdt_skel, size)));
     _FDT((fdt_begin_node(fdt_skel, "")));
diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c
index 605697d8bd..50df361187 100644
--- a/hw/ppc/spapr_drc.c
+++ b/hw/ppc/spapr_drc.c
@@ -460,7 +460,7 @@ static void drc_reset(void *opaque)
     spapr_drc_reset(SPAPR_DR_CONNECTOR(opaque));
 }
 
-static bool spapr_drc_needed(void *opaque)
+bool spapr_drc_needed(void *opaque)
 {
     sPAPRDRConnector *drc = (sPAPRDRConnector *)opaque;
     sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
diff --git a/include/hw/ppc/spapr_drc.h b/include/hw/ppc/spapr_drc.h
index a7958d0a8d..f8d9f5b231 100644
--- a/include/hw/ppc/spapr_drc.h
+++ b/include/hw/ppc/spapr_drc.h
@@ -257,6 +257,7 @@ int spapr_drc_populate_dt(void *fdt, int fdt_offset, Object *owner,
 void spapr_drc_attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt,
                       int fdt_start_offset, Error **errp);
 void spapr_drc_detach(sPAPRDRConnector *drc);
+bool spapr_drc_needed(void *opaque);
 
 static inline bool spapr_drc_unplug_requested(sPAPRDRConnector *drc)
 {
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 02/55] hw/usb/bus: Remove bad object_unparent() from usb_try_create_simple()
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
  2017-12-06 19:15 ` [Qemu-devel] [PATCH 01/55] hw/ppc: CAS reset on early device hotplug Michael Roth
@ 2017-12-06 19:15 ` Michael Roth
  2017-12-06 19:15 ` [Qemu-devel] [PATCH 03/55] block/mirror: check backing in bdrv_mirror_top_flush Michael Roth
                   ` (52 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Thomas Huth, Gerd Hoffmann

From: Thomas Huth <thuth@redhat.com>

Valgrind detects an invalid read operation when hot-plugging of an
USB device fails:

$ valgrind x86_64-softmmu/qemu-system-x86_64 -device usb-ehci -nographic -S
==30598== Memcheck, a memory error detector
==30598== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==30598== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==30598== Command: x86_64-softmmu/qemu-system-x86_64 -device usb-ehci -nographic -S
==30598==
QEMU 2.10.50 monitor - type 'help' for more information
(qemu) device_add usb-tablet
(qemu) device_add usb-tablet
(qemu) device_add usb-tablet
(qemu) device_add usb-tablet
(qemu) device_add usb-tablet
(qemu) device_add usb-tablet
==30598== Invalid read of size 8
==30598==    at 0x60EF50: object_unparent (object.c:445)
==30598==    by 0x580F0D: usb_try_create_simple (bus.c:346)
==30598==    by 0x581BEB: usb_claim_port (bus.c:451)
==30598==    by 0x582310: usb_qdev_realize (bus.c:257)
==30598==    by 0x4CB399: device_set_realized (qdev.c:914)
==30598==    by 0x60E26D: property_set_bool (object.c:1886)
==30598==    by 0x61235E: object_property_set_qobject (qom-qobject.c:27)
==30598==    by 0x61000F: object_property_set_bool (object.c:1162)
==30598==    by 0x4567C3: qdev_device_add (qdev-monitor.c:630)
==30598==    by 0x456D52: qmp_device_add (qdev-monitor.c:807)
==30598==    by 0x470A99: hmp_device_add (hmp.c:1933)
==30598==    by 0x3679C3: handle_hmp_command (monitor.c:3123)

The object_unparent() here is not necessary anymore since commit
69382d8b3e8600b3 ("qdev: Fix object reference leak in case device.realize()
fails"), so let's remove it now.

Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Message-id: 1506526106-30971-1-git-send-email-thuth@redhat.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit f3b2bea3c76ba9283b957f1373e7cebdbf863059)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 hw/usb/bus.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/hw/usb/bus.c b/hw/usb/bus.c
index d910f849e7..e56dc3348a 100644
--- a/hw/usb/bus.c
+++ b/hw/usb/bus.c
@@ -341,9 +341,7 @@ static USBDevice *usb_try_create_simple(USBBus *bus, const char *name,
     object_property_set_bool(OBJECT(dev), true, "realized", &err);
     if (err) {
         error_propagate(errp, err);
-        error_prepend(errp, "Failed to initialize USB device '%s': ",
-                      name);
-        object_unparent(OBJECT(dev));
+        error_prepend(errp, "Failed to initialize USB device '%s': ", name);
         return NULL;
     }
     return dev;
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 03/55] block/mirror: check backing in bdrv_mirror_top_flush
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
  2017-12-06 19:15 ` [Qemu-devel] [PATCH 01/55] hw/ppc: CAS reset on early device hotplug Michael Roth
  2017-12-06 19:15 ` [Qemu-devel] [PATCH 02/55] hw/usb/bus: Remove bad object_unparent() from usb_try_create_simple() Michael Roth
@ 2017-12-06 19:15 ` Michael Roth
  2017-12-06 19:15 ` [Qemu-devel] [PATCH 04/55] kvmclock: use the updated system_timer_msr Michael Roth
                   ` (51 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Vladimir Sementsov-Ogievskiy, Max Reitz

From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>

Backing may be zero after failed bdrv_append in mirror_start_job,
which leads to SIGSEGV.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-id: 20170929152255.5431-1-vsementsov@virtuozzo.com
Signed-off-by: Max Reitz <mreitz@redhat.com>
(cherry picked from commit ce960aa9062a407d0ca15aee3dcd3bd84a4e24f9)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 block/mirror.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/block/mirror.c b/block/mirror.c
index 429751b9fe..03fc6d63b7 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -1056,6 +1056,10 @@ static int coroutine_fn bdrv_mirror_top_pwritev(BlockDriverState *bs,
 
 static int coroutine_fn bdrv_mirror_top_flush(BlockDriverState *bs)
 {
+    if (bs->backing == NULL) {
+        /* we can be here after failed bdrv_append in mirror_start_job */
+        return 0;
+    }
     return bdrv_co_flush(bs->backing->bs);
 }
 
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 04/55] kvmclock: use the updated system_timer_msr
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (2 preceding siblings ...)
  2017-12-06 19:15 ` [Qemu-devel] [PATCH 03/55] block/mirror: check backing in bdrv_mirror_top_flush Michael Roth
@ 2017-12-06 19:15 ` Michael Roth
  2017-12-06 19:15 ` [Qemu-devel] [PATCH 05/55] block: Perform copy-on-read in loop Michael Roth
                   ` (50 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Jim Somerville, Paolo Bonzini

From: Jim Somerville <Jim.Somerville@windriver.com>

Fixes e2b6c17 (kvmclock: update system_time_msr address forcibly)
which makes a call to get the latest value of the address
stored in system_timer_msr, but then uses the old address anyway.

Signed-off-by: Jim Somerville <Jim.Somerville@windriver.com>
Message-Id: <59b67db0bd15a46ab47c3aa657c81a4c11f168ea.1506702472.git.Jim.Somerville@windriver.com>
Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 346b1215b1e9f7cc6d8fe9fb6f3c2778b890afb6)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 hw/i386/kvm/clock.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/i386/kvm/clock.c b/hw/i386/kvm/clock.c
index 363d1b5743..a31d8ff240 100644
--- a/hw/i386/kvm/clock.c
+++ b/hw/i386/kvm/clock.c
@@ -62,7 +62,7 @@ static uint64_t kvmclock_current_nsec(KVMClockState *s)
 {
     CPUState *cpu = first_cpu;
     CPUX86State *env = cpu->env_ptr;
-    hwaddr kvmclock_struct_pa = env->system_time_msr & ~1ULL;
+    hwaddr kvmclock_struct_pa;
     uint64_t migration_tsc = env->tsc;
     struct pvclock_vcpu_time_info time;
     uint64_t delta;
@@ -77,6 +77,7 @@ static uint64_t kvmclock_current_nsec(KVMClockState *s)
         return 0;
     }
 
+    kvmclock_struct_pa = env->system_time_msr & ~1ULL;
     cpu_physical_memory_read(kvmclock_struct_pa, &time, sizeof(time));
 
     assert(time.tsc_timestamp <= migration_tsc);
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 05/55] block: Perform copy-on-read in loop
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (3 preceding siblings ...)
  2017-12-06 19:15 ` [Qemu-devel] [PATCH 04/55] kvmclock: use the updated system_timer_msr Michael Roth
@ 2017-12-06 19:15 ` Michael Roth
  2017-12-06 19:15 ` [Qemu-devel] [PATCH 06/55] exec: Explicitly export target AS from address_space_translate_internal Michael Roth
                   ` (49 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Eric Blake, Kevin Wolf

From: Eric Blake <eblake@redhat.com>

Improve our braindead copy-on-read implementation.  Pre-patch,
we have multiple issues:
- we create a bounce buffer and perform a write for the entire
request, even if the active image already has 99% of the
clusters occupied, and really only needs to copy-on-read the
remaining 1% of the clusters
- our bounce buffer was as large as the read request, and can
needlessly exhaust our memory by using double the memory of
the request size (the original request plus our bounce buffer),
rather than a capped maximum overhead beyond the original
- if a driver has a max_transfer limit, we are bypassing the
normal code in bdrv_aligned_preadv() that fragments to that
limit, and instead attempt to read the entire buffer from the
driver in one go, which some drivers may assert on
- a client can request a large request of nearly 2G such that
rounding the request out to cluster boundaries results in a
byte count larger than 2G.  While this cannot exceed 32 bits,
it DOES have some follow-on problems:
-- the call to bdrv_driver_pread() can assert for exceeding
BDRV_REQUEST_MAX_BYTES, if the driver is old and lacks
.bdrv_co_preadv
-- if the buffer is all zeroes, the subsequent call to
bdrv_co_do_pwrite_zeroes is a no-op due to a negative size,
which means we did not actually copy on read

Fix all of these issues by breaking up the action into a loop,
where each iteration is capped to sane limits.  Also, querying
the allocation status allows us to optimize: when data is
already present in the active layer, we don't need to bounce.

Note that the code has a telling comment that copy-on-read
should probably be a filter driver rather than a bolt-on hack
in io.c; but that remains a task for another day.

CC: qemu-stable@nongnu.org
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit cb2e28780c7080af489e72227683fe374f05022d)
 Conflicts:
	block/io.c
* remove context dep on d855ebcd3
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 block/io.c | 118 ++++++++++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 81 insertions(+), 37 deletions(-)

diff --git a/block/io.c b/block/io.c
index 26003814eb..fce856ea8a 100644
--- a/block/io.c
+++ b/block/io.c
@@ -34,6 +34,9 @@
 
 #define NOT_DONE 0x7fffffff /* used while emulated sync operation in progress */
 
+/* Maximum bounce buffer for copy-on-read and write zeroes, in bytes */
+#define MAX_BOUNCE_BUFFER (32768 << BDRV_SECTOR_BITS)
+
 static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
     int64_t offset, int bytes, BdrvRequestFlags flags);
 
@@ -945,11 +948,14 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
 
     BlockDriver *drv = bs->drv;
     struct iovec iov;
-    QEMUIOVector bounce_qiov;
+    QEMUIOVector local_qiov;
     int64_t cluster_offset;
     unsigned int cluster_bytes;
     size_t skip_bytes;
     int ret;
+    int max_transfer = MIN_NON_ZERO(bs->bl.max_transfer,
+                                    BDRV_REQUEST_MAX_BYTES);
+    unsigned int progress = 0;
 
     /* FIXME We cannot require callers to have write permissions when all they
      * are doing is a read request. If we did things right, write permissions
@@ -961,52 +967,94 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
     // assert(child->perm & (BLK_PERM_WRITE_UNCHANGED | BLK_PERM_WRITE));
 
     /* Cover entire cluster so no additional backing file I/O is required when
-     * allocating cluster in the image file.
+     * allocating cluster in the image file.  Note that this value may exceed
+     * BDRV_REQUEST_MAX_BYTES (even when the original read did not), which
+     * is one reason we loop rather than doing it all at once.
      */
     bdrv_round_to_clusters(bs, offset, bytes, &cluster_offset, &cluster_bytes);
+    skip_bytes = offset - cluster_offset;
 
     trace_bdrv_co_do_copy_on_readv(bs, offset, bytes,
                                    cluster_offset, cluster_bytes);
 
-    iov.iov_len = cluster_bytes;
-    iov.iov_base = bounce_buffer = qemu_try_blockalign(bs, iov.iov_len);
+    bounce_buffer = qemu_try_blockalign(bs,
+                                        MIN(MIN(max_transfer, cluster_bytes),
+                                            MAX_BOUNCE_BUFFER));
     if (bounce_buffer == NULL) {
         ret = -ENOMEM;
         goto err;
     }
 
-    qemu_iovec_init_external(&bounce_qiov, &iov, 1);
+    while (cluster_bytes) {
+        int64_t pnum;
 
-    ret = bdrv_driver_preadv(bs, cluster_offset, cluster_bytes,
-                             &bounce_qiov, 0);
-    if (ret < 0) {
-        goto err;
-    }
+        ret = bdrv_is_allocated(bs, cluster_offset,
+                                MIN(cluster_bytes, max_transfer), &pnum);
+        if (ret < 0) {
+            /* Safe to treat errors in querying allocation as if
+             * unallocated; we'll probably fail again soon on the
+             * read, but at least that will set a decent errno.
+             */
+            pnum = MIN(cluster_bytes, max_transfer);
+        }
 
-    if (drv->bdrv_co_pwrite_zeroes &&
-        buffer_is_zero(bounce_buffer, iov.iov_len)) {
-        /* FIXME: Should we (perhaps conditionally) be setting
-         * BDRV_REQ_MAY_UNMAP, if it will allow for a sparser copy
-         * that still correctly reads as zero? */
-        ret = bdrv_co_do_pwrite_zeroes(bs, cluster_offset, cluster_bytes, 0);
-    } else {
-        /* This does not change the data on the disk, it is not necessary
-         * to flush even in cache=writethrough mode.
-         */
-        ret = bdrv_driver_pwritev(bs, cluster_offset, cluster_bytes,
-                                  &bounce_qiov, 0);
-    }
+        assert(skip_bytes < pnum);
 
-    if (ret < 0) {
-        /* It might be okay to ignore write errors for guest requests.  If this
-         * is a deliberate copy-on-read then we don't want to ignore the error.
-         * Simply report it in all cases.
-         */
-        goto err;
-    }
+        if (ret <= 0) {
+            /* Must copy-on-read; use the bounce buffer */
+            iov.iov_base = bounce_buffer;
+            iov.iov_len = pnum = MIN(pnum, MAX_BOUNCE_BUFFER);
+            qemu_iovec_init_external(&local_qiov, &iov, 1);
 
-    skip_bytes = offset - cluster_offset;
-    qemu_iovec_from_buf(qiov, 0, bounce_buffer + skip_bytes, bytes);
+            ret = bdrv_driver_preadv(bs, cluster_offset, pnum,
+                                     &local_qiov, 0);
+            if (ret < 0) {
+                goto err;
+            }
+
+            if (drv->bdrv_co_pwrite_zeroes &&
+                buffer_is_zero(bounce_buffer, pnum)) {
+                /* FIXME: Should we (perhaps conditionally) be setting
+                 * BDRV_REQ_MAY_UNMAP, if it will allow for a sparser copy
+                 * that still correctly reads as zero? */
+                ret = bdrv_co_do_pwrite_zeroes(bs, cluster_offset, pnum, 0);
+            } else {
+                /* This does not change the data on the disk, it is not
+                 * necessary to flush even in cache=writethrough mode.
+                 */
+                ret = bdrv_driver_pwritev(bs, cluster_offset, pnum,
+                                          &local_qiov, 0);
+            }
+
+            if (ret < 0) {
+                /* It might be okay to ignore write errors for guest
+                 * requests.  If this is a deliberate copy-on-read
+                 * then we don't want to ignore the error.  Simply
+                 * report it in all cases.
+                 */
+                goto err;
+            }
+
+            qemu_iovec_from_buf(qiov, progress, bounce_buffer + skip_bytes,
+                                pnum - skip_bytes);
+        } else {
+            /* Read directly into the destination */
+            qemu_iovec_init(&local_qiov, qiov->niov);
+            qemu_iovec_concat(&local_qiov, qiov, progress, pnum - skip_bytes);
+            ret = bdrv_driver_preadv(bs, offset + progress, local_qiov.size,
+                                     &local_qiov, 0);
+            qemu_iovec_destroy(&local_qiov);
+            if (ret < 0) {
+                goto err;
+            }
+        }
+
+        cluster_offset += pnum;
+        cluster_bytes -= pnum;
+        progress += pnum - skip_bytes;
+        skip_bytes = 0;
+    }
+    ret = 0;
 
 err:
     qemu_vfree(bounce_buffer);
@@ -1212,9 +1260,6 @@ int coroutine_fn bdrv_co_readv(BdrvChild *child, int64_t sector_num,
     return bdrv_co_do_readv(child, sector_num, nb_sectors, qiov, 0);
 }
 
-/* Maximum buffer for write zeroes fallback, in bytes */
-#define MAX_WRITE_ZEROES_BOUNCE_BUFFER (32768 << BDRV_SECTOR_BITS)
-
 static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
     int64_t offset, int bytes, BdrvRequestFlags flags)
 {
@@ -1229,8 +1274,7 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
     int max_write_zeroes = MIN_NON_ZERO(bs->bl.max_pwrite_zeroes, INT_MAX);
     int alignment = MAX(bs->bl.pwrite_zeroes_alignment,
                         bs->bl.request_alignment);
-    int max_transfer = MIN_NON_ZERO(bs->bl.max_transfer,
-                                    MAX_WRITE_ZEROES_BOUNCE_BUFFER);
+    int max_transfer = MIN_NON_ZERO(bs->bl.max_transfer, MAX_BOUNCE_BUFFER);
 
     assert(alignment % bs->bl.request_alignment == 0);
     head = offset % alignment;
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 06/55] exec: Explicitly export target AS from address_space_translate_internal
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (4 preceding siblings ...)
  2017-12-06 19:15 ` [Qemu-devel] [PATCH 05/55] block: Perform copy-on-read in loop Michael Roth
@ 2017-12-06 19:15 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 07/55] memory: Open code FlatView rendering Michael Roth
                   ` (48 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Alexey Kardashevskiy, Paolo Bonzini

From: Alexey Kardashevskiy <aik@ozlabs.ru>

This adds an AS** parameter to address_space_do_translate()
to make it easier for the next patch to share FlatViews.

This should cause no behavioural change.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Message-Id: <20170921085110.25598-2-aik@ozlabs.ru>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit e76bb18f7e430e0c50fb38d051feacf268bd78f4)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 exec.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/exec.c b/exec.c
index d20c34ca83..bd94248390 100644
--- a/exec.c
+++ b/exec.c
@@ -477,7 +477,8 @@ static MemoryRegionSection address_space_do_translate(AddressSpace *as,
                                                       hwaddr *xlat,
                                                       hwaddr *plen,
                                                       bool is_write,
-                                                      bool is_mmio)
+                                                      bool is_mmio,
+                                                      AddressSpace **target_as)
 {
     IOMMUTLBEntry iotlb;
     MemoryRegionSection *section;
@@ -504,6 +505,7 @@ static MemoryRegionSection address_space_do_translate(AddressSpace *as,
         }
 
         as = iotlb.target_as;
+        *target_as = iotlb.target_as;
     }
 
     *xlat = addr;
@@ -526,7 +528,7 @@ IOMMUTLBEntry address_space_get_iotlb_entry(AddressSpace *as, hwaddr addr,
 
     /* This can never be MMIO. */
     section = address_space_do_translate(as, addr, &xlat, &plen,
-                                         is_write, false);
+                                         is_write, false, &as);
 
     /* Illegal translation */
     if (section.mr == &io_mem_unassigned) {
@@ -549,7 +551,7 @@ IOMMUTLBEntry address_space_get_iotlb_entry(AddressSpace *as, hwaddr addr,
     plen -= 1;
 
     return (IOMMUTLBEntry) {
-        .target_as = section.address_space,
+        .target_as = as,
         .iova = addr & ~plen,
         .translated_addr = xlat & ~plen,
         .addr_mask = plen,
@@ -570,7 +572,8 @@ MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr,
     MemoryRegionSection section;
 
     /* This can be MMIO, so setup MMIO bit. */
-    section = address_space_do_translate(as, addr, xlat, plen, is_write, true);
+    section = address_space_do_translate(as, addr, xlat, plen, is_write, true,
+                                         &as);
     mr = section.mr;
 
     if (xen_enabled() && memory_access_is_direct(mr, is_write)) {
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 07/55] memory: Open code FlatView rendering
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (5 preceding siblings ...)
  2017-12-06 19:15 ` [Qemu-devel] [PATCH 06/55] exec: Explicitly export target AS from address_space_translate_internal Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 08/55] memory: Move FlatView allocation to a helper Michael Roth
                   ` (47 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Alexey Kardashevskiy, Paolo Bonzini

From: Alexey Kardashevskiy <aik@ozlabs.ru>

We are going to share FlatView's between AddressSpace's and per-AS
memory listeners won't suit the purpose anymore so open code
the dispatch tree rendering.

Since there is a good chance that dispatch_listener was the only
listener, this avoids address_space_update_topology_pass() if there is
no registered listeners; this should improve starting time.

This should cause no behavioural change.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Message-Id: <20170921085110.25598-3-aik@ozlabs.ru>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 9a62e24f45bc97f8eaf198caf58906b47c50a8d5)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 exec.c                         | 27 +++------------------------
 include/exec/memory-internal.h |  6 ++++--
 include/exec/memory.h          |  1 -
 memory.c                       | 19 ++++++++++++++-----
 4 files changed, 21 insertions(+), 32 deletions(-)

diff --git a/exec.c b/exec.c
index bd94248390..3ed3718dea 100644
--- a/exec.c
+++ b/exec.c
@@ -1348,9 +1348,8 @@ static void register_multipage(AddressSpaceDispatch *d,
     phys_page_set(d, start_addr >> TARGET_PAGE_BITS, num_pages, section_index);
 }
 
-static void mem_add(MemoryListener *listener, MemoryRegionSection *section)
+void mem_add(AddressSpace *as, MemoryRegionSection *section)
 {
-    AddressSpace *as = container_of(listener, AddressSpace, dispatch_listener);
     AddressSpaceDispatch *d = as->next_dispatch;
     MemoryRegionSection now = *section, remain = *section;
     Int128 page_size = int128_make64(TARGET_PAGE_SIZE);
@@ -2674,9 +2673,8 @@ static void io_mem_init(void)
                           NULL, UINT64_MAX);
 }
 
-static void mem_begin(MemoryListener *listener)
+void mem_begin(AddressSpace *as)
 {
-    AddressSpace *as = container_of(listener, AddressSpace, dispatch_listener);
     AddressSpaceDispatch *d = g_new0(AddressSpaceDispatch, 1);
     uint16_t n;
 
@@ -2700,9 +2698,8 @@ static void address_space_dispatch_free(AddressSpaceDispatch *d)
     g_free(d);
 }
 
-static void mem_commit(MemoryListener *listener)
+void mem_commit(AddressSpace *as)
 {
-    AddressSpace *as = container_of(listener, AddressSpace, dispatch_listener);
     AddressSpaceDispatch *cur = as->dispatch;
     AddressSpaceDispatch *next = as->next_dispatch;
 
@@ -2732,24 +2729,6 @@ static void tcg_commit(MemoryListener *listener)
     tlb_flush(cpuas->cpu);
 }
 
-void address_space_init_dispatch(AddressSpace *as)
-{
-    as->dispatch = NULL;
-    as->dispatch_listener = (MemoryListener) {
-        .begin = mem_begin,
-        .commit = mem_commit,
-        .region_add = mem_add,
-        .region_nop = mem_add,
-        .priority = 0,
-    };
-    memory_listener_register(&as->dispatch_listener, as);
-}
-
-void address_space_unregister(AddressSpace *as)
-{
-    memory_listener_unregister(&as->dispatch_listener);
-}
-
 void address_space_destroy_dispatch(AddressSpace *as)
 {
     AddressSpaceDispatch *d = as->dispatch;
diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h
index fb467acdba..9abde2f11c 100644
--- a/include/exec/memory-internal.h
+++ b/include/exec/memory-internal.h
@@ -22,8 +22,6 @@
 #ifndef CONFIG_USER_ONLY
 typedef struct AddressSpaceDispatch AddressSpaceDispatch;
 
-void address_space_init_dispatch(AddressSpace *as);
-void address_space_unregister(AddressSpace *as);
 void address_space_destroy_dispatch(AddressSpace *as);
 
 extern const MemoryRegionOps unassigned_mem_ops;
@@ -31,5 +29,9 @@ extern const MemoryRegionOps unassigned_mem_ops;
 bool memory_region_access_valid(MemoryRegion *mr, hwaddr addr,
                                 unsigned size, bool is_write);
 
+void mem_add(AddressSpace *as, MemoryRegionSection *section);
+void mem_begin(AddressSpace *as);
+void mem_commit(AddressSpace *as);
+
 #endif
 #endif
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 400dd4491b..9ee0f2e846 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -328,7 +328,6 @@ struct AddressSpace {
     struct MemoryRegionIoeventfd *ioeventfds;
     struct AddressSpaceDispatch *dispatch;
     struct AddressSpaceDispatch *next_dispatch;
-    MemoryListener dispatch_listener;
     QTAILQ_HEAD(memory_listeners_as, MemoryListener) listeners;
     QTAILQ_ENTRY(AddressSpace) address_spaces_link;
 };
diff --git a/memory.c b/memory.c
index c0adc35410..138e21d35d 100644
--- a/memory.c
+++ b/memory.c
@@ -879,14 +879,24 @@ static void address_space_update_topology_pass(AddressSpace *as,
     }
 }
 
-
 static void address_space_update_topology(AddressSpace *as)
 {
     FlatView *old_view = address_space_get_flatview(as);
     FlatView *new_view = generate_memory_topology(as->root);
+    int i;
 
-    address_space_update_topology_pass(as, old_view, new_view, false);
-    address_space_update_topology_pass(as, old_view, new_view, true);
+    mem_begin(as);
+    for (i = 0; i < new_view->nr; i++) {
+        MemoryRegionSection mrs =
+            section_from_flat_range(&new_view->ranges[i], as);
+        mem_add(as, &mrs);
+    }
+    mem_commit(as);
+
+    if (!QTAILQ_EMPTY(&as->listeners)) {
+        address_space_update_topology_pass(as, old_view, new_view, false);
+        address_space_update_topology_pass(as, old_view, new_view, true);
+    }
 
     /* Writes are protected by the BQL.  */
     atomic_rcu_set(&as->current_map, new_view);
@@ -2621,7 +2631,7 @@ void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name)
     QTAILQ_INIT(&as->listeners);
     QTAILQ_INSERT_TAIL(&address_spaces, as, address_spaces_link);
     as->name = g_strdup(name ? name : "anonymous");
-    address_space_init_dispatch(as);
+    as->dispatch = NULL;
     memory_region_update_pending |= root->enabled;
     memory_region_transaction_commit();
 }
@@ -2672,7 +2682,6 @@ void address_space_destroy(AddressSpace *as)
     as->root = NULL;
     memory_region_transaction_commit();
     QTAILQ_REMOVE(&address_spaces, as, address_spaces_link);
-    address_space_unregister(as);
 
     /* At this point, as->dispatch and as->current_map are dummy
      * entries that the guest should never use.  Wait for the old
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 08/55] memory: Move FlatView allocation to a helper
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (6 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 07/55] memory: Open code FlatView rendering Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 09/55] memory: Move AddressSpaceDispatch from AddressSpace to FlatView Michael Roth
                   ` (46 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Alexey Kardashevskiy, Paolo Bonzini

From: Alexey Kardashevskiy <aik@ozlabs.ru>

This moves a FlatView allocation and initialization to a helper.
While we are nere, replace g_new with g_new0 to not to bother if we add
new fields in the future.

This should cause no behavioural change.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Message-Id: <20170921085110.25598-4-aik@ozlabs.ru>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit cc94cd6d36602d976a5e7bc29134d1eaefb4102e)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 memory.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/memory.c b/memory.c
index 138e21d35d..c0aa296223 100644
--- a/memory.c
+++ b/memory.c
@@ -258,12 +258,14 @@ static bool flatrange_equal(FlatRange *a, FlatRange *b)
         && a->readonly == b->readonly;
 }
 
-static void flatview_init(FlatView *view)
+static FlatView *flatview_new(void)
 {
+    FlatView *view;
+
+    view = g_new0(FlatView, 1);
     view->ref = 1;
-    view->ranges = NULL;
-    view->nr = 0;
-    view->nr_allocated = 0;
+
+    return view;
 }
 
 /* Insert a range into a given position.  Caller is responsible for maintaining
@@ -706,8 +708,7 @@ static FlatView *generate_memory_topology(MemoryRegion *mr)
 {
     FlatView *view;
 
-    view = g_new(FlatView, 1);
-    flatview_init(view);
+    view = flatview_new();
 
     if (mr) {
         render_memory_region(view, mr, int128_zero(),
@@ -2624,8 +2625,7 @@ void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name)
     as->ref_count = 1;
     as->root = root;
     as->malloced = false;
-    as->current_map = g_new(FlatView, 1);
-    flatview_init(as->current_map);
+    as->current_map = flatview_new();
     as->ioeventfd_nb = 0;
     as->ioeventfds = NULL;
     QTAILQ_INIT(&as->listeners);
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 09/55] memory: Move AddressSpaceDispatch from AddressSpace to FlatView
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (7 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 08/55] memory: Move FlatView allocation to a helper Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 10/55] memory: Remove AddressSpace pointer from AddressSpaceDispatch Michael Roth
                   ` (45 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Alexey Kardashevskiy, Paolo Bonzini

From: Alexey Kardashevskiy <aik@ozlabs.ru>

As we are going to share FlatView's between AddressSpace's,
and AddressSpaceDispatch is a structure to perform quick lookup
in FlatView, this moves ASD to FlatView.

After previosly open coded ASD rendering, we can also remove
as->next_dispatch as the new FlatView pointer is stored
on a stack and set to an AS atomically.

flatview_destroy() is executed under RCU instead of
address_space_dispatch_free() now.

This makes mem_begin/mem_commit to work with ASD and mem_add with FV
as later on mem_add will be taking FV as an argument anyway.

This should cause no behavioural change.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Message-Id: <20170921085110.25598-5-aik@ozlabs.ru>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 66a6df1dc6d5b28cc3e65db0d71683fbdddc6b62)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 exec.c                         | 41 +++++++++++------------------------------
 include/exec/memory-internal.h | 12 +++++++-----
 include/exec/memory.h          |  2 --
 memory.c                       | 31 ++++++++++++++++++++++++-------
 4 files changed, 42 insertions(+), 44 deletions(-)

diff --git a/exec.c b/exec.c
index 3ed3718dea..6b0211bafc 100644
--- a/exec.c
+++ b/exec.c
@@ -188,8 +188,6 @@ typedef struct PhysPageMap {
 } PhysPageMap;
 
 struct AddressSpaceDispatch {
-    struct rcu_head rcu;
-
     MemoryRegionSection *mru_section;
     /* This is a multi-level map on the physical address space.
      * The bottom level has pointers to MemoryRegionSections.
@@ -486,7 +484,7 @@ static MemoryRegionSection address_space_do_translate(AddressSpace *as,
     IOMMUMemoryRegionClass *imrc;
 
     for (;;) {
-        AddressSpaceDispatch *d = atomic_rcu_read(&as->dispatch);
+        AddressSpaceDispatch *d = address_space_to_dispatch(as);
         section = address_space_translate_internal(d, addr, &addr, plen, is_mmio);
 
         iommu_mr = memory_region_get_iommu(section->mr);
@@ -1223,7 +1221,7 @@ hwaddr memory_region_section_get_iotlb(CPUState *cpu,
     } else {
         AddressSpaceDispatch *d;
 
-        d = atomic_rcu_read(&section->address_space->dispatch);
+        d = address_space_to_dispatch(section->address_space);
         iotlb = section - d->map.sections;
         iotlb += xlat;
     }
@@ -1348,9 +1346,9 @@ static void register_multipage(AddressSpaceDispatch *d,
     phys_page_set(d, start_addr >> TARGET_PAGE_BITS, num_pages, section_index);
 }
 
-void mem_add(AddressSpace *as, MemoryRegionSection *section)
+void mem_add(AddressSpace *as, FlatView *fv, MemoryRegionSection *section)
 {
-    AddressSpaceDispatch *d = as->next_dispatch;
+    AddressSpaceDispatch *d = flatview_to_dispatch(fv);
     MemoryRegionSection now = *section, remain = *section;
     Int128 page_size = int128_make64(TARGET_PAGE_SIZE);
 
@@ -2673,7 +2671,7 @@ static void io_mem_init(void)
                           NULL, UINT64_MAX);
 }
 
-void mem_begin(AddressSpace *as)
+AddressSpaceDispatch *mem_begin(AddressSpace *as)
 {
     AddressSpaceDispatch *d = g_new0(AddressSpaceDispatch, 1);
     uint16_t n;
@@ -2689,26 +2687,19 @@ void mem_begin(AddressSpace *as)
 
     d->phys_map  = (PhysPageEntry) { .ptr = PHYS_MAP_NODE_NIL, .skip = 1 };
     d->as = as;
-    as->next_dispatch = d;
+
+    return d;
 }
 
-static void address_space_dispatch_free(AddressSpaceDispatch *d)
+void address_space_dispatch_free(AddressSpaceDispatch *d)
 {
     phys_sections_free(&d->map);
     g_free(d);
 }
 
-void mem_commit(AddressSpace *as)
+void mem_commit(AddressSpaceDispatch *d)
 {
-    AddressSpaceDispatch *cur = as->dispatch;
-    AddressSpaceDispatch *next = as->next_dispatch;
-
-    phys_page_compact_all(next, next->map.nodes_nb);
-
-    atomic_rcu_set(&as->dispatch, next);
-    if (cur) {
-        call_rcu(cur, address_space_dispatch_free, rcu);
-    }
+    phys_page_compact_all(d, d->map.nodes_nb);
 }
 
 static void tcg_commit(MemoryListener *listener)
@@ -2724,21 +2715,11 @@ static void tcg_commit(MemoryListener *listener)
      * We reload the dispatch pointer now because cpu_reloading_memory_map()
      * may have split the RCU critical section.
      */
-    d = atomic_rcu_read(&cpuas->as->dispatch);
+    d = address_space_to_dispatch(cpuas->as);
     atomic_rcu_set(&cpuas->memory_dispatch, d);
     tlb_flush(cpuas->cpu);
 }
 
-void address_space_destroy_dispatch(AddressSpace *as)
-{
-    AddressSpaceDispatch *d = as->dispatch;
-
-    atomic_rcu_set(&as->dispatch, NULL);
-    if (d) {
-        call_rcu(d, address_space_dispatch_free, rcu);
-    }
-}
-
 static void memory_map_init(void)
 {
     system_memory = g_malloc(sizeof(*system_memory));
diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h
index 9abde2f11c..6e08eda256 100644
--- a/include/exec/memory-internal.h
+++ b/include/exec/memory-internal.h
@@ -22,16 +22,18 @@
 #ifndef CONFIG_USER_ONLY
 typedef struct AddressSpaceDispatch AddressSpaceDispatch;
 
-void address_space_destroy_dispatch(AddressSpace *as);
-
 extern const MemoryRegionOps unassigned_mem_ops;
 
 bool memory_region_access_valid(MemoryRegion *mr, hwaddr addr,
                                 unsigned size, bool is_write);
 
-void mem_add(AddressSpace *as, MemoryRegionSection *section);
-void mem_begin(AddressSpace *as);
-void mem_commit(AddressSpace *as);
+void mem_add(AddressSpace *as, FlatView *fv, MemoryRegionSection *section);
+AddressSpaceDispatch *mem_begin(AddressSpace *as);
+void mem_commit(AddressSpaceDispatch *d);
+
+AddressSpaceDispatch *address_space_to_dispatch(AddressSpace *as);
+AddressSpaceDispatch *flatview_to_dispatch(FlatView *fv);
+void address_space_dispatch_free(AddressSpaceDispatch *d);
 
 #endif
 #endif
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 9ee0f2e846..8f26d63417 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -326,8 +326,6 @@ struct AddressSpace {
 
     int ioeventfd_nb;
     struct MemoryRegionIoeventfd *ioeventfds;
-    struct AddressSpaceDispatch *dispatch;
-    struct AddressSpaceDispatch *next_dispatch;
     QTAILQ_HEAD(memory_listeners_as, MemoryListener) listeners;
     QTAILQ_ENTRY(AddressSpace) address_spaces_link;
 };
diff --git a/memory.c b/memory.c
index c0aa296223..de57a16ece 100644
--- a/memory.c
+++ b/memory.c
@@ -229,6 +229,7 @@ struct FlatView {
     FlatRange *ranges;
     unsigned nr;
     unsigned nr_allocated;
+    struct AddressSpaceDispatch *dispatch;
 };
 
 typedef struct AddressSpaceOps AddressSpaceOps;
@@ -289,6 +290,9 @@ static void flatview_destroy(FlatView *view)
 {
     int i;
 
+    if (view->dispatch) {
+        address_space_dispatch_free(view->dispatch);
+    }
     for (i = 0; i < view->nr; i++) {
         memory_region_unref(view->ranges[i].mr);
     }
@@ -304,10 +308,25 @@ static void flatview_ref(FlatView *view)
 static void flatview_unref(FlatView *view)
 {
     if (atomic_fetch_dec(&view->ref) == 1) {
-        flatview_destroy(view);
+        call_rcu(view, flatview_destroy, rcu);
     }
 }
 
+static FlatView *address_space_to_flatview(AddressSpace *as)
+{
+    return atomic_rcu_read(&as->current_map);
+}
+
+AddressSpaceDispatch *flatview_to_dispatch(FlatView *fv)
+{
+    return fv->dispatch;
+}
+
+AddressSpaceDispatch *address_space_to_dispatch(AddressSpace *as)
+{
+    return flatview_to_dispatch(address_space_to_flatview(as));
+}
+
 static bool can_merge(FlatRange *r1, FlatRange *r2)
 {
     return int128_eq(addrrange_end(r1->addr), r2->addr.start)
@@ -886,13 +905,13 @@ static void address_space_update_topology(AddressSpace *as)
     FlatView *new_view = generate_memory_topology(as->root);
     int i;
 
-    mem_begin(as);
+    new_view->dispatch = mem_begin(as);
     for (i = 0; i < new_view->nr; i++) {
         MemoryRegionSection mrs =
             section_from_flat_range(&new_view->ranges[i], as);
-        mem_add(as, &mrs);
+        mem_add(as, new_view, &mrs);
     }
-    mem_commit(as);
+    mem_commit(new_view->dispatch);
 
     if (!QTAILQ_EMPTY(&as->listeners)) {
         address_space_update_topology_pass(as, old_view, new_view, false);
@@ -901,7 +920,7 @@ static void address_space_update_topology(AddressSpace *as)
 
     /* Writes are protected by the BQL.  */
     atomic_rcu_set(&as->current_map, new_view);
-    call_rcu(old_view, flatview_unref, rcu);
+    flatview_unref(old_view);
 
     /* Note that all the old MemoryRegions are still alive up to this
      * point.  This relieves most MemoryListeners from the need to
@@ -2631,7 +2650,6 @@ void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name)
     QTAILQ_INIT(&as->listeners);
     QTAILQ_INSERT_TAIL(&address_spaces, as, address_spaces_link);
     as->name = g_strdup(name ? name : "anonymous");
-    as->dispatch = NULL;
     memory_region_update_pending |= root->enabled;
     memory_region_transaction_commit();
 }
@@ -2640,7 +2658,6 @@ static void do_address_space_destroy(AddressSpace *as)
 {
     bool do_free = as->malloced;
 
-    address_space_destroy_dispatch(as);
     assert(QTAILQ_EMPTY(&as->listeners));
 
     flatview_unref(as->current_map);
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 10/55] memory: Remove AddressSpace pointer from AddressSpaceDispatch
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (8 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 09/55] memory: Move AddressSpaceDispatch from AddressSpace to FlatView Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 11/55] memory: avoid "resurrection" of dead FlatViews Michael Roth
                   ` (44 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Alexey Kardashevskiy, Paolo Bonzini

From: Alexey Kardashevskiy <aik@ozlabs.ru>

AS in ASD is only used to pass AS from mem_begin() to register_subpage()
to store it in MemoryRegionSection, we can do this directly now.

This should cause no behavioural change.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Message-Id: <20170921085110.25598-6-aik@ozlabs.ru>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit c7752523787dc148f5ee976162e80ab594c386a1)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 exec.c | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/exec.c b/exec.c
index 6b0211bafc..3212c5e70d 100644
--- a/exec.c
+++ b/exec.c
@@ -194,7 +194,6 @@ struct AddressSpaceDispatch {
      */
     PhysPageEntry phys_map;
     PhysPageMap map;
-    AddressSpace *as;
 };
 
 #define SUBPAGE_IDX(addr) ((addr) & ~TARGET_PAGE_MASK)
@@ -1304,7 +1303,8 @@ static void phys_sections_free(PhysPageMap *map)
     g_free(map->nodes);
 }
 
-static void register_subpage(AddressSpaceDispatch *d, MemoryRegionSection *section)
+static void register_subpage(AddressSpace *as, AddressSpaceDispatch *d,
+                             MemoryRegionSection *section)
 {
     subpage_t *subpage;
     hwaddr base = section->offset_within_address_space
@@ -1319,8 +1319,8 @@ static void register_subpage(AddressSpaceDispatch *d, MemoryRegionSection *secti
     assert(existing->mr->subpage || existing->mr == &io_mem_unassigned);
 
     if (!(existing->mr->subpage)) {
-        subpage = subpage_init(d->as, base);
-        subsection.address_space = d->as;
+        subpage = subpage_init(as, base);
+        subsection.address_space = as;
         subsection.mr = &subpage->iomem;
         phys_page_set(d, base >> TARGET_PAGE_BITS, 1,
                       phys_section_add(&d->map, &subsection));
@@ -1357,7 +1357,7 @@ void mem_add(AddressSpace *as, FlatView *fv, MemoryRegionSection *section)
                        - now.offset_within_address_space;
 
         now.size = int128_min(int128_make64(left), now.size);
-        register_subpage(d, &now);
+        register_subpage(as, d, &now);
     } else {
         now.size = int128_zero();
     }
@@ -1367,10 +1367,10 @@ void mem_add(AddressSpace *as, FlatView *fv, MemoryRegionSection *section)
         remain.offset_within_region += int128_get64(now.size);
         now = remain;
         if (int128_lt(remain.size, page_size)) {
-            register_subpage(d, &now);
+            register_subpage(as, d, &now);
         } else if (remain.offset_within_address_space & ~TARGET_PAGE_MASK) {
             now.size = page_size;
-            register_subpage(d, &now);
+            register_subpage(as, d, &now);
         } else {
             now.size = int128_and(now.size, int128_neg(page_size));
             register_multipage(d, &now);
@@ -2686,7 +2686,6 @@ AddressSpaceDispatch *mem_begin(AddressSpace *as)
     assert(n == PHYS_SECTION_WATCH);
 
     d->phys_map  = (PhysPageEntry) { .ptr = PHYS_MAP_NODE_NIL, .skip = 1 };
-    d->as = as;
 
     return d;
 }
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 11/55] memory: avoid "resurrection" of dead FlatViews
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (9 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 10/55] memory: Remove AddressSpace pointer from AddressSpaceDispatch Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 12/55] memory: Switch memory from using AddressSpace to FlatView Michael Roth
                   ` (43 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Paolo Bonzini

From: Paolo Bonzini <pbonzini@redhat.com>

It's possible for address_space_get_flatview() as it currently stands
to cause a use-after-free for the returned FlatView, if the reference
count is incremented after the FlatView has been replaced by a writer:

   thread 1             thread 2             RCU thread
  -------------------------------------------------------------
   rcu_read_lock
   read as->current_map
                        set as->current_map
                        flatview_unref
                           '--> call_rcu
   flatview_ref
     [ref=1]
   rcu_read_unlock
                                             flatview_destroy
   <badness>

Since FlatViews are not updated very often, we can just detect the
situation using a new atomic op atomic_fetch_inc_nonzero, similar to
Linux's atomic_inc_not_zero, which performs the refcount increment only if
it hasn't already hit zero.  This is similar to Linux commit de09a9771a53
("CRED: Fix get_task_cred() and task_state() to not resurrect dead
credentials", 2010-07-29).

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 447b0d0b9ee8a0ac216c3186e0f3c427a1001f0c)
 Conflicts:
	docs/devel/atomics.txt
* drop documentation ref to atomic_fetch_xor
* prereq for 166206845f
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 docs/devel/atomics.txt |  1 +
 include/qemu/atomic.h  |  8 ++++++++
 memory.c               | 12 ++++++++----
 3 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/docs/devel/atomics.txt b/docs/devel/atomics.txt
index 3ef5d85b1b..3fbaf52140 100644
--- a/docs/devel/atomics.txt
+++ b/docs/devel/atomics.txt
@@ -63,6 +63,7 @@ operations:
     typeof(*ptr) atomic_fetch_sub(ptr, val)
     typeof(*ptr) atomic_fetch_and(ptr, val)
     typeof(*ptr) atomic_fetch_or(ptr, val)
+    typeof(*ptr) atomic_fetch_inc_nonzero(ptr)
     typeof(*ptr) atomic_xchg(ptr, val)
     typeof(*ptr) atomic_cmpxchg(ptr, old, new)
 
diff --git a/include/qemu/atomic.h b/include/qemu/atomic.h
index b6b62fb771..d73c9e14d7 100644
--- a/include/qemu/atomic.h
+++ b/include/qemu/atomic.h
@@ -442,4 +442,12 @@
 } while(0)
 #endif
 
+#define atomic_fetch_inc_nonzero(ptr) ({                                \
+    typeof_strip_qual(*ptr) _oldn = atomic_read(ptr);                   \
+    while (_oldn && atomic_cmpxchg(ptr, _oldn, _oldn + 1) != _oldn) {   \
+        _oldn = atomic_read(ptr);                                       \
+    }                                                                   \
+    _oldn;                                                              \
+})
+
 #endif /* QEMU_ATOMIC_H */
diff --git a/memory.c b/memory.c
index de57a16ece..41e2e67301 100644
--- a/memory.c
+++ b/memory.c
@@ -300,9 +300,9 @@ static void flatview_destroy(FlatView *view)
     g_free(view);
 }
 
-static void flatview_ref(FlatView *view)
+static bool flatview_ref(FlatView *view)
 {
-    atomic_inc(&view->ref);
+    return atomic_fetch_inc_nonzero(&view->ref) > 0;
 }
 
 static void flatview_unref(FlatView *view)
@@ -792,8 +792,12 @@ static FlatView *address_space_get_flatview(AddressSpace *as)
     FlatView *view;
 
     rcu_read_lock();
-    view = atomic_rcu_read(&as->current_map);
-    flatview_ref(view);
+    do {
+        view = atomic_rcu_read(&as->current_map);
+        /* If somebody has replaced as->current_map concurrently,
+         * flatview_ref returns false.
+         */
+    } while (!flatview_ref(view));
     rcu_read_unlock();
     return view;
 }
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 12/55] memory: Switch memory from using AddressSpace to FlatView
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (10 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 11/55] memory: avoid "resurrection" of dead FlatViews Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 13/55] memory: Cleanup after switching " Michael Roth
                   ` (42 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Alexey Kardashevskiy, Paolo Bonzini

From: Alexey Kardashevskiy <aik@ozlabs.ru>

FlatView's will be shared between AddressSpace's and subpage_t
and MemoryRegionSection cannot store AS anymore, hence this change.

In particular, for:

 typedef struct subpage_t {
     MemoryRegion iomem;
-    AddressSpace *as;
+    FlatView *fv;
     hwaddr base;
     uint16_t sub_section[];
 } subpage_t;

  struct MemoryRegionSection {
     MemoryRegion *mr;
-    AddressSpace *address_space;
+    FlatView *fv;
     hwaddr offset_within_region;
     Int128 size;
     hwaddr offset_within_address_space;
     bool readonly;
 };

This should cause no behavioural change.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Message-Id: <20170921085110.25598-7-aik@ozlabs.ru>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 166206845f7fd75e720e6feea0bb01957c8da07f)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 exec.c                         | 180 ++++++++++++++++++++++++-----------------
 hw/intc/openpic_kvm.c          |   2 +-
 include/exec/memory-internal.h |   2 +-
 include/exec/memory.h          |  51 ++++++++----
 memory.c                       |  33 ++++----
 5 files changed, 159 insertions(+), 109 deletions(-)

diff --git a/exec.c b/exec.c
index 3212c5e70d..b561098df3 100644
--- a/exec.c
+++ b/exec.c
@@ -199,7 +199,7 @@ struct AddressSpaceDispatch {
 #define SUBPAGE_IDX(addr) ((addr) & ~TARGET_PAGE_MASK)
 typedef struct subpage_t {
     MemoryRegion iomem;
-    AddressSpace *as;
+    FlatView *fv;
     hwaddr base;
     uint16_t sub_section[];
 } subpage_t;
@@ -469,13 +469,13 @@ address_space_translate_internal(AddressSpaceDispatch *d, hwaddr addr, hwaddr *x
 }
 
 /* Called from RCU critical section */
-static MemoryRegionSection address_space_do_translate(AddressSpace *as,
-                                                      hwaddr addr,
-                                                      hwaddr *xlat,
-                                                      hwaddr *plen,
-                                                      bool is_write,
-                                                      bool is_mmio,
-                                                      AddressSpace **target_as)
+static MemoryRegionSection flatview_do_translate(FlatView *fv,
+                                                 hwaddr addr,
+                                                 hwaddr *xlat,
+                                                 hwaddr *plen,
+                                                 bool is_write,
+                                                 bool is_mmio,
+                                                 AddressSpace **target_as)
 {
     IOMMUTLBEntry iotlb;
     MemoryRegionSection *section;
@@ -483,8 +483,9 @@ static MemoryRegionSection address_space_do_translate(AddressSpace *as,
     IOMMUMemoryRegionClass *imrc;
 
     for (;;) {
-        AddressSpaceDispatch *d = address_space_to_dispatch(as);
-        section = address_space_translate_internal(d, addr, &addr, plen, is_mmio);
+        section = address_space_translate_internal(
+                flatview_to_dispatch(fv), addr, &addr,
+                plen, is_mmio);
 
         iommu_mr = memory_region_get_iommu(section->mr);
         if (!iommu_mr) {
@@ -501,7 +502,7 @@ static MemoryRegionSection address_space_do_translate(AddressSpace *as,
             goto translate_fail;
         }
 
-        as = iotlb.target_as;
+        fv = address_space_to_flatview(iotlb.target_as);
         *target_as = iotlb.target_as;
     }
 
@@ -524,8 +525,8 @@ IOMMUTLBEntry address_space_get_iotlb_entry(AddressSpace *as, hwaddr addr,
     plen = (hwaddr)-1;
 
     /* This can never be MMIO. */
-    section = address_space_do_translate(as, addr, &xlat, &plen,
-                                         is_write, false, &as);
+    section = flatview_do_translate(address_space_to_flatview(as), addr,
+                                    &xlat, &plen, is_write, false, &as);
 
     /* Illegal translation */
     if (section.mr == &io_mem_unassigned) {
@@ -561,16 +562,15 @@ iotlb_fail:
 }
 
 /* Called from RCU critical section */
-MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr,
-                                      hwaddr *xlat, hwaddr *plen,
-                                      bool is_write)
+MemoryRegion *flatview_translate(FlatView *fv, hwaddr addr, hwaddr *xlat,
+                                 hwaddr *plen, bool is_write)
 {
     MemoryRegion *mr;
     MemoryRegionSection section;
+    AddressSpace *as = NULL;
 
     /* This can be MMIO, so setup MMIO bit. */
-    section = address_space_do_translate(as, addr, xlat, plen, is_write, true,
-                                         &as);
+    section = flatview_do_translate(fv, addr, xlat, plen, is_write, true, &as);
     mr = section.mr;
 
     if (xen_enabled() && memory_access_is_direct(mr, is_write)) {
@@ -1220,7 +1220,7 @@ hwaddr memory_region_section_get_iotlb(CPUState *cpu,
     } else {
         AddressSpaceDispatch *d;
 
-        d = address_space_to_dispatch(section->address_space);
+        d = flatview_to_dispatch(section->fv);
         iotlb = section - d->map.sections;
         iotlb += xlat;
     }
@@ -1246,7 +1246,7 @@ hwaddr memory_region_section_get_iotlb(CPUState *cpu,
 
 static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
                              uint16_t section);
-static subpage_t *subpage_init(AddressSpace *as, hwaddr base);
+static subpage_t *subpage_init(FlatView *fv, hwaddr base);
 
 static void *(*phys_mem_alloc)(size_t size, uint64_t *align) =
                                qemu_anon_ram_alloc;
@@ -1303,7 +1303,7 @@ static void phys_sections_free(PhysPageMap *map)
     g_free(map->nodes);
 }
 
-static void register_subpage(AddressSpace *as, AddressSpaceDispatch *d,
+static void register_subpage(FlatView *fv, AddressSpaceDispatch *d,
                              MemoryRegionSection *section)
 {
     subpage_t *subpage;
@@ -1319,8 +1319,8 @@ static void register_subpage(AddressSpace *as, AddressSpaceDispatch *d,
     assert(existing->mr->subpage || existing->mr == &io_mem_unassigned);
 
     if (!(existing->mr->subpage)) {
-        subpage = subpage_init(as, base);
-        subsection.address_space = as;
+        subpage = subpage_init(fv, base);
+        subsection.fv = fv;
         subsection.mr = &subpage->iomem;
         phys_page_set(d, base >> TARGET_PAGE_BITS, 1,
                       phys_section_add(&d->map, &subsection));
@@ -1346,7 +1346,7 @@ static void register_multipage(AddressSpaceDispatch *d,
     phys_page_set(d, start_addr >> TARGET_PAGE_BITS, num_pages, section_index);
 }
 
-void mem_add(AddressSpace *as, FlatView *fv, MemoryRegionSection *section)
+void mem_add(FlatView *fv, MemoryRegionSection *section)
 {
     AddressSpaceDispatch *d = flatview_to_dispatch(fv);
     MemoryRegionSection now = *section, remain = *section;
@@ -1357,7 +1357,7 @@ void mem_add(AddressSpace *as, FlatView *fv, MemoryRegionSection *section)
                        - now.offset_within_address_space;
 
         now.size = int128_min(int128_make64(left), now.size);
-        register_subpage(as, d, &now);
+        register_subpage(fv, d, &now);
     } else {
         now.size = int128_zero();
     }
@@ -1367,10 +1367,10 @@ void mem_add(AddressSpace *as, FlatView *fv, MemoryRegionSection *section)
         remain.offset_within_region += int128_get64(now.size);
         now = remain;
         if (int128_lt(remain.size, page_size)) {
-            register_subpage(as, d, &now);
+            register_subpage(fv, d, &now);
         } else if (remain.offset_within_address_space & ~TARGET_PAGE_MASK) {
             now.size = page_size;
-            register_subpage(as, d, &now);
+            register_subpage(fv, d, &now);
         } else {
             now.size = int128_and(now.size, int128_neg(page_size));
             register_multipage(d, &now);
@@ -2501,6 +2501,11 @@ static const MemoryRegionOps watch_mem_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
+static MemTxResult flatview_write(FlatView *fv, hwaddr addr, MemTxAttrs attrs,
+                                  const uint8_t *buf, int len);
+static bool flatview_access_valid(FlatView *fv, hwaddr addr, int len,
+                                  bool is_write);
+
 static MemTxResult subpage_read(void *opaque, hwaddr addr, uint64_t *data,
                                 unsigned len, MemTxAttrs attrs)
 {
@@ -2512,8 +2517,7 @@ static MemTxResult subpage_read(void *opaque, hwaddr addr, uint64_t *data,
     printf("%s: subpage %p len %u addr " TARGET_FMT_plx "\n", __func__,
            subpage, len, addr);
 #endif
-    res = address_space_read(subpage->as, addr + subpage->base,
-                             attrs, buf, len);
+    res = flatview_read(subpage->fv, addr + subpage->base, attrs, buf, len);
     if (res) {
         return res;
     }
@@ -2562,8 +2566,7 @@ static MemTxResult subpage_write(void *opaque, hwaddr addr,
     default:
         abort();
     }
-    return address_space_write(subpage->as, addr + subpage->base,
-                               attrs, buf, len);
+    return flatview_write(subpage->fv, addr + subpage->base, attrs, buf, len);
 }
 
 static bool subpage_accepts(void *opaque, hwaddr addr,
@@ -2575,8 +2578,8 @@ static bool subpage_accepts(void *opaque, hwaddr addr,
            __func__, subpage, is_write ? 'w' : 'r', len, addr);
 #endif
 
-    return address_space_access_valid(subpage->as, addr + subpage->base,
-                                      len, is_write);
+    return flatview_access_valid(subpage->fv, addr + subpage->base,
+                                 len, is_write);
 }
 
 static const MemoryRegionOps subpage_ops = {
@@ -2610,12 +2613,12 @@ static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
     return 0;
 }
 
-static subpage_t *subpage_init(AddressSpace *as, hwaddr base)
+static subpage_t *subpage_init(FlatView *fv, hwaddr base)
 {
     subpage_t *mmio;
 
     mmio = g_malloc0(sizeof(subpage_t) + TARGET_PAGE_SIZE * sizeof(uint16_t));
-    mmio->as = as;
+    mmio->fv = fv;
     mmio->base = base;
     memory_region_init_io(&mmio->iomem, NULL, &subpage_ops, mmio,
                           NULL, TARGET_PAGE_SIZE);
@@ -2629,12 +2632,11 @@ static subpage_t *subpage_init(AddressSpace *as, hwaddr base)
     return mmio;
 }
 
-static uint16_t dummy_section(PhysPageMap *map, AddressSpace *as,
-                              MemoryRegion *mr)
+static uint16_t dummy_section(PhysPageMap *map, FlatView *fv, MemoryRegion *mr)
 {
-    assert(as);
+    assert(fv);
     MemoryRegionSection section = {
-        .address_space = as,
+        .fv = fv,
         .mr = mr,
         .offset_within_address_space = 0,
         .offset_within_region = 0,
@@ -2673,16 +2675,17 @@ static void io_mem_init(void)
 
 AddressSpaceDispatch *mem_begin(AddressSpace *as)
 {
+    FlatView *fv = address_space_to_flatview(as);
     AddressSpaceDispatch *d = g_new0(AddressSpaceDispatch, 1);
     uint16_t n;
 
-    n = dummy_section(&d->map, as, &io_mem_unassigned);
+    n = dummy_section(&d->map, fv, &io_mem_unassigned);
     assert(n == PHYS_SECTION_UNASSIGNED);
-    n = dummy_section(&d->map, as, &io_mem_notdirty);
+    n = dummy_section(&d->map, fv, &io_mem_notdirty);
     assert(n == PHYS_SECTION_NOTDIRTY);
-    n = dummy_section(&d->map, as, &io_mem_rom);
+    n = dummy_section(&d->map, fv, &io_mem_rom);
     assert(n == PHYS_SECTION_ROM);
-    n = dummy_section(&d->map, as, &io_mem_watch);
+    n = dummy_section(&d->map, fv, &io_mem_watch);
     assert(n == PHYS_SECTION_WATCH);
 
     d->phys_map  = (PhysPageEntry) { .ptr = PHYS_MAP_NODE_NIL, .skip = 1 };
@@ -2862,11 +2865,11 @@ static bool prepare_mmio_access(MemoryRegion *mr)
 }
 
 /* Called within RCU critical section.  */
-static MemTxResult address_space_write_continue(AddressSpace *as, hwaddr addr,
-                                                MemTxAttrs attrs,
-                                                const uint8_t *buf,
-                                                int len, hwaddr addr1,
-                                                hwaddr l, MemoryRegion *mr)
+static MemTxResult flatview_write_continue(FlatView *fv, hwaddr addr,
+                                           MemTxAttrs attrs,
+                                           const uint8_t *buf,
+                                           int len, hwaddr addr1,
+                                           hwaddr l, MemoryRegion *mr)
 {
     uint8_t *ptr;
     uint64_t val;
@@ -2928,14 +2931,14 @@ static MemTxResult address_space_write_continue(AddressSpace *as, hwaddr addr,
         }
 
         l = len;
-        mr = address_space_translate(as, addr, &addr1, &l, true);
+        mr = flatview_translate(fv, addr, &addr1, &l, true);
     }
 
     return result;
 }
 
-MemTxResult address_space_write(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
-                                const uint8_t *buf, int len)
+static MemTxResult flatview_write(FlatView *fv, hwaddr addr, MemTxAttrs attrs,
+                                  const uint8_t *buf, int len)
 {
     hwaddr l;
     hwaddr addr1;
@@ -2945,20 +2948,27 @@ MemTxResult address_space_write(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
     if (len > 0) {
         rcu_read_lock();
         l = len;
-        mr = address_space_translate(as, addr, &addr1, &l, true);
-        result = address_space_write_continue(as, addr, attrs, buf, len,
-                                              addr1, l, mr);
+        mr = flatview_translate(fv, addr, &addr1, &l, true);
+        result = flatview_write_continue(fv, addr, attrs, buf, len,
+                                         addr1, l, mr);
         rcu_read_unlock();
     }
 
     return result;
 }
 
+MemTxResult address_space_write(AddressSpace *as, hwaddr addr,
+                                              MemTxAttrs attrs,
+                                              const uint8_t *buf, int len)
+{
+    return flatview_write(address_space_to_flatview(as), addr, attrs, buf, len);
+}
+
 /* Called within RCU critical section.  */
-MemTxResult address_space_read_continue(AddressSpace *as, hwaddr addr,
-                                        MemTxAttrs attrs, uint8_t *buf,
-                                        int len, hwaddr addr1, hwaddr l,
-                                        MemoryRegion *mr)
+MemTxResult flatview_read_continue(FlatView *fv, hwaddr addr,
+                                   MemTxAttrs attrs, uint8_t *buf,
+                                   int len, hwaddr addr1, hwaddr l,
+                                   MemoryRegion *mr)
 {
     uint8_t *ptr;
     uint64_t val;
@@ -3018,14 +3028,14 @@ MemTxResult address_space_read_continue(AddressSpace *as, hwaddr addr,
         }
 
         l = len;
-        mr = address_space_translate(as, addr, &addr1, &l, false);
+        mr = flatview_translate(fv, addr, &addr1, &l, false);
     }
 
     return result;
 }
 
-MemTxResult address_space_read_full(AddressSpace *as, hwaddr addr,
-                                    MemTxAttrs attrs, uint8_t *buf, int len)
+MemTxResult flatview_read_full(FlatView *fv, hwaddr addr,
+                               MemTxAttrs attrs, uint8_t *buf, int len)
 {
     hwaddr l;
     hwaddr addr1;
@@ -3035,25 +3045,33 @@ MemTxResult address_space_read_full(AddressSpace *as, hwaddr addr,
     if (len > 0) {
         rcu_read_lock();
         l = len;
-        mr = address_space_translate(as, addr, &addr1, &l, false);
-        result = address_space_read_continue(as, addr, attrs, buf, len,
-                                             addr1, l, mr);
+        mr = flatview_translate(fv, addr, &addr1, &l, false);
+        result = flatview_read_continue(fv, addr, attrs, buf, len,
+                                        addr1, l, mr);
         rcu_read_unlock();
     }
 
     return result;
 }
 
-MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
-                             uint8_t *buf, int len, bool is_write)
+static MemTxResult flatview_rw(FlatView *fv, hwaddr addr, MemTxAttrs attrs,
+                               uint8_t *buf, int len, bool is_write)
 {
     if (is_write) {
-        return address_space_write(as, addr, attrs, (uint8_t *)buf, len);
+        return flatview_write(fv, addr, attrs, (uint8_t *)buf, len);
     } else {
-        return address_space_read(as, addr, attrs, (uint8_t *)buf, len);
+        return flatview_read(fv, addr, attrs, (uint8_t *)buf, len);
     }
 }
 
+MemTxResult address_space_rw(AddressSpace *as, hwaddr addr,
+                             MemTxAttrs attrs, uint8_t *buf,
+                             int len, bool is_write)
+{
+    return flatview_rw(address_space_to_flatview(as),
+                       addr, attrs, buf, len, is_write);
+}
+
 void cpu_physical_memory_rw(hwaddr addr, uint8_t *buf,
                             int len, int is_write)
 {
@@ -3211,7 +3229,8 @@ static void cpu_notify_map_clients(void)
     qemu_mutex_unlock(&map_client_list_lock);
 }
 
-bool address_space_access_valid(AddressSpace *as, hwaddr addr, int len, bool is_write)
+static bool flatview_access_valid(FlatView *fv, hwaddr addr, int len,
+                                  bool is_write)
 {
     MemoryRegion *mr;
     hwaddr l, xlat;
@@ -3219,7 +3238,7 @@ bool address_space_access_valid(AddressSpace *as, hwaddr addr, int len, bool is_
     rcu_read_lock();
     while (len > 0) {
         l = len;
-        mr = address_space_translate(as, addr, &xlat, &l, is_write);
+        mr = flatview_translate(fv, addr, &xlat, &l, is_write);
         if (!memory_access_is_direct(mr, is_write)) {
             l = memory_access_size(mr, l, addr);
             if (!memory_region_access_valid(mr, xlat, l, is_write)) {
@@ -3235,8 +3254,16 @@ bool address_space_access_valid(AddressSpace *as, hwaddr addr, int len, bool is_
     return true;
 }
 
+bool address_space_access_valid(AddressSpace *as, hwaddr addr,
+                                int len, bool is_write)
+{
+    return flatview_access_valid(address_space_to_flatview(as),
+                                 addr, len, is_write);
+}
+
 static hwaddr
-address_space_extend_translation(AddressSpace *as, hwaddr addr, hwaddr target_len,
+flatview_extend_translation(FlatView *fv, hwaddr addr,
+                                 hwaddr target_len,
                                  MemoryRegion *mr, hwaddr base, hwaddr len,
                                  bool is_write)
 {
@@ -3253,7 +3280,8 @@ address_space_extend_translation(AddressSpace *as, hwaddr addr, hwaddr target_le
         }
 
         len = target_len;
-        this_mr = address_space_translate(as, addr, &xlat, &len, is_write);
+        this_mr = flatview_translate(fv, addr, &xlat,
+                                                   &len, is_write);
         if (this_mr != mr || xlat != base + done) {
             return done;
         }
@@ -3276,6 +3304,7 @@ void *address_space_map(AddressSpace *as,
     hwaddr l, xlat;
     MemoryRegion *mr;
     void *ptr;
+    FlatView *fv = address_space_to_flatview(as);
 
     if (len == 0) {
         return NULL;
@@ -3283,7 +3312,7 @@ void *address_space_map(AddressSpace *as,
 
     l = len;
     rcu_read_lock();
-    mr = address_space_translate(as, addr, &xlat, &l, is_write);
+    mr = flatview_translate(fv, addr, &xlat, &l, is_write);
 
     if (!memory_access_is_direct(mr, is_write)) {
         if (atomic_xchg(&bounce.in_use, true)) {
@@ -3299,7 +3328,7 @@ void *address_space_map(AddressSpace *as,
         memory_region_ref(mr);
         bounce.mr = mr;
         if (!is_write) {
-            address_space_read(as, addr, MEMTXATTRS_UNSPECIFIED,
+            flatview_read(fv, addr, MEMTXATTRS_UNSPECIFIED,
                                bounce.buffer, l);
         }
 
@@ -3310,7 +3339,8 @@ void *address_space_map(AddressSpace *as,
 
 
     memory_region_ref(mr);
-    *plen = address_space_extend_translation(as, addr, len, mr, xlat, l, is_write);
+    *plen = flatview_extend_translation(fv, addr, len, mr, xlat,
+                                             l, is_write);
     ptr = qemu_ram_ptr_length(mr->ram_block, xlat, plen, true);
     rcu_read_unlock();
 
diff --git a/hw/intc/openpic_kvm.c b/hw/intc/openpic_kvm.c
index 0518e017c4..fa83420254 100644
--- a/hw/intc/openpic_kvm.c
+++ b/hw/intc/openpic_kvm.c
@@ -124,7 +124,7 @@ static void kvm_openpic_region_add(MemoryListener *listener,
     uint64_t reg_base;
     int ret;
 
-    if (section->address_space != &address_space_memory) {
+    if (section->fv != address_space_to_flatview(&address_space_memory)) {
         abort();
     }
 
diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h
index 6e08eda256..1cf8ad9869 100644
--- a/include/exec/memory-internal.h
+++ b/include/exec/memory-internal.h
@@ -27,7 +27,7 @@ extern const MemoryRegionOps unassigned_mem_ops;
 bool memory_region_access_valid(MemoryRegion *mr, hwaddr addr,
                                 unsigned size, bool is_write);
 
-void mem_add(AddressSpace *as, FlatView *fv, MemoryRegionSection *section);
+void mem_add(FlatView *fv, MemoryRegionSection *section);
 AddressSpaceDispatch *mem_begin(AddressSpace *as);
 void mem_commit(AddressSpaceDispatch *d);
 
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 8f26d63417..6715551fc6 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -48,6 +48,7 @@
 
 typedef struct MemoryRegionOps MemoryRegionOps;
 typedef struct MemoryRegionMmio MemoryRegionMmio;
+typedef struct FlatView FlatView;
 
 struct MemoryRegionMmio {
     CPUReadMemoryFunc *read[3];
@@ -330,6 +331,8 @@ struct AddressSpace {
     QTAILQ_ENTRY(AddressSpace) address_spaces_link;
 };
 
+FlatView *address_space_to_flatview(AddressSpace *as);
+
 /**
  * MemoryRegionSection: describes a fragment of a #MemoryRegion
  *
@@ -343,7 +346,7 @@ struct AddressSpace {
  */
 struct MemoryRegionSection {
     MemoryRegion *mr;
-    AddressSpace *address_space;
+    FlatView *fv;
     hwaddr offset_within_region;
     Int128 size;
     hwaddr offset_within_address_space;
@@ -1852,9 +1855,17 @@ IOMMUTLBEntry address_space_get_iotlb_entry(AddressSpace *as, hwaddr addr,
  * @len: pointer to length
  * @is_write: indicates the transfer direction
  */
-MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr,
-                                      hwaddr *xlat, hwaddr *len,
-                                      bool is_write);
+MemoryRegion *flatview_translate(FlatView *fv,
+                                 hwaddr addr, hwaddr *xlat,
+                                 hwaddr *len, bool is_write);
+
+static inline MemoryRegion *address_space_translate(AddressSpace *as,
+                                                    hwaddr addr, hwaddr *xlat,
+                                                    hwaddr *len, bool is_write)
+{
+    return flatview_translate(address_space_to_flatview(as),
+                              addr, xlat, len, is_write);
+}
 
 /* address_space_access_valid: check for validity of accessing an address
  * space range
@@ -1905,12 +1916,13 @@ void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len,
 
 
 /* Internal functions, part of the implementation of address_space_read.  */
-MemTxResult address_space_read_continue(AddressSpace *as, hwaddr addr,
-                                        MemTxAttrs attrs, uint8_t *buf,
-                                        int len, hwaddr addr1, hwaddr l,
-					MemoryRegion *mr);
-MemTxResult address_space_read_full(AddressSpace *as, hwaddr addr,
-                                    MemTxAttrs attrs, uint8_t *buf, int len);
+MemTxResult flatview_read_continue(FlatView *fv, hwaddr addr,
+                                   MemTxAttrs attrs, uint8_t *buf,
+                                   int len, hwaddr addr1, hwaddr l,
+                                   MemoryRegion *mr);
+
+MemTxResult flatview_read_full(FlatView *fv, hwaddr addr,
+                               MemTxAttrs attrs, uint8_t *buf, int len);
 void *qemu_map_ram_ptr(RAMBlock *ram_block, ram_addr_t addr);
 
 static inline bool memory_access_is_direct(MemoryRegion *mr, bool is_write)
@@ -1937,8 +1949,8 @@ static inline bool memory_access_is_direct(MemoryRegion *mr, bool is_write)
  * @buf: buffer with the data transferred
  */
 static inline __attribute__((__always_inline__))
-MemTxResult address_space_read(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
-                               uint8_t *buf, int len)
+MemTxResult flatview_read(FlatView *fv, hwaddr addr, MemTxAttrs attrs,
+                          uint8_t *buf, int len)
 {
     MemTxResult result = MEMTX_OK;
     hwaddr l, addr1;
@@ -1949,22 +1961,29 @@ MemTxResult address_space_read(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
         if (len) {
             rcu_read_lock();
             l = len;
-            mr = address_space_translate(as, addr, &addr1, &l, false);
+            mr = flatview_translate(fv, addr, &addr1, &l, false);
             if (len == l && memory_access_is_direct(mr, false)) {
                 ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
                 memcpy(buf, ptr, len);
             } else {
-                result = address_space_read_continue(as, addr, attrs, buf, len,
-                                                     addr1, l, mr);
+                result = flatview_read_continue(fv, addr, attrs, buf, len,
+                                                addr1, l, mr);
             }
             rcu_read_unlock();
         }
     } else {
-        result = address_space_read_full(as, addr, attrs, buf, len);
+        result = flatview_read_full(fv, addr, attrs, buf, len);
     }
     return result;
 }
 
+static inline MemTxResult address_space_read(AddressSpace *as, hwaddr addr,
+                                             MemTxAttrs attrs, uint8_t *buf,
+                                             int len)
+{
+    return flatview_read(address_space_to_flatview(as), addr, attrs, buf, len);
+}
+
 /**
  * address_space_read_cached: read from a cached RAM region
  *
diff --git a/memory.c b/memory.c
index 41e2e67301..6678a538d2 100644
--- a/memory.c
+++ b/memory.c
@@ -154,7 +154,8 @@ enum ListenerDirection { Forward, Reverse };
 /* No need to ref/unref .mr, the FlatRange keeps it alive.  */
 #define MEMORY_LISTENER_UPDATE_REGION(fr, as, dir, callback, _args...)  \
     do {                                                                \
-        MemoryRegionSection mrs = section_from_flat_range(fr, as);      \
+        MemoryRegionSection mrs = section_from_flat_range(fr,           \
+                address_space_to_flatview(as));                         \
         MEMORY_LISTENER_CALL(as, callback, dir, &mrs, ##_args);         \
     } while(0)
 
@@ -208,7 +209,6 @@ static bool memory_region_ioeventfd_equal(MemoryRegionIoeventfd a,
 }
 
 typedef struct FlatRange FlatRange;
-typedef struct FlatView FlatView;
 
 /* Range of memory in the global map.  Addresses are absolute. */
 struct FlatRange {
@@ -238,11 +238,11 @@ typedef struct AddressSpaceOps AddressSpaceOps;
     for (var = (view)->ranges; var < (view)->ranges + (view)->nr; ++var)
 
 static inline MemoryRegionSection
-section_from_flat_range(FlatRange *fr, AddressSpace *as)
+section_from_flat_range(FlatRange *fr, FlatView *fv)
 {
     return (MemoryRegionSection) {
         .mr = fr->mr,
-        .address_space = as,
+        .fv = fv,
         .offset_within_region = fr->offset_in_region,
         .size = fr->addr.size,
         .offset_within_address_space = int128_get64(fr->addr.start),
@@ -312,7 +312,7 @@ static void flatview_unref(FlatView *view)
     }
 }
 
-static FlatView *address_space_to_flatview(AddressSpace *as)
+FlatView *address_space_to_flatview(AddressSpace *as)
 {
     return atomic_rcu_read(&as->current_map);
 }
@@ -760,7 +760,7 @@ static void address_space_add_del_ioeventfds(AddressSpace *as,
                                                   fds_new[inew]))) {
             fd = &fds_old[iold];
             section = (MemoryRegionSection) {
-                .address_space = as,
+                .fv = address_space_to_flatview(as),
                 .offset_within_address_space = int128_get64(fd->addr.start),
                 .size = fd->addr.size,
             };
@@ -773,7 +773,7 @@ static void address_space_add_del_ioeventfds(AddressSpace *as,
                                                          fds_old[iold]))) {
             fd = &fds_new[inew];
             section = (MemoryRegionSection) {
-                .address_space = as,
+                .fv = address_space_to_flatview(as),
                 .offset_within_address_space = int128_get64(fd->addr.start),
                 .size = fd->addr.size,
             };
@@ -793,7 +793,7 @@ static FlatView *address_space_get_flatview(AddressSpace *as)
 
     rcu_read_lock();
     do {
-        view = atomic_rcu_read(&as->current_map);
+        view = address_space_to_flatview(as);
         /* If somebody has replaced as->current_map concurrently,
          * flatview_ref returns false.
          */
@@ -912,8 +912,8 @@ static void address_space_update_topology(AddressSpace *as)
     new_view->dispatch = mem_begin(as);
     for (i = 0; i < new_view->nr; i++) {
         MemoryRegionSection mrs =
-            section_from_flat_range(&new_view->ranges[i], as);
-        mem_add(as, new_view, &mrs);
+            section_from_flat_range(&new_view->ranges[i], new_view);
+        mem_add(new_view, &mrs);
     }
     mem_commit(new_view->dispatch);
 
@@ -1869,7 +1869,7 @@ void memory_region_sync_dirty_bitmap(MemoryRegion *mr)
         view = address_space_get_flatview(as);
         FOR_EACH_FLAT_RANGE(fr, view) {
             if (fr->mr == mr) {
-                MemoryRegionSection mrs = section_from_flat_range(fr, as);
+                MemoryRegionSection mrs = section_from_flat_range(fr, view);
                 listener->log_sync(listener, &mrs);
             }
         }
@@ -1972,7 +1972,7 @@ static void memory_region_update_coalesced_range_as(MemoryRegion *mr, AddressSpa
     FOR_EACH_FLAT_RANGE(fr, view) {
         if (fr->mr == mr) {
             section = (MemoryRegionSection) {
-                .address_space = as,
+                .fv = view,
                 .offset_within_address_space = int128_get64(fr->addr.start),
                 .size = fr->addr.size,
             };
@@ -2323,7 +2323,7 @@ static MemoryRegionSection memory_region_find_rcu(MemoryRegion *mr,
     }
     range = addrrange_make(int128_make64(addr), int128_make64(size));
 
-    view = atomic_rcu_read(&as->current_map);
+    view = address_space_to_flatview(as);
     fr = flatview_lookup(view, range);
     if (!fr) {
         return ret;
@@ -2334,7 +2334,7 @@ static MemoryRegionSection memory_region_find_rcu(MemoryRegion *mr,
     }
 
     ret.mr = fr->mr;
-    ret.address_space = as;
+    ret.fv = view;
     range = addrrange_intersection(range, fr->addr);
     ret.offset_within_region = fr->offset_in_region;
     ret.offset_within_region += int128_get64(int128_sub(range.start,
@@ -2383,7 +2383,8 @@ void memory_global_dirty_log_sync(void)
         view = address_space_get_flatview(as);
         FOR_EACH_FLAT_RANGE(fr, view) {
             if (fr->dirty_log_mask) {
-                MemoryRegionSection mrs = section_from_flat_range(fr, as);
+                MemoryRegionSection mrs = section_from_flat_range(fr, view);
+
                 listener->log_sync(listener, &mrs);
             }
         }
@@ -2468,7 +2469,7 @@ static void listener_add_address_space(MemoryListener *listener,
     FOR_EACH_FLAT_RANGE(fr, view) {
         MemoryRegionSection section = {
             .mr = fr->mr,
-            .address_space = as,
+            .fv = view,
             .offset_within_region = fr->offset_in_region,
             .size = fr->addr.size,
             .offset_within_address_space = int128_get64(fr->addr.start),
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 13/55] memory: Cleanup after switching to FlatView
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (11 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 12/55] memory: Switch memory from using AddressSpace to FlatView Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 14/55] memory: Rename mem_begin/mem_commit/mem_add helpers Michael Roth
                   ` (41 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Alexey Kardashevskiy, Paolo Bonzini

From: Alexey Kardashevskiy <aik@ozlabs.ru>

We store AddressSpaceDispatch* in FlatView anyway so there is no need
to carry it from mem_add() to register_subpage/register_multipage.

This should cause no behavioural change.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Message-Id: <20170921085110.25598-8-aik@ozlabs.ru>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 9950322a593ff900a860fb52938159461798a831)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 exec.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/exec.c b/exec.c
index b561098df3..3e02b82c05 100644
--- a/exec.c
+++ b/exec.c
@@ -1303,9 +1303,9 @@ static void phys_sections_free(PhysPageMap *map)
     g_free(map->nodes);
 }
 
-static void register_subpage(FlatView *fv, AddressSpaceDispatch *d,
-                             MemoryRegionSection *section)
+static void register_subpage(FlatView *fv, MemoryRegionSection *section)
 {
+    AddressSpaceDispatch *d = flatview_to_dispatch(fv);
     subpage_t *subpage;
     hwaddr base = section->offset_within_address_space
         & TARGET_PAGE_MASK;
@@ -1334,9 +1334,10 @@ static void register_subpage(FlatView *fv, AddressSpaceDispatch *d,
 }
 
 
-static void register_multipage(AddressSpaceDispatch *d,
+static void register_multipage(FlatView *fv,
                                MemoryRegionSection *section)
 {
+    AddressSpaceDispatch *d = flatview_to_dispatch(fv);
     hwaddr start_addr = section->offset_within_address_space;
     uint16_t section_index = phys_section_add(&d->map, section);
     uint64_t num_pages = int128_get64(int128_rshift(section->size,
@@ -1348,7 +1349,6 @@ static void register_multipage(AddressSpaceDispatch *d,
 
 void mem_add(FlatView *fv, MemoryRegionSection *section)
 {
-    AddressSpaceDispatch *d = flatview_to_dispatch(fv);
     MemoryRegionSection now = *section, remain = *section;
     Int128 page_size = int128_make64(TARGET_PAGE_SIZE);
 
@@ -1357,7 +1357,7 @@ void mem_add(FlatView *fv, MemoryRegionSection *section)
                        - now.offset_within_address_space;
 
         now.size = int128_min(int128_make64(left), now.size);
-        register_subpage(fv, d, &now);
+        register_subpage(fv, &now);
     } else {
         now.size = int128_zero();
     }
@@ -1367,13 +1367,13 @@ void mem_add(FlatView *fv, MemoryRegionSection *section)
         remain.offset_within_region += int128_get64(now.size);
         now = remain;
         if (int128_lt(remain.size, page_size)) {
-            register_subpage(fv, d, &now);
+            register_subpage(fv, &now);
         } else if (remain.offset_within_address_space & ~TARGET_PAGE_MASK) {
             now.size = page_size;
-            register_subpage(fv, d, &now);
+            register_subpage(fv, &now);
         } else {
             now.size = int128_and(now.size, int128_neg(page_size));
-            register_multipage(d, &now);
+            register_multipage(fv, &now);
         }
     }
 }
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 14/55] memory: Rename mem_begin/mem_commit/mem_add helpers
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (12 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 13/55] memory: Cleanup after switching " Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 15/55] memory: Store physical root MR in FlatView Michael Roth
                   ` (40 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Alexey Kardashevskiy, Paolo Bonzini

From: Alexey Kardashevskiy <aik@ozlabs.ru>

This renames some helpers to reflect better what they do.

This should cause no behavioural change.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Message-Id: <20170921085110.25598-9-aik@ozlabs.ru>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 8629d3fcb77e9775e44d9051bad0fb5187925eae)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 exec.c                         | 12 +++---------
 include/exec/memory-internal.h |  6 +++---
 memory.c                       |  6 +++---
 3 files changed, 9 insertions(+), 15 deletions(-)

diff --git a/exec.c b/exec.c
index 3e02b82c05..b1f29d35d8 100644
--- a/exec.c
+++ b/exec.c
@@ -359,7 +359,7 @@ static void phys_page_compact(PhysPageEntry *lp, Node *nodes)
     }
 }
 
-static void phys_page_compact_all(AddressSpaceDispatch *d, int nodes_nb)
+void address_space_dispatch_compact(AddressSpaceDispatch *d)
 {
     if (d->phys_map.skip) {
         phys_page_compact(&d->phys_map, d->map.nodes);
@@ -1347,7 +1347,7 @@ static void register_multipage(FlatView *fv,
     phys_page_set(d, start_addr >> TARGET_PAGE_BITS, num_pages, section_index);
 }
 
-void mem_add(FlatView *fv, MemoryRegionSection *section)
+void flatview_add_to_dispatch(FlatView *fv, MemoryRegionSection *section)
 {
     MemoryRegionSection now = *section, remain = *section;
     Int128 page_size = int128_make64(TARGET_PAGE_SIZE);
@@ -2673,9 +2673,8 @@ static void io_mem_init(void)
                           NULL, UINT64_MAX);
 }
 
-AddressSpaceDispatch *mem_begin(AddressSpace *as)
+AddressSpaceDispatch *address_space_dispatch_new(FlatView *fv)
 {
-    FlatView *fv = address_space_to_flatview(as);
     AddressSpaceDispatch *d = g_new0(AddressSpaceDispatch, 1);
     uint16_t n;
 
@@ -2699,11 +2698,6 @@ void address_space_dispatch_free(AddressSpaceDispatch *d)
     g_free(d);
 }
 
-void mem_commit(AddressSpaceDispatch *d)
-{
-    phys_page_compact_all(d, d->map.nodes_nb);
-}
-
 static void tcg_commit(MemoryListener *listener)
 {
     CPUAddressSpace *cpuas;
diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h
index 1cf8ad9869..d4a35c6e96 100644
--- a/include/exec/memory-internal.h
+++ b/include/exec/memory-internal.h
@@ -27,9 +27,9 @@ extern const MemoryRegionOps unassigned_mem_ops;
 bool memory_region_access_valid(MemoryRegion *mr, hwaddr addr,
                                 unsigned size, bool is_write);
 
-void mem_add(FlatView *fv, MemoryRegionSection *section);
-AddressSpaceDispatch *mem_begin(AddressSpace *as);
-void mem_commit(AddressSpaceDispatch *d);
+void flatview_add_to_dispatch(FlatView *fv, MemoryRegionSection *section);
+AddressSpaceDispatch *address_space_dispatch_new(FlatView *fv);
+void address_space_dispatch_compact(AddressSpaceDispatch *d);
 
 AddressSpaceDispatch *address_space_to_dispatch(AddressSpace *as);
 AddressSpaceDispatch *flatview_to_dispatch(FlatView *fv);
diff --git a/memory.c b/memory.c
index 6678a538d2..b7d253636b 100644
--- a/memory.c
+++ b/memory.c
@@ -909,13 +909,13 @@ static void address_space_update_topology(AddressSpace *as)
     FlatView *new_view = generate_memory_topology(as->root);
     int i;
 
-    new_view->dispatch = mem_begin(as);
+    new_view->dispatch = address_space_dispatch_new(new_view);
     for (i = 0; i < new_view->nr; i++) {
         MemoryRegionSection mrs =
             section_from_flat_range(&new_view->ranges[i], new_view);
-        mem_add(new_view, &mrs);
+        flatview_add_to_dispatch(new_view, &mrs);
     }
-    mem_commit(new_view->dispatch);
+    address_space_dispatch_compact(new_view->dispatch);
 
     if (!QTAILQ_EMPTY(&as->listeners)) {
         address_space_update_topology_pass(as, old_view, new_view, false);
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 15/55] memory: Store physical root MR in FlatView
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (13 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 14/55] memory: Rename mem_begin/mem_commit/mem_add helpers Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 16/55] memory: Alloc dispatch tree where topology is generared Michael Roth
                   ` (39 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Alexey Kardashevskiy, Paolo Bonzini

From: Alexey Kardashevskiy <aik@ozlabs.ru>

Address spaces get to keep a root MR (alias or not) but FlatView stores
the actual MR as this is going to be used later on to decide whether to
share a particular FlatView or not.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Message-Id: <20170921085110.25598-10-aik@ozlabs.ru>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 89c177bbdd6cf8e50b3fd4831697d50e195d6432)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 memory.c | 26 ++++++++++++++++++++++----
 1 file changed, 22 insertions(+), 4 deletions(-)

diff --git a/memory.c b/memory.c
index b7d253636b..7972235a06 100644
--- a/memory.c
+++ b/memory.c
@@ -230,6 +230,7 @@ struct FlatView {
     unsigned nr;
     unsigned nr_allocated;
     struct AddressSpaceDispatch *dispatch;
+    MemoryRegion *root;
 };
 
 typedef struct AddressSpaceOps AddressSpaceOps;
@@ -259,12 +260,14 @@ static bool flatrange_equal(FlatRange *a, FlatRange *b)
         && a->readonly == b->readonly;
 }
 
-static FlatView *flatview_new(void)
+static FlatView *flatview_new(MemoryRegion *mr_root)
 {
     FlatView *view;
 
     view = g_new0(FlatView, 1);
     view->ref = 1;
+    view->root = mr_root;
+    memory_region_ref(mr_root);
 
     return view;
 }
@@ -297,6 +300,7 @@ static void flatview_destroy(FlatView *view)
         memory_region_unref(view->ranges[i].mr);
     }
     g_free(view->ranges);
+    memory_region_unref(view->root);
     g_free(view);
 }
 
@@ -722,12 +726,25 @@ static void render_memory_region(FlatView *view,
     }
 }
 
+static MemoryRegion *memory_region_get_flatview_root(MemoryRegion *mr)
+{
+    while (mr->alias && !mr->alias_offset &&
+           int128_ge(mr->size, mr->alias->size)) {
+        /* The alias is included in its entirety.  Use it as
+         * the "real" root, so that we can share more FlatViews.
+         */
+        mr = mr->alias;
+    }
+
+    return mr;
+}
+
 /* Render a memory topology into a list of disjoint absolute ranges. */
 static FlatView *generate_memory_topology(MemoryRegion *mr)
 {
     FlatView *view;
 
-    view = flatview_new();
+    view = flatview_new(mr);
 
     if (mr) {
         render_memory_region(view, mr, int128_zero(),
@@ -906,7 +923,8 @@ static void address_space_update_topology_pass(AddressSpace *as,
 static void address_space_update_topology(AddressSpace *as)
 {
     FlatView *old_view = address_space_get_flatview(as);
-    FlatView *new_view = generate_memory_topology(as->root);
+    MemoryRegion *physmr = memory_region_get_flatview_root(old_view->root);
+    FlatView *new_view = generate_memory_topology(physmr);
     int i;
 
     new_view->dispatch = address_space_dispatch_new(new_view);
@@ -2649,7 +2667,7 @@ void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name)
     as->ref_count = 1;
     as->root = root;
     as->malloced = false;
-    as->current_map = flatview_new();
+    as->current_map = flatview_new(root);
     as->ioeventfd_nb = 0;
     as->ioeventfds = NULL;
     QTAILQ_INIT(&as->listeners);
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 16/55] memory: Alloc dispatch tree where topology is generared
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (14 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 15/55] memory: Store physical root MR in FlatView Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 17/55] memory: Move address_space_update_ioeventfds Michael Roth
                   ` (38 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Alexey Kardashevskiy, Paolo Bonzini

From: Alexey Kardashevskiy <aik@ozlabs.ru>

This is to make next patches simpler.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Message-Id: <20170921085110.25598-11-aik@ozlabs.ru>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 9bf561e36cf8fed9565011a19ba9ea0100e1811e)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 memory.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/memory.c b/memory.c
index 7972235a06..8034520148 100644
--- a/memory.c
+++ b/memory.c
@@ -742,6 +742,7 @@ static MemoryRegion *memory_region_get_flatview_root(MemoryRegion *mr)
 /* Render a memory topology into a list of disjoint absolute ranges. */
 static FlatView *generate_memory_topology(MemoryRegion *mr)
 {
+    int i;
     FlatView *view;
 
     view = flatview_new(mr);
@@ -752,6 +753,14 @@ static FlatView *generate_memory_topology(MemoryRegion *mr)
     }
     flatview_simplify(view);
 
+    view->dispatch = address_space_dispatch_new(view);
+    for (i = 0; i < view->nr; i++) {
+        MemoryRegionSection mrs =
+            section_from_flat_range(&view->ranges[i], view);
+        flatview_add_to_dispatch(view, &mrs);
+    }
+    address_space_dispatch_compact(view->dispatch);
+
     return view;
 }
 
@@ -925,15 +934,6 @@ static void address_space_update_topology(AddressSpace *as)
     FlatView *old_view = address_space_get_flatview(as);
     MemoryRegion *physmr = memory_region_get_flatview_root(old_view->root);
     FlatView *new_view = generate_memory_topology(physmr);
-    int i;
-
-    new_view->dispatch = address_space_dispatch_new(new_view);
-    for (i = 0; i < new_view->nr; i++) {
-        MemoryRegionSection mrs =
-            section_from_flat_range(&new_view->ranges[i], new_view);
-        flatview_add_to_dispatch(new_view, &mrs);
-    }
-    address_space_dispatch_compact(new_view->dispatch);
 
     if (!QTAILQ_EMPTY(&as->listeners)) {
         address_space_update_topology_pass(as, old_view, new_view, false);
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 17/55] memory: Move address_space_update_ioeventfds
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (15 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 16/55] memory: Alloc dispatch tree where topology is generared Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 18/55] memory: Share FlatView's and dispatch trees between address spaces Michael Roth
                   ` (37 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Alexey Kardashevskiy, Paolo Bonzini

From: Alexey Kardashevskiy <aik@ozlabs.ru>

So it is called (twice) from the same function. This is to make the next
patches a bit simpler.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Message-Id: <20170921085110.25598-12-aik@ozlabs.ru>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 02218487649558ed66c3689d4cc55250a42601d8)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 memory.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/memory.c b/memory.c
index 8034520148..1f58d29755 100644
--- a/memory.c
+++ b/memory.c
@@ -951,8 +951,6 @@ static void address_space_update_topology(AddressSpace *as)
      * counting is necessary.
      */
     flatview_unref(old_view);
-
-    address_space_update_ioeventfds(as);
 }
 
 void memory_region_transaction_begin(void)
@@ -975,6 +973,7 @@ void memory_region_transaction_commit(void)
 
             QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
                 address_space_update_topology(as);
+                address_space_update_ioeventfds(as);
             }
             memory_region_update_pending = false;
             MEMORY_LISTENER_CALL_GLOBAL(commit, Forward);
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 18/55] memory: Share FlatView's and dispatch trees between address spaces
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (16 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 17/55] memory: Move address_space_update_ioeventfds Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 19/55] memory: Do not allocate FlatView in address_space_init Michael Roth
                   ` (36 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Alexey Kardashevskiy, Paolo Bonzini

From: Alexey Kardashevskiy <aik@ozlabs.ru>

This allows sharing flat views between address spaces (AS) when
the same root memory region is used when creating a new address space.
This is done by walking through all ASes and caching one FlatView per
a physical root MR (i.e. not aliased).

This removes search for duplicates from address_space_init_shareable() as
FlatViews are shared elsewhere and keeping as::ref_count correct seems
an unnecessary and useless complication.

This should cause no change and memory use or boot time yet.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Message-Id: <20170921085110.25598-13-aik@ozlabs.ru>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 967dc9b1194a9281124b2e1ce67b6c3359a2138f)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 memory.c | 56 +++++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 45 insertions(+), 11 deletions(-)

diff --git a/memory.c b/memory.c
index 1f58d29755..f0c864206a 100644
--- a/memory.c
+++ b/memory.c
@@ -47,6 +47,8 @@ static QTAILQ_HEAD(memory_listeners, MemoryListener) memory_listeners
 static QTAILQ_HEAD(, AddressSpace) address_spaces
     = QTAILQ_HEAD_INITIALIZER(address_spaces);
 
+static GHashTable *flat_views;
+
 typedef struct AddrRange AddrRange;
 
 /*
@@ -760,6 +762,7 @@ static FlatView *generate_memory_topology(MemoryRegion *mr)
         flatview_add_to_dispatch(view, &mrs);
     }
     address_space_dispatch_compact(view->dispatch);
+    g_hash_table_replace(flat_views, mr, view);
 
     return view;
 }
@@ -929,11 +932,47 @@ static void address_space_update_topology_pass(AddressSpace *as,
     }
 }
 
-static void address_space_update_topology(AddressSpace *as)
+static void flatviews_init(void)
+{
+    if (flat_views) {
+        return;
+    }
+
+    flat_views = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL,
+                                       (GDestroyNotify) flatview_unref);
+}
+
+static void flatviews_reset(void)
+{
+    AddressSpace *as;
+
+    if (flat_views) {
+        g_hash_table_unref(flat_views);
+        flat_views = NULL;
+    }
+    flatviews_init();
+
+    /* Render unique FVs */
+    QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
+        MemoryRegion *physmr = memory_region_get_flatview_root(as->root);
+
+        if (g_hash_table_lookup(flat_views, physmr)) {
+            continue;
+        }
+
+        generate_memory_topology(physmr);
+    }
+}
+
+static void address_space_set_flatview(AddressSpace *as)
 {
     FlatView *old_view = address_space_get_flatview(as);
-    MemoryRegion *physmr = memory_region_get_flatview_root(old_view->root);
-    FlatView *new_view = generate_memory_topology(physmr);
+    MemoryRegion *physmr = memory_region_get_flatview_root(as->root);
+    FlatView *new_view = g_hash_table_lookup(flat_views, physmr);
+
+    assert(new_view);
+
+    flatview_ref(new_view);
 
     if (!QTAILQ_EMPTY(&as->listeners)) {
         address_space_update_topology_pass(as, old_view, new_view, false);
@@ -969,10 +1008,12 @@ void memory_region_transaction_commit(void)
     --memory_region_transaction_depth;
     if (!memory_region_transaction_depth) {
         if (memory_region_update_pending) {
+            flatviews_reset();
+
             MEMORY_LISTENER_CALL_GLOBAL(begin, Forward);
 
             QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
-                address_space_update_topology(as);
+                address_space_set_flatview(as);
                 address_space_update_ioeventfds(as);
             }
             memory_region_update_pending = false;
@@ -2695,13 +2736,6 @@ AddressSpace *address_space_init_shareable(MemoryRegion *root, const char *name)
 {
     AddressSpace *as;
 
-    QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
-        if (root == as->root && as->malloced) {
-            as->ref_count++;
-            return as;
-        }
-    }
-
     as = g_malloc0(sizeof *as);
     address_space_init(as, root, name);
     as->malloced = true;
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 19/55] memory: Do not allocate FlatView in address_space_init
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (17 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 18/55] memory: Share FlatView's and dispatch trees between address spaces Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 20/55] memory: Get rid of address_space_init_shareable Michael Roth
                   ` (35 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Alexey Kardashevskiy, Paolo Bonzini

From: Alexey Kardashevskiy <aik@ozlabs.ru>

This creates a new AS object without any FlatView as
memory_region_transaction_commit() may want to reuse the empty FV.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Message-Id: <20170921085110.25598-14-aik@ozlabs.ru>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 67ace39b253ed5ae465275bc870f7e495547658b)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 memory.c | 29 +++++++++++++++++++++++------
 1 file changed, 23 insertions(+), 6 deletions(-)

diff --git a/memory.c b/memory.c
index f0c864206a..6914d87d0d 100644
--- a/memory.c
+++ b/memory.c
@@ -966,22 +966,37 @@ static void flatviews_reset(void)
 
 static void address_space_set_flatview(AddressSpace *as)
 {
-    FlatView *old_view = address_space_get_flatview(as);
+    FlatView *old_view = address_space_to_flatview(as);
     MemoryRegion *physmr = memory_region_get_flatview_root(as->root);
     FlatView *new_view = g_hash_table_lookup(flat_views, physmr);
 
     assert(new_view);
 
+    if (old_view == new_view) {
+        return;
+    }
+
+    if (old_view) {
+        flatview_ref(old_view);
+    }
+
     flatview_ref(new_view);
 
     if (!QTAILQ_EMPTY(&as->listeners)) {
-        address_space_update_topology_pass(as, old_view, new_view, false);
-        address_space_update_topology_pass(as, old_view, new_view, true);
+        FlatView tmpview = { .nr = 0 }, *old_view2 = old_view;
+
+        if (!old_view2) {
+            old_view2 = &tmpview;
+        }
+        address_space_update_topology_pass(as, old_view2, new_view, false);
+        address_space_update_topology_pass(as, old_view2, new_view, true);
     }
 
     /* Writes are protected by the BQL.  */
     atomic_rcu_set(&as->current_map, new_view);
-    flatview_unref(old_view);
+    if (old_view) {
+        flatview_unref(old_view);
+    }
 
     /* Note that all the old MemoryRegions are still alive up to this
      * point.  This relieves most MemoryListeners from the need to
@@ -989,7 +1004,9 @@ static void address_space_set_flatview(AddressSpace *as)
      * outside the iothread mutex, in which case precise reference
      * counting is necessary.
      */
-    flatview_unref(old_view);
+    if (old_view) {
+        flatview_unref(old_view);
+    }
 }
 
 void memory_region_transaction_begin(void)
@@ -2707,7 +2724,7 @@ void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name)
     as->ref_count = 1;
     as->root = root;
     as->malloced = false;
-    as->current_map = flatview_new(root);
+    as->current_map = NULL;
     as->ioeventfd_nb = 0;
     as->ioeventfds = NULL;
     QTAILQ_INIT(&as->listeners);
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 20/55] memory: Get rid of address_space_init_shareable
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (18 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 19/55] memory: Do not allocate FlatView in address_space_init Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 21/55] memory: Create FlatView directly Michael Roth
                   ` (34 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Alexey Kardashevskiy, Paolo Bonzini

From: Alexey Kardashevskiy <aik@ozlabs.ru>

Since FlatViews are shared now and ASes not, this gets rid of
address_space_init_shareable().

This should cause no behavioural change.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Message-Id: <20170921085110.25598-17-aik@ozlabs.ru>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit b516572f31c0ea0937cd9d11d9bd72dd83809886)
 Conflicts:
	target/arm/cpu.c
* drop context deps on 1d2091bc and 1e577cc7
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 cpus.c                  |  5 +++--
 hw/arm/armv7m.c         |  9 ++++-----
 include/exec/memory.h   | 19 -------------------
 include/hw/arm/armv7m.h |  2 +-
 memory.c                | 21 ---------------------
 target/arm/cpu.c        | 15 ++++++++-------
 target/i386/cpu.c       |  5 +++--
 7 files changed, 19 insertions(+), 57 deletions(-)

diff --git a/cpus.c b/cpus.c
index 9bed61eefc..c9a624003a 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1764,8 +1764,9 @@ void qemu_init_vcpu(CPUState *cpu)
         /* If the target cpu hasn't set up any address spaces itself,
          * give it the default one.
          */
-        AddressSpace *as = address_space_init_shareable(cpu->memory,
-                                                        "cpu-memory");
+        AddressSpace *as = g_new0(AddressSpace, 1);
+
+        address_space_init(as, cpu->memory, "cpu-memory");
         cpu->num_ases = 1;
         cpu_address_space_init(cpu, as, 0);
     }
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
index c8a11f2b53..475a88fc56 100644
--- a/hw/arm/armv7m.c
+++ b/hw/arm/armv7m.c
@@ -41,7 +41,7 @@ static MemTxResult bitband_read(void *opaque, hwaddr offset,
 
     /* Find address in underlying memory and round down to multiple of size */
     addr = bitband_addr(s, offset) & (-size);
-    res = address_space_read(s->source_as, addr, attrs, buf, size);
+    res = address_space_read(&s->source_as, addr, attrs, buf, size);
     if (res) {
         return res;
     }
@@ -66,7 +66,7 @@ static MemTxResult bitband_write(void *opaque, hwaddr offset, uint64_t value,
 
     /* Find address in underlying memory and round down to multiple of size */
     addr = bitband_addr(s, offset) & (-size);
-    res = address_space_read(s->source_as, addr, attrs, buf, size);
+    res = address_space_read(&s->source_as, addr, attrs, buf, size);
     if (res) {
         return res;
     }
@@ -79,7 +79,7 @@ static MemTxResult bitband_write(void *opaque, hwaddr offset, uint64_t value,
     } else {
         buf[bitpos >> 3] &= ~bit;
     }
-    return address_space_write(s->source_as, addr, attrs, buf, size);
+    return address_space_write(&s->source_as, addr, attrs, buf, size);
 }
 
 static const MemoryRegionOps bitband_ops = {
@@ -117,8 +117,7 @@ static void bitband_realize(DeviceState *dev, Error **errp)
         return;
     }
 
-    s->source_as = address_space_init_shareable(s->source_memory,
-                                                "bitband-source");
+    address_space_init(&s->source_as, s->source_memory, "bitband-source");
 }
 
 /* Board init.  */
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 6715551fc6..631daf0cce 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -319,8 +319,6 @@ struct AddressSpace {
     struct rcu_head rcu;
     char *name;
     MemoryRegion *root;
-    int ref_count;
-    bool malloced;
 
     /* Accessed via RCU.  */
     struct FlatView *current_map;
@@ -1595,23 +1593,6 @@ MemTxResult memory_region_dispatch_write(MemoryRegion *mr,
 void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name);
 
 /**
- * address_space_init_shareable: return an address space for a memory region,
- *                               creating it if it does not already exist
- *
- * @root: a #MemoryRegion that routes addresses for the address space
- * @name: an address space name.  The name is only used for debugging
- *        output.
- *
- * This function will return a pointer to an existing AddressSpace
- * which was initialized with the specified MemoryRegion, or it will
- * create and initialize one if it does not already exist. The ASes
- * are reference-counted, so the memory will be freed automatically
- * when the AddressSpace is destroyed via address_space_destroy.
- */
-AddressSpace *address_space_init_shareable(MemoryRegion *root,
-                                           const char *name);
-
-/**
  * address_space_destroy: destroy an address space
  *
  * Releases all resources associated with an address space.  After an address space
diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
index a9b3f2ab35..dba77dfa39 100644
--- a/include/hw/arm/armv7m.h
+++ b/include/hw/arm/armv7m.h
@@ -21,7 +21,7 @@ typedef struct {
     SysBusDevice parent_obj;
     /*< public >*/
 
-    AddressSpace *source_as;
+    AddressSpace source_as;
     MemoryRegion iomem;
     uint32_t base;
     MemoryRegion *source_memory;
diff --git a/memory.c b/memory.c
index 6914d87d0d..2e0def18ee 100644
--- a/memory.c
+++ b/memory.c
@@ -2721,9 +2721,7 @@ void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name)
 {
     memory_region_ref(root);
     memory_region_transaction_begin();
-    as->ref_count = 1;
     as->root = root;
-    as->malloced = false;
     as->current_map = NULL;
     as->ioeventfd_nb = 0;
     as->ioeventfds = NULL;
@@ -2736,37 +2734,18 @@ void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name)
 
 static void do_address_space_destroy(AddressSpace *as)
 {
-    bool do_free = as->malloced;
-
     assert(QTAILQ_EMPTY(&as->listeners));
 
     flatview_unref(as->current_map);
     g_free(as->name);
     g_free(as->ioeventfds);
     memory_region_unref(as->root);
-    if (do_free) {
-        g_free(as);
-    }
-}
-
-AddressSpace *address_space_init_shareable(MemoryRegion *root, const char *name)
-{
-    AddressSpace *as;
-
-    as = g_malloc0(sizeof *as);
-    address_space_init(as, root, name);
-    as->malloced = true;
-    return as;
 }
 
 void address_space_destroy(AddressSpace *as)
 {
     MemoryRegion *root = as->root;
 
-    as->ref_count--;
-    if (as->ref_count) {
-        return;
-    }
     /* Flush out anything from MemoryListeners listening in on this */
     memory_region_transaction_begin();
     as->root = NULL;
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 05c038bf17..24ef71ad8b 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -650,6 +650,9 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
     CPUARMState *env = &cpu->env;
     int pagebits;
     Error *local_err = NULL;
+#ifndef CONFIG_USER_ONLY
+    AddressSpace *as;
+#endif
 
     cpu_exec_realizefn(cs, &local_err);
     if (local_err != NULL) {
@@ -835,19 +838,17 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
     }
 
     if (cpu->has_el3) {
-        AddressSpace *as;
+        as = g_new0(AddressSpace, 1);
 
         if (!cpu->secure_memory) {
             cpu->secure_memory = cs->memory;
         }
-        as = address_space_init_shareable(cpu->secure_memory,
-                                          "cpu-secure-memory");
+        address_space_init(as, cpu->secure_memory, "cpu-secure-memory");
         cpu_address_space_init(cs, as, ARMASIdx_S);
     }
-    cpu_address_space_init(cs,
-                           address_space_init_shareable(cs->memory,
-                                                        "cpu-memory"),
-                           ARMASIdx_NS);
+    as = g_new0(AddressSpace, 1);
+    address_space_init(as, cs->memory, "cpu-memory");
+    cpu_address_space_init(cs, as, ARMASIdx_NS);
 #endif
 
     qemu_init_vcpu(cs);
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index ddc45abd70..df73958b82 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -3702,10 +3702,11 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
 
 #ifndef CONFIG_USER_ONLY
     if (tcg_enabled()) {
-        AddressSpace *as_normal = address_space_init_shareable(cs->memory,
-                                                               "cpu-memory");
+        AddressSpace *as_normal = g_new0(AddressSpace, 1);
         AddressSpace *as_smm = g_new(AddressSpace, 1);
 
+        address_space_init(as_normal, cs->memory, "cpu-memory");
+
         cpu->cpu_as_mem = g_new(MemoryRegion, 1);
         cpu->cpu_as_root = g_new(MemoryRegion, 1);
 
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 21/55] memory: Create FlatView directly
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (19 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 20/55] memory: Get rid of address_space_init_shareable Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 22/55] memory: trace FlatView creation and destruction Michael Roth
                   ` (33 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Alexey Kardashevskiy, Paolo Bonzini

From: Alexey Kardashevskiy <aik@ozlabs.ru>

This avoids usual memory_region_transaction_commit() which rebuilds
all FVs.

On POWER8 with 255 CPUs, 255 virtio-net, 40 PCI bridges guest this brings
down the boot time from 25s to 20s and reduces the amount of temporary FVs
allocated during machine constructon (~800000 -> ~640000) and amount of
temporary dispatch trees (~370000 -> ~300000), the total memory footprint
goes down (18G -> 17G).

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Message-Id: <20170921085110.25598-18-aik@ozlabs.ru>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 202fc01b05572ecb258fdf4c5bd56cf6de8140c7)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 memory.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/memory.c b/memory.c
index 2e0def18ee..c1a64a9ca2 100644
--- a/memory.c
+++ b/memory.c
@@ -1009,6 +1009,17 @@ static void address_space_set_flatview(AddressSpace *as)
     }
 }
 
+static void address_space_update_topology(AddressSpace *as)
+{
+    MemoryRegion *physmr = memory_region_get_flatview_root(as->root);
+
+    flatviews_init();
+    if (!g_hash_table_lookup(flat_views, physmr)) {
+        generate_memory_topology(physmr);
+    }
+    address_space_set_flatview(as);
+}
+
 void memory_region_transaction_begin(void)
 {
     qemu_flush_coalesced_mmio_buffer();
@@ -2720,7 +2731,6 @@ void memory_region_invalidate_mmio_ptr(MemoryRegion *mr, hwaddr offset,
 void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name)
 {
     memory_region_ref(root);
-    memory_region_transaction_begin();
     as->root = root;
     as->current_map = NULL;
     as->ioeventfd_nb = 0;
@@ -2728,8 +2738,8 @@ void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name)
     QTAILQ_INIT(&as->listeners);
     QTAILQ_INSERT_TAIL(&address_spaces, as, address_spaces_link);
     as->name = g_strdup(name ? name : "anonymous");
-    memory_region_update_pending |= root->enabled;
-    memory_region_transaction_commit();
+    address_space_update_topology(as);
+    address_space_update_ioeventfds(as);
 }
 
 static void do_address_space_destroy(AddressSpace *as)
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 22/55] memory: trace FlatView creation and destruction
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (20 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 21/55] memory: Create FlatView directly Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 23/55] memory: seek FlatView sharing candidates among children subregions Michael Roth
                   ` (32 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Paolo Bonzini

From: Paolo Bonzini <pbonzini@redhat.com>

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 02d9651d6a46479e9d70b72dca34e43605d06cda)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 include/exec/memory.h   | 1 -
 include/qemu/typedefs.h | 1 +
 memory.c                | 3 +++
 trace-events            | 3 +++
 4 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/include/exec/memory.h b/include/exec/memory.h
index 631daf0cce..234c71d975 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -48,7 +48,6 @@
 
 typedef struct MemoryRegionOps MemoryRegionOps;
 typedef struct MemoryRegionMmio MemoryRegionMmio;
-typedef struct FlatView FlatView;
 
 struct MemoryRegionMmio {
     CPUReadMemoryFunc *read[3];
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
index 39bc8351a3..d44dfc75ec 100644
--- a/include/qemu/typedefs.h
+++ b/include/qemu/typedefs.h
@@ -30,6 +30,7 @@ typedef struct DisplaySurface DisplaySurface;
 typedef struct DriveInfo DriveInfo;
 typedef struct Error Error;
 typedef struct EventNotifier EventNotifier;
+typedef struct FlatView FlatView;
 typedef struct FWCfgEntry FWCfgEntry;
 typedef struct FWCfgIoState FWCfgIoState;
 typedef struct FWCfgMemState FWCfgMemState;
diff --git a/memory.c b/memory.c
index c1a64a9ca2..774a17f60a 100644
--- a/memory.c
+++ b/memory.c
@@ -270,6 +270,7 @@ static FlatView *flatview_new(MemoryRegion *mr_root)
     view->ref = 1;
     view->root = mr_root;
     memory_region_ref(mr_root);
+    trace_flatview_new(view, mr_root);
 
     return view;
 }
@@ -295,6 +296,7 @@ static void flatview_destroy(FlatView *view)
 {
     int i;
 
+    trace_flatview_destroy(view, view->root);
     if (view->dispatch) {
         address_space_dispatch_free(view->dispatch);
     }
@@ -314,6 +316,7 @@ static bool flatview_ref(FlatView *view)
 static void flatview_unref(FlatView *view)
 {
     if (atomic_fetch_dec(&view->ref) == 1) {
+        trace_flatview_destroy_rcu(view, view->root);
         call_rcu(view, flatview_destroy, rcu);
     }
 }
diff --git a/trace-events b/trace-events
index 1f50f56d9d..1d2eb5d3e4 100644
--- a/trace-events
+++ b/trace-events
@@ -64,6 +64,9 @@ memory_region_tb_read(int cpu_index, uint64_t addr, uint64_t value, unsigned siz
 memory_region_tb_write(int cpu_index, uint64_t addr, uint64_t value, unsigned size) "cpu %d addr 0x%"PRIx64" value 0x%"PRIx64" size %u"
 memory_region_ram_device_read(int cpu_index, void *mr, uint64_t addr, uint64_t value, unsigned size) "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u"
 memory_region_ram_device_write(int cpu_index, void *mr, uint64_t addr, uint64_t value, unsigned size) "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u"
+flatview_new(FlatView *view, MemoryRegion *root) "%p (root %p)"
+flatview_destroy(FlatView *view, MemoryRegion *root) "%p (root %p)"
+flatview_destroy_rcu(FlatView *view, MemoryRegion *root) "%p (root %p)"
 
 ### Guest events, keep at bottom
 
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 23/55] memory: seek FlatView sharing candidates among children subregions
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (21 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 22/55] memory: trace FlatView creation and destruction Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 24/55] memory: Share special empty FlatView Michael Roth
                   ` (31 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Paolo Bonzini

From: Paolo Bonzini <pbonzini@redhat.com>

A container can be used instead of an alias to allow switching between
multiple subregions.  In this case we cannot directly share the
subregions (since they only belong to a single parent), but if the
subregions are aliases we can in turn walk those.

This is not enough to remove all source of quadratic FlatView creation,
but it enables sharing of the PCI bus master FlatViews (and their
AddressSpaceDispatch structures) across all PCI devices.  For 112
virtio-net-pci devices, boot time is reduced from 25 to 10 seconds and
memory consumption from 1.4 to 1 G.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit e673ba9af9bf8fd8e0f44025ac738b8285b3ed27)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 memory.c | 40 ++++++++++++++++++++++++++++++++++------
 1 file changed, 34 insertions(+), 6 deletions(-)

diff --git a/memory.c b/memory.c
index 774a17f60a..231bb78fa7 100644
--- a/memory.c
+++ b/memory.c
@@ -733,12 +733,40 @@ static void render_memory_region(FlatView *view,
 
 static MemoryRegion *memory_region_get_flatview_root(MemoryRegion *mr)
 {
-    while (mr->alias && !mr->alias_offset &&
-           int128_ge(mr->size, mr->alias->size)) {
-        /* The alias is included in its entirety.  Use it as
-         * the "real" root, so that we can share more FlatViews.
-         */
-        mr = mr->alias;
+    while (mr->enabled) {
+        if (mr->alias) {
+            if (!mr->alias_offset && int128_ge(mr->size, mr->alias->size)) {
+                /* The alias is included in its entirety.  Use it as
+                 * the "real" root, so that we can share more FlatViews.
+                 */
+                mr = mr->alias;
+                continue;
+            }
+        } else if (!mr->terminates) {
+            unsigned int found = 0;
+            MemoryRegion *child, *next = NULL;
+            QTAILQ_FOREACH(child, &mr->subregions, subregions_link) {
+                if (child->enabled) {
+                    if (++found > 1) {
+                        next = NULL;
+                        break;
+                    }
+                    if (!child->addr && int128_ge(mr->size, child->size)) {
+                        /* A child is included in its entirety.  If it's the only
+                         * enabled one, use it in the hope of finding an alias down the
+                         * way. This will also let us share FlatViews.
+                         */
+                        next = child;
+                    }
+                }
+            }
+            if (next) {
+                mr = next;
+                continue;
+            }
+        }
+
+        break;
     }
 
     return mr;
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 24/55] memory: Share special empty FlatView
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (22 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 23/55] memory: seek FlatView sharing candidates among children subregions Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 25/55] exec: add page_mask for flatview_do_translate Michael Roth
                   ` (30 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Alexey Kardashevskiy, Paolo Bonzini

From: Alexey Kardashevskiy <aik@ozlabs.ru>

This shares an cached empty FlatView among address spaces. The empty
FV is used every time when a root MR renders into a FV without memory
sections which happens when MR or its children are not enabled or
zero-sized. The empty_view is not NULL to keep the rest of memory
API intact; it also has a dispatch tree for the same reason.

On POWER8 with 255 CPUs, 255 virtio-net, 40 PCI bridges guest this halves
the amount of FlatView's in use (557 -> 260) and dispatch tables
(~800000 -> ~370000).  In an unrelated experiment with 112 non-virtio
devices on x86 ("-M pc"), only 4 FlatViews are alive, and about ~2000
are created at startup.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Message-Id: <20170921085110.25598-16-aik@ozlabs.ru>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 092aa2fc65b7a35121616aad8f39d47b8f921618)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 memory.c | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/memory.c b/memory.c
index 231bb78fa7..d90853855b 100644
--- a/memory.c
+++ b/memory.c
@@ -317,6 +317,7 @@ static void flatview_unref(FlatView *view)
 {
     if (atomic_fetch_dec(&view->ref) == 1) {
         trace_flatview_destroy_rcu(view, view->root);
+        assert(view->root);
         call_rcu(view, flatview_destroy, rcu);
     }
 }
@@ -760,16 +761,19 @@ static MemoryRegion *memory_region_get_flatview_root(MemoryRegion *mr)
                     }
                 }
             }
+            if (found == 0) {
+                return NULL;
+            }
             if (next) {
                 mr = next;
                 continue;
             }
         }
 
-        break;
+        return mr;
     }
 
-    return mr;
+    return NULL;
 }
 
 /* Render a memory topology into a list of disjoint absolute ranges. */
@@ -965,12 +969,22 @@ static void address_space_update_topology_pass(AddressSpace *as,
 
 static void flatviews_init(void)
 {
+    static FlatView *empty_view;
+
     if (flat_views) {
         return;
     }
 
     flat_views = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL,
                                        (GDestroyNotify) flatview_unref);
+    if (!empty_view) {
+        empty_view = generate_memory_topology(NULL);
+        /* We keep it alive forever in the global variable.  */
+        flatview_ref(empty_view);
+    } else {
+        g_hash_table_replace(flat_views, NULL, empty_view);
+        flatview_ref(empty_view);
+    }
 }
 
 static void flatviews_reset(void)
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 25/55] exec: add page_mask for flatview_do_translate
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (23 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 24/55] memory: Share special empty FlatView Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 26/55] exec: simplify address_space_get_iotlb_entry Michael Roth
                   ` (29 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Peter Xu, Maxime Coquelin, Paolo Bonzini

From: Peter Xu <peterx@redhat.com>

The function is originally used for flatview_space_translate() and what
we care about most is (xlat, plen) range. However for iotlb requests, we
don't really care about "plen", but the size of the page that "xlat" is
located on. While, plen cannot really contain this information.

A simple example to show why "plen" is not good for IOTLB translations:

E.g., for huge pages, it is possible that guest mapped 1G huge page on
device side that used this GPA range:

  0x100000000 - 0x13fffffff

Then let's say we want to translate one IOVA that finally mapped to GPA
0x13ffffe00 (which is located on this 1G huge page). Then here we'll
get:

  (xlat, plen) = (0x13fffe00, 0x200)

So the IOTLB would be only covering a very small range since from
"plen" (which is 0x200 bytes) we cannot tell the size of the page.

Actually we can really know that this is a huge page - we just throw the
information away in flatview_do_translate().

This patch introduced "page_mask" optional parameter to capture that
page mask info. Also, I made "plen" an optional parameter as well, with
some comments for the whole function.

No functional change yet.

Signed-off-by: Peter Xu <peterx@redhat.com>
Signed-off-by: Maxime Coquelin <maxime.coquelin@redhat.com>
Message-Id: <20171010094247.10173-2-maxime.coquelin@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit d5e5fafd11be4458443c43f19c1ebdd24d99a751)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 exec.c | 51 +++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 45 insertions(+), 6 deletions(-)

diff --git a/exec.c b/exec.c
index b1f29d35d8..2fd65dc3f2 100644
--- a/exec.c
+++ b/exec.c
@@ -468,11 +468,29 @@ address_space_translate_internal(AddressSpaceDispatch *d, hwaddr addr, hwaddr *x
     return section;
 }
 
-/* Called from RCU critical section */
+/**
+ * flatview_do_translate - translate an address in FlatView
+ *
+ * @fv: the flat view that we want to translate on
+ * @addr: the address to be translated in above address space
+ * @xlat: the translated address offset within memory region. It
+ *        cannot be @NULL.
+ * @plen_out: valid read/write length of the translated address. It
+ *            can be @NULL when we don't care about it.
+ * @page_mask_out: page mask for the translated address. This
+ *            should only be meaningful for IOMMU translated
+ *            addresses, since there may be huge pages that this bit
+ *            would tell. It can be @NULL if we don't care about it.
+ * @is_write: whether the translation operation is for write
+ * @is_mmio: whether this can be MMIO, set true if it can
+ *
+ * This function is called from RCU critical section
+ */
 static MemoryRegionSection flatview_do_translate(FlatView *fv,
                                                  hwaddr addr,
                                                  hwaddr *xlat,
-                                                 hwaddr *plen,
+                                                 hwaddr *plen_out,
+                                                 hwaddr *page_mask_out,
                                                  bool is_write,
                                                  bool is_mmio,
                                                  AddressSpace **target_as)
@@ -481,11 +499,17 @@ static MemoryRegionSection flatview_do_translate(FlatView *fv,
     MemoryRegionSection *section;
     IOMMUMemoryRegion *iommu_mr;
     IOMMUMemoryRegionClass *imrc;
+    hwaddr page_mask = (hwaddr)(-1);
+    hwaddr plen = (hwaddr)(-1);
+
+    if (plen_out) {
+        plen = *plen_out;
+    }
 
     for (;;) {
         section = address_space_translate_internal(
                 flatview_to_dispatch(fv), addr, &addr,
-                plen, is_mmio);
+                &plen, is_mmio);
 
         iommu_mr = memory_region_get_iommu(section->mr);
         if (!iommu_mr) {
@@ -497,7 +521,8 @@ static MemoryRegionSection flatview_do_translate(FlatView *fv,
                                 IOMMU_WO : IOMMU_RO);
         addr = ((iotlb.translated_addr & ~iotlb.addr_mask)
                 | (addr & iotlb.addr_mask));
-        *plen = MIN(*plen, (addr | iotlb.addr_mask) - addr + 1);
+        page_mask &= iotlb.addr_mask;
+        plen = MIN(plen, (addr | iotlb.addr_mask) - addr + 1);
         if (!(iotlb.perm & (1 << is_write))) {
             goto translate_fail;
         }
@@ -508,6 +533,19 @@ static MemoryRegionSection flatview_do_translate(FlatView *fv,
 
     *xlat = addr;
 
+    if (page_mask == (hwaddr)(-1)) {
+        /* Not behind an IOMMU, use default page size. */
+        page_mask = ~TARGET_PAGE_MASK;
+    }
+
+    if (page_mask_out) {
+        *page_mask_out = page_mask;
+    }
+
+    if (plen_out) {
+        *plen_out = plen;
+    }
+
     return *section;
 
 translate_fail:
@@ -526,7 +564,7 @@ IOMMUTLBEntry address_space_get_iotlb_entry(AddressSpace *as, hwaddr addr,
 
     /* This can never be MMIO. */
     section = flatview_do_translate(address_space_to_flatview(as), addr,
-                                    &xlat, &plen, is_write, false, &as);
+                                    &xlat, &plen, NULL, is_write, false, &as);
 
     /* Illegal translation */
     if (section.mr == &io_mem_unassigned) {
@@ -570,7 +608,8 @@ MemoryRegion *flatview_translate(FlatView *fv, hwaddr addr, hwaddr *xlat,
     AddressSpace *as = NULL;
 
     /* This can be MMIO, so setup MMIO bit. */
-    section = flatview_do_translate(fv, addr, xlat, plen, is_write, true, &as);
+    section = flatview_do_translate(fv, addr, xlat, plen, NULL,
+                                    is_write, true, &as);
     mr = section.mr;
 
     if (xen_enabled() && memory_access_is_direct(mr, is_write)) {
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 26/55] exec: simplify address_space_get_iotlb_entry
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (24 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 25/55] exec: add page_mask for flatview_do_translate Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 27/55] memory: fix off-by-one error in memory_region_notify_one() Michael Roth
                   ` (28 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Peter Xu, Maxime Coquelin, Paolo Bonzini

From: Peter Xu <peterx@redhat.com>

This patch let address_space_get_iotlb_entry() to use the newly
introduced page_mask parameter in flatview_do_translate(). Then we
will be sure the IOTLB can be aligned to page mask, also we should
nicely support huge pages now when introducing a764040.

Fixes: a764040 ("exec: abstract address_space_do_translate()")
Signed-off-by: Peter Xu <peterx@redhat.com>
Signed-off-by: Maxime Coquelin <maxime.coquelin@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20171010094247.10173-3-maxime.coquelin@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 076a93d7972c9c1e3839d2f65edc32568a2cce93)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 exec.c | 31 ++++++++++---------------------
 1 file changed, 10 insertions(+), 21 deletions(-)

diff --git a/exec.c b/exec.c
index 2fd65dc3f2..9a7600eb17 100644
--- a/exec.c
+++ b/exec.c
@@ -557,14 +557,14 @@ IOMMUTLBEntry address_space_get_iotlb_entry(AddressSpace *as, hwaddr addr,
                                             bool is_write)
 {
     MemoryRegionSection section;
-    hwaddr xlat, plen;
+    hwaddr xlat, page_mask;
 
-    /* Try to get maximum page mask during translation. */
-    plen = (hwaddr)-1;
-
-    /* This can never be MMIO. */
-    section = flatview_do_translate(address_space_to_flatview(as), addr,
-                                    &xlat, &plen, NULL, is_write, false, &as);
+    /*
+     * This can never be MMIO, and we don't really care about plen,
+     * but page mask.
+     */
+    section = flatview_do_translate(address_space_to_flatview(as), addr, &xlat,
+                                    NULL, &page_mask, is_write, false, &as);
 
     /* Illegal translation */
     if (section.mr == &io_mem_unassigned) {
@@ -575,22 +575,11 @@ IOMMUTLBEntry address_space_get_iotlb_entry(AddressSpace *as, hwaddr addr,
     xlat += section.offset_within_address_space -
         section.offset_within_region;
 
-    if (plen == (hwaddr)-1) {
-        /*
-         * We use default page size here. Logically it only happens
-         * for identity mappings.
-         */
-        plen = TARGET_PAGE_SIZE;
-    }
-
-    /* Convert to address mask */
-    plen -= 1;
-
     return (IOMMUTLBEntry) {
         .target_as = as,
-        .iova = addr & ~plen,
-        .translated_addr = xlat & ~plen,
-        .addr_mask = plen,
+        .iova = addr & ~page_mask,
+        .translated_addr = xlat & ~page_mask,
+        .addr_mask = page_mask,
         /* IOTLBs are for DMAs, and DMA only allows on RAMs. */
         .perm = IOMMU_RW,
     };
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 27/55] memory: fix off-by-one error in memory_region_notify_one()
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (25 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 26/55] exec: simplify address_space_get_iotlb_entry Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 28/55] hw/sd: fix out-of-bounds check for multi block reads Michael Roth
                   ` (27 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Maxime Coquelin, Peter Xu, Paolo Bonzini

From: Maxime Coquelin <maxime.coquelin@redhat.com>

This patch fixes an off-by-one error that could lead to the
notifyee to receive notifications for ranges it is not
registered to.

The bug has been spotted by code review.

Fixes: bd2bfa4c52e5 ("memory: introduce memory_region_notify_one()")
Cc: qemu-stable@nongnu.org
Cc: Peter Xu <peterx@redhat.com>
Signed-off-by: Maxime Coquelin <maxime.coquelin@redhat.com>
Message-Id: <20171010094247.10173-4-maxime.coquelin@redhat.com>
Reviewed-by: Peter Xu <peterx@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit b021d1c04452276f4926eed2d104ccbd1037a6e1)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 memory.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/memory.c b/memory.c
index d90853855b..d05a80aba5 100644
--- a/memory.c
+++ b/memory.c
@@ -1891,7 +1891,7 @@ void memory_region_notify_one(IOMMUNotifier *notifier,
      * Skip the notification if the notification does not overlap
      * with registered range.
      */
-    if (notifier->start > entry->iova + entry->addr_mask + 1 ||
+    if (notifier->start > entry->iova + entry->addr_mask ||
         notifier->end < entry->iova) {
         return;
     }
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 28/55] hw/sd: fix out-of-bounds check for multi block reads
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (26 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 27/55] memory: fix off-by-one error in memory_region_notify_one() Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 29/55] qcow2: Fix unaligned preallocated truncation Michael Roth
                   ` (26 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Michael Olbrich, Peter Maydell

From: Michael Olbrich <m.olbrich@pengutronix.de>

The current code checks if the next block exceeds the size of the card.
This generates an error while reading the last block of the card.
Do the out-of-bounds check when starting to read a new block to fix this.

This issue became visible with increased error checking in Linux 4.13.

Cc: qemu-stable@nongnu.org
Signed-off-by: Michael Olbrich <m.olbrich@pengutronix.de>
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
Message-id: 20170916091611.10241-1-m.olbrich@pengutronix.de
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit 8573378e62d19e25a2434e23462ec99ef4d065ac)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 hw/sd/sd.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index ba47bff4db..35347a5bbc 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1797,8 +1797,13 @@ uint8_t sd_read_data(SDState *sd)
         break;
 
     case 18:	/* CMD18:  READ_MULTIPLE_BLOCK */
-        if (sd->data_offset == 0)
+        if (sd->data_offset == 0) {
+            if (sd->data_start + io_len > sd->size) {
+                sd->card_status |= ADDRESS_ERROR;
+                return 0x00;
+            }
             BLK_READ_BLOCK(sd->data_start, io_len);
+        }
         ret = sd->data[sd->data_offset ++];
 
         if (sd->data_offset >= io_len) {
@@ -1812,11 +1817,6 @@ uint8_t sd_read_data(SDState *sd)
                     break;
                 }
             }
-
-            if (sd->data_start + io_len > sd->size) {
-                sd->card_status |= ADDRESS_ERROR;
-                break;
-            }
         }
         break;
 
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 29/55] qcow2: Fix unaligned preallocated truncation
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (27 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 28/55] hw/sd: fix out-of-bounds check for multi block reads Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 30/55] qcow2: Always execute preallocate() in a coroutine Michael Roth
                   ` (25 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Max Reitz

From: Max Reitz <mreitz@redhat.com>

A qcow2 image file's length is not required to have a length that is a
multiple of the cluster size.  However, qcow2_refcount_area() expects an
aligned value for its @start_offset parameter, so we need to round
@old_file_size up to the next cluster boundary.

Reported-by: Ping Li <pingl@redhat.com>
Bug: https://bugzilla.redhat.com/show_bug.cgi?id=1414049
Signed-off-by: Max Reitz <mreitz@redhat.com>
Message-id: 20171009215533.12530-2-mreitz@redhat.com
Cc: qemu-stable@nongnu.org
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Jeff Cody <jcody@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Max Reitz <mreitz@redhat.com>
(cherry picked from commit e400ad1e1f0127b4fdabcb1c8de1e99be91788df)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 block/qcow2.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/block/qcow2.c b/block/qcow2.c
index a756bf9541..10e38074ad 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -3161,6 +3161,7 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
                              "Failed to inquire current file length");
             return ret;
         }
+        old_file_size = ROUND_UP(old_file_size, s->cluster_size);
 
         nb_new_data_clusters = DIV_ROUND_UP(offset - old_length,
                                             s->cluster_size);
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 30/55] qcow2: Always execute preallocate() in a coroutine
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (28 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 29/55] qcow2: Fix unaligned preallocated truncation Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 31/55] iotests: Add cluster_size=64k to 125 Michael Roth
                   ` (24 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Max Reitz

From: Max Reitz <mreitz@redhat.com>

Some qcow2 functions (at least perform_cow()) expect s->lock to be
taken.  Therefore, if we want to make use of them, we should execute
preallocate() (as "preallocate_co") in a coroutine so that we can use
the qemu_co_mutex_* functions.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Message-id: 20171009215533.12530-3-mreitz@redhat.com
Cc: qemu-stable@nongnu.org
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Jeff Cody <jcody@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Max Reitz <mreitz@redhat.com>
(cherry picked from commit 572b07bea1d1a0f7726fd95c2613c76002a379bc)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 block/qcow2.c | 41 ++++++++++++++++++++++++++++++++++-------
 1 file changed, 34 insertions(+), 7 deletions(-)

diff --git a/block/qcow2.c b/block/qcow2.c
index 10e38074ad..668665ea8d 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -2476,6 +2476,14 @@ static int qcow2_set_up_encryption(BlockDriverState *bs, const char *encryptfmt,
 }
 
 
+typedef struct PreallocCo {
+    BlockDriverState *bs;
+    uint64_t offset;
+    uint64_t new_length;
+
+    int ret;
+} PreallocCo;
+
 /**
  * Preallocates metadata structures for data clusters between @offset (in the
  * guest disk) and @new_length (which is thus generally the new guest disk
@@ -2483,9 +2491,12 @@ static int qcow2_set_up_encryption(BlockDriverState *bs, const char *encryptfmt,
  *
  * Returns: 0 on success, -errno on failure.
  */
-static int preallocate(BlockDriverState *bs,
-                       uint64_t offset, uint64_t new_length)
+static void coroutine_fn preallocate_co(void *opaque)
 {
+    PreallocCo *params = opaque;
+    BlockDriverState *bs = params->bs;
+    uint64_t offset = params->offset;
+    uint64_t new_length = params->new_length;
     BDRVQcow2State *s = bs->opaque;
     uint64_t bytes;
     uint64_t host_offset = 0;
@@ -2493,9 +2504,7 @@ static int preallocate(BlockDriverState *bs,
     int ret;
     QCowL2Meta *meta;
 
-    if (qemu_in_coroutine()) {
-        qemu_co_mutex_lock(&s->lock);
-    }
+    qemu_co_mutex_lock(&s->lock);
 
     assert(offset <= new_length);
     bytes = new_length - offset;
@@ -2549,10 +2558,28 @@ static int preallocate(BlockDriverState *bs,
     ret = 0;
 
 done:
+    qemu_co_mutex_unlock(&s->lock);
+    params->ret = ret;
+}
+
+static int preallocate(BlockDriverState *bs,
+                       uint64_t offset, uint64_t new_length)
+{
+    PreallocCo params = {
+        .bs         = bs,
+        .offset     = offset,
+        .new_length = new_length,
+        .ret        = -EINPROGRESS,
+    };
+
     if (qemu_in_coroutine()) {
-        qemu_co_mutex_unlock(&s->lock);
+        preallocate_co(&params);
+    } else {
+        Coroutine *co = qemu_coroutine_create(preallocate_co, &params);
+        bdrv_coroutine_enter(bs, co);
+        BDRV_POLL_WHILE(bs, params.ret == -EINPROGRESS);
     }
-    return ret;
+    return params.ret;
 }
 
 /* qcow2_refcount_metadata_size:
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 31/55] iotests: Add cluster_size=64k to 125
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (29 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 30/55] qcow2: Always execute preallocate() in a coroutine Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 32/55] nios2: define tcg_env Michael Roth
                   ` (23 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Max Reitz

From: Max Reitz <mreitz@redhat.com>

Apparently it would be a good idea to test that, too.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Message-id: 20171009215533.12530-4-mreitz@redhat.com
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Jeff Cody <jcody@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Max Reitz <mreitz@redhat.com>
(cherry picked from commit 4c112a397c2f61038914fa315a7896ce6d645d18)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 tests/qemu-iotests/125     |   7 +-
 tests/qemu-iotests/125.out | 480 ++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 437 insertions(+), 50 deletions(-)

diff --git a/tests/qemu-iotests/125 b/tests/qemu-iotests/125
index 9424313e82..c20c71570c 100755
--- a/tests/qemu-iotests/125
+++ b/tests/qemu-iotests/125
@@ -69,13 +69,15 @@ fi
 # in B
 CREATION_SIZE=$((2 * 1024 * 1024 - 48 * 1024))
 
+# 512 is the actual test -- but it's good to test 64k as well, just to be sure.
+for cluster_size in 512 64k; do
 # in kB
 for GROWTH_SIZE in 16 48 80; do
     for create_mode in off metadata falloc full; do
         for growth_mode in off metadata falloc full; do
-            echo "--- growth_size=$GROWTH_SIZE create_mode=$create_mode growth_mode=$growth_mode ---"
+            echo "--- cluster_size=$cluster_size growth_size=$GROWTH_SIZE create_mode=$create_mode growth_mode=$growth_mode ---"
 
-            IMGOPTS="preallocation=$create_mode,cluster_size=512" _make_test_img ${CREATION_SIZE}
+            IMGOPTS="preallocation=$create_mode,cluster_size=$cluster_size" _make_test_img ${CREATION_SIZE}
             $QEMU_IMG resize -f "$IMGFMT" --preallocation=$growth_mode "$TEST_IMG" +${GROWTH_SIZE}K
 
             host_size_0=$(get_image_size_on_host)
@@ -123,6 +125,7 @@ for GROWTH_SIZE in 16 48 80; do
         done
     done
 done
+done
 
 # success, all done
 echo '*** done'
diff --git a/tests/qemu-iotests/125.out b/tests/qemu-iotests/125.out
index 3f4d6e31a6..596905f533 100644
--- a/tests/qemu-iotests/125.out
+++ b/tests/qemu-iotests/125.out
@@ -1,5 +1,5 @@
 QA output created by 125
---- growth_size=16 create_mode=off growth_mode=off ---
+--- cluster_size=512 growth_size=16 create_mode=off growth_mode=off ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -7,7 +7,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 16384/16384 bytes at offset 2048000
 16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=16 create_mode=off growth_mode=metadata ---
+--- cluster_size=512 growth_size=16 create_mode=off growth_mode=metadata ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -15,7 +15,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 16384/16384 bytes at offset 2048000
 16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=16 create_mode=off growth_mode=falloc ---
+--- cluster_size=512 growth_size=16 create_mode=off growth_mode=falloc ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -23,7 +23,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 16384/16384 bytes at offset 2048000
 16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=16 create_mode=off growth_mode=full ---
+--- cluster_size=512 growth_size=16 create_mode=off growth_mode=full ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -31,7 +31,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 16384/16384 bytes at offset 2048000
 16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=16 create_mode=metadata growth_mode=off ---
+--- cluster_size=512 growth_size=16 create_mode=metadata growth_mode=off ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -39,7 +39,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 16384/16384 bytes at offset 2048000
 16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=16 create_mode=metadata growth_mode=metadata ---
+--- cluster_size=512 growth_size=16 create_mode=metadata growth_mode=metadata ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -47,7 +47,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 16384/16384 bytes at offset 2048000
 16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=16 create_mode=metadata growth_mode=falloc ---
+--- cluster_size=512 growth_size=16 create_mode=metadata growth_mode=falloc ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -55,7 +55,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 16384/16384 bytes at offset 2048000
 16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=16 create_mode=metadata growth_mode=full ---
+--- cluster_size=512 growth_size=16 create_mode=metadata growth_mode=full ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -63,7 +63,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 16384/16384 bytes at offset 2048000
 16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=16 create_mode=falloc growth_mode=off ---
+--- cluster_size=512 growth_size=16 create_mode=falloc growth_mode=off ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -71,7 +71,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 16384/16384 bytes at offset 2048000
 16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=16 create_mode=falloc growth_mode=metadata ---
+--- cluster_size=512 growth_size=16 create_mode=falloc growth_mode=metadata ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -79,7 +79,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 16384/16384 bytes at offset 2048000
 16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=16 create_mode=falloc growth_mode=falloc ---
+--- cluster_size=512 growth_size=16 create_mode=falloc growth_mode=falloc ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -87,7 +87,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 16384/16384 bytes at offset 2048000
 16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=16 create_mode=falloc growth_mode=full ---
+--- cluster_size=512 growth_size=16 create_mode=falloc growth_mode=full ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -95,7 +95,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 16384/16384 bytes at offset 2048000
 16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=16 create_mode=full growth_mode=off ---
+--- cluster_size=512 growth_size=16 create_mode=full growth_mode=off ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -103,7 +103,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 16384/16384 bytes at offset 2048000
 16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=16 create_mode=full growth_mode=metadata ---
+--- cluster_size=512 growth_size=16 create_mode=full growth_mode=metadata ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -111,7 +111,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 16384/16384 bytes at offset 2048000
 16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=16 create_mode=full growth_mode=falloc ---
+--- cluster_size=512 growth_size=16 create_mode=full growth_mode=falloc ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -119,7 +119,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 16384/16384 bytes at offset 2048000
 16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=16 create_mode=full growth_mode=full ---
+--- cluster_size=512 growth_size=16 create_mode=full growth_mode=full ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -127,7 +127,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 16384/16384 bytes at offset 2048000
 16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=48 create_mode=off growth_mode=off ---
+--- cluster_size=512 growth_size=48 create_mode=off growth_mode=off ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -135,7 +135,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 49152/49152 bytes at offset 2048000
 48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=48 create_mode=off growth_mode=metadata ---
+--- cluster_size=512 growth_size=48 create_mode=off growth_mode=metadata ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -143,7 +143,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 49152/49152 bytes at offset 2048000
 48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=48 create_mode=off growth_mode=falloc ---
+--- cluster_size=512 growth_size=48 create_mode=off growth_mode=falloc ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -151,7 +151,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 49152/49152 bytes at offset 2048000
 48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=48 create_mode=off growth_mode=full ---
+--- cluster_size=512 growth_size=48 create_mode=off growth_mode=full ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -159,7 +159,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 49152/49152 bytes at offset 2048000
 48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=48 create_mode=metadata growth_mode=off ---
+--- cluster_size=512 growth_size=48 create_mode=metadata growth_mode=off ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -167,7 +167,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 49152/49152 bytes at offset 2048000
 48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=48 create_mode=metadata growth_mode=metadata ---
+--- cluster_size=512 growth_size=48 create_mode=metadata growth_mode=metadata ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -175,7 +175,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 49152/49152 bytes at offset 2048000
 48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=48 create_mode=metadata growth_mode=falloc ---
+--- cluster_size=512 growth_size=48 create_mode=metadata growth_mode=falloc ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -183,7 +183,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 49152/49152 bytes at offset 2048000
 48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=48 create_mode=metadata growth_mode=full ---
+--- cluster_size=512 growth_size=48 create_mode=metadata growth_mode=full ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -191,7 +191,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 49152/49152 bytes at offset 2048000
 48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=48 create_mode=falloc growth_mode=off ---
+--- cluster_size=512 growth_size=48 create_mode=falloc growth_mode=off ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -199,7 +199,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 49152/49152 bytes at offset 2048000
 48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=48 create_mode=falloc growth_mode=metadata ---
+--- cluster_size=512 growth_size=48 create_mode=falloc growth_mode=metadata ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -207,7 +207,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 49152/49152 bytes at offset 2048000
 48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=48 create_mode=falloc growth_mode=falloc ---
+--- cluster_size=512 growth_size=48 create_mode=falloc growth_mode=falloc ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -215,7 +215,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 49152/49152 bytes at offset 2048000
 48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=48 create_mode=falloc growth_mode=full ---
+--- cluster_size=512 growth_size=48 create_mode=falloc growth_mode=full ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -223,7 +223,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 49152/49152 bytes at offset 2048000
 48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=48 create_mode=full growth_mode=off ---
+--- cluster_size=512 growth_size=48 create_mode=full growth_mode=off ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -231,7 +231,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 49152/49152 bytes at offset 2048000
 48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=48 create_mode=full growth_mode=metadata ---
+--- cluster_size=512 growth_size=48 create_mode=full growth_mode=metadata ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -239,7 +239,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 49152/49152 bytes at offset 2048000
 48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=48 create_mode=full growth_mode=falloc ---
+--- cluster_size=512 growth_size=48 create_mode=full growth_mode=falloc ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -247,7 +247,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 49152/49152 bytes at offset 2048000
 48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=48 create_mode=full growth_mode=full ---
+--- cluster_size=512 growth_size=48 create_mode=full growth_mode=full ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -255,7 +255,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 49152/49152 bytes at offset 2048000
 48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=80 create_mode=off growth_mode=off ---
+--- cluster_size=512 growth_size=80 create_mode=off growth_mode=off ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -263,7 +263,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 81920/81920 bytes at offset 2048000
 80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=80 create_mode=off growth_mode=metadata ---
+--- cluster_size=512 growth_size=80 create_mode=off growth_mode=metadata ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -271,7 +271,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 81920/81920 bytes at offset 2048000
 80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=80 create_mode=off growth_mode=falloc ---
+--- cluster_size=512 growth_size=80 create_mode=off growth_mode=falloc ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -279,7 +279,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 81920/81920 bytes at offset 2048000
 80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=80 create_mode=off growth_mode=full ---
+--- cluster_size=512 growth_size=80 create_mode=off growth_mode=full ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -287,7 +287,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 81920/81920 bytes at offset 2048000
 80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=80 create_mode=metadata growth_mode=off ---
+--- cluster_size=512 growth_size=80 create_mode=metadata growth_mode=off ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -295,7 +295,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 81920/81920 bytes at offset 2048000
 80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=80 create_mode=metadata growth_mode=metadata ---
+--- cluster_size=512 growth_size=80 create_mode=metadata growth_mode=metadata ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -303,7 +303,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 81920/81920 bytes at offset 2048000
 80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=80 create_mode=metadata growth_mode=falloc ---
+--- cluster_size=512 growth_size=80 create_mode=metadata growth_mode=falloc ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -311,7 +311,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 81920/81920 bytes at offset 2048000
 80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=80 create_mode=metadata growth_mode=full ---
+--- cluster_size=512 growth_size=80 create_mode=metadata growth_mode=full ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -319,7 +319,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 81920/81920 bytes at offset 2048000
 80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=80 create_mode=falloc growth_mode=off ---
+--- cluster_size=512 growth_size=80 create_mode=falloc growth_mode=off ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -327,7 +327,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 81920/81920 bytes at offset 2048000
 80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=80 create_mode=falloc growth_mode=metadata ---
+--- cluster_size=512 growth_size=80 create_mode=falloc growth_mode=metadata ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -335,7 +335,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 81920/81920 bytes at offset 2048000
 80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=80 create_mode=falloc growth_mode=falloc ---
+--- cluster_size=512 growth_size=80 create_mode=falloc growth_mode=falloc ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -343,7 +343,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 81920/81920 bytes at offset 2048000
 80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=80 create_mode=falloc growth_mode=full ---
+--- cluster_size=512 growth_size=80 create_mode=falloc growth_mode=full ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -351,7 +351,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 81920/81920 bytes at offset 2048000
 80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=80 create_mode=full growth_mode=off ---
+--- cluster_size=512 growth_size=80 create_mode=full growth_mode=off ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -359,7 +359,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 81920/81920 bytes at offset 2048000
 80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=80 create_mode=full growth_mode=metadata ---
+--- cluster_size=512 growth_size=80 create_mode=full growth_mode=metadata ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -367,7 +367,7 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 81920/81920 bytes at offset 2048000
 80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=80 create_mode=full growth_mode=falloc ---
+--- cluster_size=512 growth_size=80 create_mode=full growth_mode=falloc ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
@@ -375,7 +375,391 @@ wrote 2048000/2048000 bytes at offset 0
 wrote 81920/81920 bytes at offset 2048000
 80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
---- growth_size=80 create_mode=full growth_mode=full ---
+--- cluster_size=512 growth_size=80 create_mode=full growth_mode=full ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 81920/81920 bytes at offset 2048000
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=16 create_mode=off growth_mode=off ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 16384/16384 bytes at offset 2048000
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=16 create_mode=off growth_mode=metadata ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 16384/16384 bytes at offset 2048000
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=16 create_mode=off growth_mode=falloc ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 16384/16384 bytes at offset 2048000
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=16 create_mode=off growth_mode=full ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 16384/16384 bytes at offset 2048000
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=16 create_mode=metadata growth_mode=off ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 16384/16384 bytes at offset 2048000
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=16 create_mode=metadata growth_mode=metadata ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 16384/16384 bytes at offset 2048000
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=16 create_mode=metadata growth_mode=falloc ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 16384/16384 bytes at offset 2048000
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=16 create_mode=metadata growth_mode=full ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 16384/16384 bytes at offset 2048000
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=16 create_mode=falloc growth_mode=off ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 16384/16384 bytes at offset 2048000
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=16 create_mode=falloc growth_mode=metadata ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 16384/16384 bytes at offset 2048000
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=16 create_mode=falloc growth_mode=falloc ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 16384/16384 bytes at offset 2048000
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=16 create_mode=falloc growth_mode=full ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 16384/16384 bytes at offset 2048000
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=16 create_mode=full growth_mode=off ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 16384/16384 bytes at offset 2048000
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=16 create_mode=full growth_mode=metadata ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 16384/16384 bytes at offset 2048000
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=16 create_mode=full growth_mode=falloc ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 16384/16384 bytes at offset 2048000
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=16 create_mode=full growth_mode=full ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 16384/16384 bytes at offset 2048000
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=48 create_mode=off growth_mode=off ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 49152/49152 bytes at offset 2048000
+48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=48 create_mode=off growth_mode=metadata ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 49152/49152 bytes at offset 2048000
+48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=48 create_mode=off growth_mode=falloc ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 49152/49152 bytes at offset 2048000
+48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=48 create_mode=off growth_mode=full ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 49152/49152 bytes at offset 2048000
+48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=48 create_mode=metadata growth_mode=off ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 49152/49152 bytes at offset 2048000
+48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=48 create_mode=metadata growth_mode=metadata ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 49152/49152 bytes at offset 2048000
+48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=48 create_mode=metadata growth_mode=falloc ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 49152/49152 bytes at offset 2048000
+48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=48 create_mode=metadata growth_mode=full ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 49152/49152 bytes at offset 2048000
+48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=48 create_mode=falloc growth_mode=off ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 49152/49152 bytes at offset 2048000
+48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=48 create_mode=falloc growth_mode=metadata ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 49152/49152 bytes at offset 2048000
+48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=48 create_mode=falloc growth_mode=falloc ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 49152/49152 bytes at offset 2048000
+48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=48 create_mode=falloc growth_mode=full ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 49152/49152 bytes at offset 2048000
+48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=48 create_mode=full growth_mode=off ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 49152/49152 bytes at offset 2048000
+48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=48 create_mode=full growth_mode=metadata ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 49152/49152 bytes at offset 2048000
+48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=48 create_mode=full growth_mode=falloc ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 49152/49152 bytes at offset 2048000
+48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=48 create_mode=full growth_mode=full ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 49152/49152 bytes at offset 2048000
+48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=80 create_mode=off growth_mode=off ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 81920/81920 bytes at offset 2048000
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=80 create_mode=off growth_mode=metadata ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 81920/81920 bytes at offset 2048000
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=80 create_mode=off growth_mode=falloc ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 81920/81920 bytes at offset 2048000
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=80 create_mode=off growth_mode=full ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 81920/81920 bytes at offset 2048000
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=80 create_mode=metadata growth_mode=off ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 81920/81920 bytes at offset 2048000
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=80 create_mode=metadata growth_mode=metadata ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 81920/81920 bytes at offset 2048000
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=80 create_mode=metadata growth_mode=falloc ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 81920/81920 bytes at offset 2048000
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=80 create_mode=metadata growth_mode=full ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 81920/81920 bytes at offset 2048000
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=80 create_mode=falloc growth_mode=off ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 81920/81920 bytes at offset 2048000
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=80 create_mode=falloc growth_mode=metadata ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 81920/81920 bytes at offset 2048000
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=80 create_mode=falloc growth_mode=falloc ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 81920/81920 bytes at offset 2048000
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=80 create_mode=falloc growth_mode=full ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 81920/81920 bytes at offset 2048000
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=80 create_mode=full growth_mode=off ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 81920/81920 bytes at offset 2048000
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=80 create_mode=full growth_mode=metadata ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 81920/81920 bytes at offset 2048000
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=80 create_mode=full growth_mode=falloc ---
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
+Image resized.
+wrote 2048000/2048000 bytes at offset 0
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 81920/81920 bytes at offset 2048000
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+--- cluster_size=64k growth_size=80 create_mode=full growth_mode=full ---
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
 Image resized.
 wrote 2048000/2048000 bytes at offset 0
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 32/55] nios2: define tcg_env
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (30 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 31/55] iotests: Add cluster_size=64k to 125 Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 33/55] io: monitor encoutput buffer size from websocket GSource Michael Roth
                   ` (22 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Paolo Bonzini, Marek Vasut

From: Paolo Bonzini <pbonzini@redhat.com>

This should be done by all target and, since commit 53f6672bcf
("gen-icount: use tcg_ctx.tcg_env instead of cpu_env", 2017-06-30),
is causing the NIOS2 target to hang.

This is because the test for "should I exit to the main loop"
was being done with the correct offset to the icount decrementer,
but using TCG temporary 0 (the frame pointer) rather than the
env pointer.

Cc: qemu-stable@nongnu.org
Cc: Marek Vasut <marex@denx.de>
Reported-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 17bd9597be45b96ae00716b0ae01a4d11bbee1ab)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 target/nios2/translate.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/target/nios2/translate.c b/target/nios2/translate.c
index 8b97d6585f..f25ef7e2bb 100644
--- a/target/nios2/translate.c
+++ b/target/nios2/translate.c
@@ -942,6 +942,7 @@ void nios2_tcg_init(void)
     int i;
 
     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+    tcg_ctx.tcg_env = cpu_env;
 
     for (i = 0; i < NUM_CORE_REGS; i++) {
         cpu_R[i] = tcg_global_mem_new(cpu_env,
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 33/55] io: monitor encoutput buffer size from websocket GSource
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (31 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 32/55] nios2: define tcg_env Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 34/55] ppc: fix setting of compat mode Michael Roth
                   ` (21 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Daniel P. Berrange

From: "Daniel P. Berrange" <berrange@redhat.com>

The websocket GSource is monitoring the size of the rawoutput
buffer to determine if the channel can accepts more writes.
The rawoutput buffer, however, is merely a temporary staging
buffer before data is copied into the encoutput buffer. Thus
its size will always be zero when the GSource runs.

This flaw causes the encoutput buffer to grow without bound
if the other end of the underlying data channel doesn't
read data being sent. This can be seen with VNC if a client
is on a slow WAN link and the guest OS is sending many screen
updates. A malicious VNC client can act like it is on a slow
link by playing a video in the guest and then reading data
very slowly, causing QEMU host memory to expand arbitrarily.

This issue is assigned CVE-2017-15268, publically reported in

  https://bugs.launchpad.net/qemu/+bug/1718964

(cherry picked from commit a7b20a8efa28e5f22c26c06cd06c2f12bc863493)

Reviewed-by: Eric Blake <eblake@redhat.com>

[Dan: Added extra checks to deal with code refactored in master but
 not stable 2.10]

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 io/channel-websock.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/io/channel-websock.c b/io/channel-websock.c
index 5a3badbec2..19116dc148 100644
--- a/io/channel-websock.c
+++ b/io/channel-websock.c
@@ -26,7 +26,7 @@
 #include "trace.h"
 
 
-/* Max amount to allow in rawinput/rawoutput buffers */
+/* Max amount to allow in rawinput/encoutput buffers */
 #define QIO_CHANNEL_WEBSOCK_MAX_BUFFER 8192
 
 #define QIO_CHANNEL_WEBSOCK_CLIENT_KEY_LEN 24
@@ -1006,7 +1006,7 @@ qio_channel_websock_source_prepare(GSource *source,
     if (wsource->wioc->rawinput.offset) {
         cond |= G_IO_IN;
     }
-    if (wsource->wioc->rawoutput.offset < QIO_CHANNEL_WEBSOCK_MAX_BUFFER) {
+    if (wsource->wioc->encoutput.offset < QIO_CHANNEL_WEBSOCK_MAX_BUFFER) {
         cond |= G_IO_OUT;
     }
 
@@ -1022,7 +1022,7 @@ qio_channel_websock_source_check(GSource *source)
     if (wsource->wioc->rawinput.offset) {
         cond |= G_IO_IN;
     }
-    if (wsource->wioc->rawoutput.offset < QIO_CHANNEL_WEBSOCK_MAX_BUFFER) {
+    if (wsource->wioc->encoutput.offset < QIO_CHANNEL_WEBSOCK_MAX_BUFFER) {
         cond |= G_IO_OUT;
     }
 
@@ -1041,7 +1041,7 @@ qio_channel_websock_source_dispatch(GSource *source,
     if (wsource->wioc->rawinput.offset) {
         cond |= G_IO_IN;
     }
-    if (wsource->wioc->rawoutput.offset < QIO_CHANNEL_WEBSOCK_MAX_BUFFER) {
+    if (wsource->wioc->encoutput.offset < QIO_CHANNEL_WEBSOCK_MAX_BUFFER) {
         cond |= G_IO_OUT;
     }
 
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 34/55] ppc: fix setting of compat mode
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (32 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 33/55] io: monitor encoutput buffer size from websocket GSource Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 35/55] translate.c: Fix usermode big-endian AArch32 LDREXD and STREXD Michael Roth
                   ` (20 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Greg Kurz, David Gibson

From: Greg Kurz <groug@kaod.org>

While trying to make KVM PR usable again, commit 5dfaa532ae introduced a
regression: the current compat_pvr value is passed to KVM instead of the
new one. This means that we always pass 0 instead of the max-cpu-compat
PVR during the initial machine reset. And at CAS time, we either pass
the PVR from the command line or even don't call kvmppc_set_compat() at
all, ie, the PCR will not be set as expected.

For example if we start a big endian fedora26 guest in power7 compat
mode on a POWER8 host, we get this in the guest:

$ cat /proc/cpuinfo
processor       : 0
cpu             : POWER7 (architected), altivec supported
clock           : 4024.000000MHz
revision        : 2.0 (pvr 004d 0200)

timebase        : 512000000
platform        : pSeries
model           : IBM pSeries (emulated by qemu)
machine         : CHRP IBM pSeries (emulated by qemu)
MMU             : Hash

but the guest can still execute POWER8 instructions, and the following
program succeeds:

int main()
{
        asm("vncipher 0,0,0"); // ISA 2.07 instruction
}

Let's pass the new compat_pvr to kvmppc_set_compat() and the program fails
with SIGILL as expected.

Reported-by: Nageswara R Sastry <rnsastry@linux.vnet.ibm.com>
Signed-off-by: Greg Kurz <groug@kaod.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
(cherry picked from commit e4f0c6bb1a9f72ad9e32c3171d36bae17ea1cd67)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 target/ppc/compat.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/ppc/compat.c b/target/ppc/compat.c
index f8729fe46d..ad8f93c064 100644
--- a/target/ppc/compat.c
+++ b/target/ppc/compat.c
@@ -141,7 +141,7 @@ void ppc_set_compat(PowerPCCPU *cpu, uint32_t compat_pvr, Error **errp)
     cpu_synchronize_state(CPU(cpu));
 
     if (kvm_enabled() && cpu->compat_pvr != compat_pvr) {
-        int ret = kvmppc_set_compat(cpu, cpu->compat_pvr);
+        int ret = kvmppc_set_compat(cpu, compat_pvr);
         if (ret < 0) {
             error_setg_errno(errp, -ret,
                              "Unable to set CPU compatibility mode in KVM");
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 35/55] translate.c: Fix usermode big-endian AArch32 LDREXD and STREXD
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (33 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 34/55] ppc: fix setting of compat mode Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 36/55] hw/intc/arm_gicv3_its: Don't abort on table save failure Michael Roth
                   ` (19 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Peter Maydell

From: Peter Maydell <peter.maydell@linaro.org>

For AArch32 LDREXD and STREXD, architecturally the 32-bit word at the
lowest address is always Rt and the one at addr+4 is Rt2, even if the
CPU is big-endian. Our implementation does these with a single
64-bit store, so if we're big-endian then we need to put the two
32-bit halves together in the opposite order to little-endian,
so that they end up in the right places. We were trying to do
this with the gen_aa32_frob64() function, but that is not correct
for the usermode emulator, because there there is a distinction
between "load a 64 bit value" (which does a BE 64-bit access
and doesn't need swapping) and "load two 32 bit values as one
64 bit access" (where we still need to do the swapping, like
system mode BE32).

Fixes: https://bugs.launchpad.net/qemu/+bug/1725267
Cc: qemu-stable@nongnu.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 1509622400-13351-1-git-send-email-peter.maydell@linaro.org
(cherry picked from commit 3448d47b3172015006b79197eb5a69826c6a7b6d)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 target/arm/translate.c | 39 ++++++++++++++++++++++++++++++++++-----
 1 file changed, 34 insertions(+), 5 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index d1a5f56998..ad758d333d 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -7858,9 +7858,27 @@ static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
         TCGv_i32 tmp2 = tcg_temp_new_i32();
         TCGv_i64 t64 = tcg_temp_new_i64();
 
-        gen_aa32_ld_i64(s, t64, addr, get_mem_index(s), opc);
+        /* For AArch32, architecturally the 32-bit word at the lowest
+         * address is always Rt and the one at addr+4 is Rt2, even if
+         * the CPU is big-endian. That means we don't want to do a
+         * gen_aa32_ld_i64(), which invokes gen_aa32_frob64() as if
+         * for an architecturally 64-bit access, but instead do a
+         * 64-bit access using MO_BE if appropriate and then split
+         * the two halves.
+         * This only makes a difference for BE32 user-mode, where
+         * frob64() must not flip the two halves of the 64-bit data
+         * but this code must treat BE32 user-mode like BE32 system.
+         */
+        TCGv taddr = gen_aa32_addr(s, addr, opc);
+
+        tcg_gen_qemu_ld_i64(t64, taddr, get_mem_index(s), opc);
+        tcg_temp_free(taddr);
         tcg_gen_mov_i64(cpu_exclusive_val, t64);
-        tcg_gen_extr_i64_i32(tmp, tmp2, t64);
+        if (s->be_data == MO_BE) {
+            tcg_gen_extr_i64_i32(tmp2, tmp, t64);
+        } else {
+            tcg_gen_extr_i64_i32(tmp, tmp2, t64);
+        }
         tcg_temp_free_i64(t64);
 
         store_reg(s, rt2, tmp2);
@@ -7909,15 +7927,26 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
         TCGv_i64 n64 = tcg_temp_new_i64();
 
         t2 = load_reg(s, rt2);
-        tcg_gen_concat_i32_i64(n64, t1, t2);
+        /* For AArch32, architecturally the 32-bit word at the lowest
+         * address is always Rt and the one at addr+4 is Rt2, even if
+         * the CPU is big-endian. Since we're going to treat this as a
+         * single 64-bit BE store, we need to put the two halves in the
+         * opposite order for BE to LE, so that they end up in the right
+         * places.
+         * We don't want gen_aa32_frob64() because that does the wrong
+         * thing for BE32 usermode.
+         */
+        if (s->be_data == MO_BE) {
+            tcg_gen_concat_i32_i64(n64, t2, t1);
+        } else {
+            tcg_gen_concat_i32_i64(n64, t1, t2);
+        }
         tcg_temp_free_i32(t2);
-        gen_aa32_frob64(s, n64);
 
         tcg_gen_atomic_cmpxchg_i64(o64, taddr, cpu_exclusive_val, n64,
                                    get_mem_index(s), opc);
         tcg_temp_free_i64(n64);
 
-        gen_aa32_frob64(s, o64);
         tcg_gen_setcond_i64(TCG_COND_NE, o64, o64, cpu_exclusive_val);
         tcg_gen_extrl_i64_i32(t0, o64);
 
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 36/55] hw/intc/arm_gicv3_its: Don't abort on table save failure
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (34 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 35/55] translate.c: Fix usermode big-endian AArch32 LDREXD and STREXD Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 37/55] net/socket: fix coverity issue Michael Roth
                   ` (18 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Eric Auger, Peter Maydell

From: Eric Auger <eric.auger@redhat.com>

The ITS is not fully properly reset at the moment. Caches are
not emptied.

After a reset, in case we attempt to save the state before
the bound devices have registered their MSIs and after the
1st level table has been allocated by the ITS driver
(device BASER is valid), the first level entries are still
invalid. If the device cache is not empty (devices registered
before the reset), vgic_its_save_device_tables fails with -EINVAL.
This causes a QEMU abort().

Cc: qemu-stable@nongnu.org
Signed-off-by: Eric Auger <eric.auger@redhat.com>
Reported-by: wanghaibin <wanghaibin.wang@huawei.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit 8a7348b5d62d7ea16807e6bea54b448a0184bb0f)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 hw/intc/arm_gicv3_its_kvm.c | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/hw/intc/arm_gicv3_its_kvm.c b/hw/intc/arm_gicv3_its_kvm.c
index 1f8991b8a6..1cc58c2da3 100644
--- a/hw/intc/arm_gicv3_its_kvm.c
+++ b/hw/intc/arm_gicv3_its_kvm.c
@@ -64,20 +64,16 @@ static void vm_change_state_handler(void *opaque, int running,
 {
     GICv3ITSState *s = (GICv3ITSState *)opaque;
     Error *err = NULL;
-    int ret;
 
     if (running) {
         return;
     }
 
-    ret = kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
-                            KVM_DEV_ARM_ITS_SAVE_TABLES, NULL, true, &err);
+    kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
+                      KVM_DEV_ARM_ITS_SAVE_TABLES, NULL, true, &err);
     if (err) {
         error_report_err(err);
     }
-    if (ret < 0 && ret != -EFAULT) {
-        abort();
-    }
 }
 
 static void kvm_arm_its_realize(DeviceState *dev, Error **errp)
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 37/55] net/socket: fix coverity issue
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (35 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 36/55] hw/intc/arm_gicv3_its: Don't abort on table save failure Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 38/55] net: fix check for number of parameters to -netdev socket Michael Roth
                   ` (17 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Jens Freimann, Jason Wang

From: Jens Freimann <jfreimann@redhat.com>

This fixes coverity issue CID1005339.

Make sure that saddr is not used uninitialized if the
mcast parameter is NULL.

Cc: qemu-stable@nongnu.org
Reported-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Jens Freimann <jfreimann@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
(cherry picked from commit bb160b571fe469b03228d4502c75a18045978a74)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 net/socket.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/socket.c b/net/socket.c
index 18af2ab5f3..6664a75aa4 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -369,7 +369,7 @@ static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer,
     net_socket_read_poll(s, true);
 
     /* mcast: save bound address as dst */
-    if (is_connected) {
+    if (is_connected && mcast != NULL) {
         s->dgram_dst = saddr;
         snprintf(nc->info_str, sizeof(nc->info_str),
                  "socket: fd=%d (cloned mcast=%s:%d)",
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 38/55] net: fix check for number of parameters to -netdev socket
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (36 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 37/55] net/socket: fix coverity issue Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 39/55] nbd/client: Use error_prepend() correctly Michael Roth
                   ` (16 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Jens Freimann, Jason Wang

From: Jens Freimann <jfreimann@redhat.com>

Since commit 0f8c289ad "net: fix -netdev socket,fd= for UDP sockets"
we allow more than one parameter for -netdev socket. But now
we run into an assert when no parameter at all is specified

> qemu-system-x86_64 -netdev socket
socket.c:729: net_init_socket: Assertion `sock->has_udp' failed.

Fix this by reverting the change of the if condition done in 0f8c289ad.

Cc: Jason Wang <jasowang@redhat.com>
Cc: qemu-stable@nongnu.org
Fixes: 0f8c289ad539feb5135c545bea947b310a893f4b
Reported-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
Signed-off-by: Jens Freimann <jfreimann@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
(cherry picked from commit ff86d5762552787f1fcb7da695ec4f8c1be754b4)
 Conflicts:
	net/socket.c
* drop context dep on 0522a959
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 net/socket.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/socket.c b/net/socket.c
index 6664a75aa4..95060e5ca2 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -674,8 +674,8 @@ int net_init_socket(const Netdev *netdev, const char *name,
     assert(netdev->type == NET_CLIENT_DRIVER_SOCKET);
     sock = &netdev->u.socket;
 
-    if (sock->has_listen + sock->has_connect + sock->has_mcast +
-        sock->has_udp > 1) {
+    if (sock->has_fd + sock->has_listen + sock->has_connect + sock->has_mcast +
+        sock->has_udp != 1) {
         error_report("exactly one of listen=, connect=, mcast= or udp="
                      " is required");
         return -1;
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 39/55] nbd/client: Use error_prepend() correctly
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (37 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 38/55] net: fix check for number of parameters to -netdev socket Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 40/55] util/stats64: Fix min/max comparisons Michael Roth
                   ` (15 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Eric Blake

From: Eric Blake <eblake@redhat.com>

When using error prepend(), it is necessary to end with a space
in the format string; otherwise, messages come out incorrectly,
such as when connecting to a socket that hangs up immediately:

can't open device nbd://localhost:10809/: Failed to read dataUnexpected end-of-file before all bytes were read

Originally botched in commit e44ed99d, then several more instances
added in the meantime.

Pre-existing and not fixed here: we are inconsistent on capitalization;
some of our messages start with lower case, and others start with upper,
although the use of error_prepend() is much nicer to read when all
fragments consistently start with lower.

CC: qemu-stable@nongnu.org
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <20171113152424.25381-1-eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
(cherry picked from commit cb6b1a3fc30c52ffd94ed0b69ca5991b19651724)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 nbd/client.c | 50 ++++++++++++++++++++++++++------------------------
 1 file changed, 26 insertions(+), 24 deletions(-)

diff --git a/nbd/client.c b/nbd/client.c
index 0a17de80b5..4caff77119 100644
--- a/nbd/client.c
+++ b/nbd/client.c
@@ -111,12 +111,12 @@ static int nbd_send_option_request(QIOChannel *ioc, uint32_t opt,
     stl_be_p(&req.length, len);
 
     if (nbd_write(ioc, &req, sizeof(req), errp) < 0) {
-        error_prepend(errp, "Failed to send option request header");
+        error_prepend(errp, "Failed to send option request header: ");
         return -1;
     }
 
     if (len && nbd_write(ioc, (char *) data, len, errp) < 0) {
-        error_prepend(errp, "Failed to send option request data");
+        error_prepend(errp, "Failed to send option request data: ");
         return -1;
     }
 
@@ -145,7 +145,7 @@ static int nbd_receive_option_reply(QIOChannel *ioc, uint32_t opt,
 {
     QEMU_BUILD_BUG_ON(sizeof(*reply) != 20);
     if (nbd_read(ioc, reply, sizeof(*reply), errp) < 0) {
-        error_prepend(errp, "failed to read option reply");
+        error_prepend(errp, "failed to read option reply: ");
         nbd_send_opt_abort(ioc);
         return -1;
     }
@@ -198,7 +198,7 @@ static int nbd_handle_reply_err(QIOChannel *ioc, nbd_opt_reply *reply,
         msg = g_malloc(reply->length + 1);
         if (nbd_read(ioc, msg, reply->length, errp) < 0) {
             error_prepend(errp, "failed to read option error 0x%" PRIx32
-                          " (%s) message",
+                          " (%s) message: ",
                           reply->type, nbd_rep_lookup(reply->type));
             goto cleanup;
         }
@@ -309,7 +309,7 @@ static int nbd_receive_list(QIOChannel *ioc, const char *want, bool *match,
         return -1;
     }
     if (nbd_read(ioc, &namelen, sizeof(namelen), errp) < 0) {
-        error_prepend(errp, "failed to read option name length");
+        error_prepend(errp, "failed to read option name length: ");
         nbd_send_opt_abort(ioc);
         return -1;
     }
@@ -322,7 +322,8 @@ static int nbd_receive_list(QIOChannel *ioc, const char *want, bool *match,
     }
     if (namelen != strlen(want)) {
         if (nbd_drop(ioc, len, errp) < 0) {
-            error_prepend(errp, "failed to skip export name with wrong length");
+            error_prepend(errp,
+                          "failed to skip export name with wrong length: ");
             nbd_send_opt_abort(ioc);
             return -1;
         }
@@ -331,14 +332,14 @@ static int nbd_receive_list(QIOChannel *ioc, const char *want, bool *match,
 
     assert(namelen < sizeof(name));
     if (nbd_read(ioc, name, namelen, errp) < 0) {
-        error_prepend(errp, "failed to read export name");
+        error_prepend(errp, "failed to read export name: ");
         nbd_send_opt_abort(ioc);
         return -1;
     }
     name[namelen] = '\0';
     len -= namelen;
     if (nbd_drop(ioc, len, errp) < 0) {
-        error_prepend(errp, "failed to read export description");
+        error_prepend(errp, "failed to read export description: ");
         nbd_send_opt_abort(ioc);
         return -1;
     }
@@ -424,7 +425,7 @@ static int nbd_opt_go(QIOChannel *ioc, const char *wantname,
             return -1;
         }
         if (nbd_read(ioc, &type, sizeof(type), errp) < 0) {
-            error_prepend(errp, "failed to read info type");
+            error_prepend(errp, "failed to read info type: ");
             nbd_send_opt_abort(ioc);
             return -1;
         }
@@ -439,13 +440,13 @@ static int nbd_opt_go(QIOChannel *ioc, const char *wantname,
                 return -1;
             }
             if (nbd_read(ioc, &info->size, sizeof(info->size), errp) < 0) {
-                error_prepend(errp, "failed to read info size");
+                error_prepend(errp, "failed to read info size: ");
                 nbd_send_opt_abort(ioc);
                 return -1;
             }
             be64_to_cpus(&info->size);
             if (nbd_read(ioc, &info->flags, sizeof(info->flags), errp) < 0) {
-                error_prepend(errp, "failed to read info flags");
+                error_prepend(errp, "failed to read info flags: ");
                 nbd_send_opt_abort(ioc);
                 return -1;
             }
@@ -462,7 +463,7 @@ static int nbd_opt_go(QIOChannel *ioc, const char *wantname,
             }
             if (nbd_read(ioc, &info->min_block, sizeof(info->min_block),
                          errp) < 0) {
-                error_prepend(errp, "failed to read info minimum block size");
+                error_prepend(errp, "failed to read info minimum block size: ");
                 nbd_send_opt_abort(ioc);
                 return -1;
             }
@@ -475,7 +476,8 @@ static int nbd_opt_go(QIOChannel *ioc, const char *wantname,
             }
             if (nbd_read(ioc, &info->opt_block, sizeof(info->opt_block),
                          errp) < 0) {
-                error_prepend(errp, "failed to read info preferred block size");
+                error_prepend(errp,
+                              "failed to read info preferred block size: ");
                 nbd_send_opt_abort(ioc);
                 return -1;
             }
@@ -489,7 +491,7 @@ static int nbd_opt_go(QIOChannel *ioc, const char *wantname,
             }
             if (nbd_read(ioc, &info->max_block, sizeof(info->max_block),
                          errp) < 0) {
-                error_prepend(errp, "failed to read info maximum block size");
+                error_prepend(errp, "failed to read info maximum block size: ");
                 nbd_send_opt_abort(ioc);
                 return -1;
             }
@@ -501,7 +503,7 @@ static int nbd_opt_go(QIOChannel *ioc, const char *wantname,
         default:
             trace_nbd_opt_go_info_unknown(type, nbd_info_lookup(type));
             if (nbd_drop(ioc, len, errp) < 0) {
-                error_prepend(errp, "Failed to read info payload");
+                error_prepend(errp, "Failed to read info payload: ");
                 nbd_send_opt_abort(ioc);
                 return -1;
             }
@@ -624,7 +626,7 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name,
     }
 
     if (nbd_read(ioc, buf, 8, errp) < 0) {
-        error_prepend(errp, "Failed to read data");
+        error_prepend(errp, "Failed to read data: ");
         goto fail;
     }
 
@@ -643,7 +645,7 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name,
     }
 
     if (nbd_read(ioc, &magic, sizeof(magic), errp) < 0) {
-        error_prepend(errp, "Failed to read magic");
+        error_prepend(errp, "Failed to read magic: ");
         goto fail;
     }
     magic = be64_to_cpu(magic);
@@ -655,7 +657,7 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name,
         bool fixedNewStyle = false;
 
         if (nbd_read(ioc, &globalflags, sizeof(globalflags), errp) < 0) {
-            error_prepend(errp, "Failed to read server flags");
+            error_prepend(errp, "Failed to read server flags: ");
             goto fail;
         }
         globalflags = be16_to_cpu(globalflags);
@@ -671,7 +673,7 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name,
         /* client requested flags */
         clientflags = cpu_to_be32(clientflags);
         if (nbd_write(ioc, &clientflags, sizeof(clientflags), errp) < 0) {
-            error_prepend(errp, "Failed to send clientflags field");
+            error_prepend(errp, "Failed to send clientflags field: ");
             goto fail;
         }
         if (tlscreds) {
@@ -723,13 +725,13 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name,
 
         /* Read the response */
         if (nbd_read(ioc, &info->size, sizeof(info->size), errp) < 0) {
-            error_prepend(errp, "Failed to read export length");
+            error_prepend(errp, "Failed to read export length: ");
             goto fail;
         }
         be64_to_cpus(&info->size);
 
         if (nbd_read(ioc, &info->flags, sizeof(info->flags), errp) < 0) {
-            error_prepend(errp, "Failed to read export flags");
+            error_prepend(errp, "Failed to read export flags: ");
             goto fail;
         }
         be16_to_cpus(&info->flags);
@@ -746,13 +748,13 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name,
         }
 
         if (nbd_read(ioc, &info->size, sizeof(info->size), errp) < 0) {
-            error_prepend(errp, "Failed to read export length");
+            error_prepend(errp, "Failed to read export length: ");
             goto fail;
         }
         be64_to_cpus(&info->size);
 
         if (nbd_read(ioc, &oldflags, sizeof(oldflags), errp) < 0) {
-            error_prepend(errp, "Failed to read export flags");
+            error_prepend(errp, "Failed to read export flags: ");
             goto fail;
         }
         be32_to_cpus(&oldflags);
@@ -768,7 +770,7 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name,
 
     trace_nbd_receive_negotiate_size_flags(info->size, info->flags);
     if (zeroes && nbd_drop(ioc, 124, errp) < 0) {
-        error_prepend(errp, "Failed to read reserved block");
+        error_prepend(errp, "Failed to read reserved block: ");
         goto fail;
     }
     rc = 0;
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 40/55] util/stats64: Fix min/max comparisons
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (38 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 39/55] nbd/client: Use error_prepend() correctly Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 41/55] virtio: Add queue interface to restore avail index from vring used index Michael Roth
                   ` (14 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Max Reitz, Paolo Bonzini

From: Max Reitz <mreitz@redhat.com>

stat64_min_slow() and stat64_max_slow() compare the wrong way.  This
makes iotest 136 fail with clang and -m32.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Message-Id: <20171114232223.25207-1-mreitz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 26a5db322be1e424a815d070ddd04442a5e5df50)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 util/stats64.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/util/stats64.c b/util/stats64.c
index 9968fcceac..389c365a9e 100644
--- a/util/stats64.c
+++ b/util/stats64.c
@@ -91,7 +91,7 @@ bool stat64_min_slow(Stat64 *s, uint64_t value)
     low = atomic_read(&s->low);
 
     orig = ((uint64_t)high << 32) | low;
-    if (orig < value) {
+    if (value < orig) {
         /* We have to set low before high, just like stat64_min reads
          * high before low.  The value may become higher temporarily, but
          * stat64_get does not notice (it takes the lock) and the only ill
@@ -120,7 +120,7 @@ bool stat64_max_slow(Stat64 *s, uint64_t value)
     low = atomic_read(&s->low);
 
     orig = ((uint64_t)high << 32) | low;
-    if (orig > value) {
+    if (value > orig) {
         /* We have to set low before high, just like stat64_max reads
          * high before low.  The value may become lower temporarily, but
          * stat64_get does not notice (it takes the lock) and the only ill
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 41/55] virtio: Add queue interface to restore avail index from vring used index
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (39 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 40/55] util/stats64: Fix min/max comparisons Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 42/55] vhost: restore avail index from vring used index on disconnection Michael Roth
                   ` (13 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Maxime Coquelin, Michael S . Tsirkin

From: Maxime Coquelin <maxime.coquelin@redhat.com>

In case of backend crash, it is not possible to restore internal
avail index from the backend value as vhost_get_vring_base
callback fails.

This patch provides a new interface to restore internal avail index
from the vring used index, as done by some vhost-user backend on
reconnection.

Signed-off-by: Maxime Coquelin <maxime.coquelin@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit 2d4ba6cc741df15df6fbb4feaa706a02e103083a)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 hw/virtio/virtio.c         | 10 ++++++++++
 include/hw/virtio/virtio.h |  1 +
 2 files changed, 11 insertions(+)

diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 464947f76d..15cf6021a0 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -2311,6 +2311,16 @@ void virtio_queue_set_last_avail_idx(VirtIODevice *vdev, int n, uint16_t idx)
     vdev->vq[n].shadow_avail_idx = idx;
 }
 
+void virtio_queue_restore_last_avail_idx(VirtIODevice *vdev, int n)
+{
+    rcu_read_lock();
+    if (vdev->vq[n].vring.desc) {
+        vdev->vq[n].last_avail_idx = vring_used_idx(&vdev->vq[n]);
+        vdev->vq[n].shadow_avail_idx = vdev->vq[n].last_avail_idx;
+    }
+    rcu_read_unlock();
+}
+
 void virtio_queue_update_used_idx(VirtIODevice *vdev, int n)
 {
     rcu_read_lock();
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index 80c45c321e..3d5c84e829 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -272,6 +272,7 @@ hwaddr virtio_queue_get_avail_size(VirtIODevice *vdev, int n);
 hwaddr virtio_queue_get_used_size(VirtIODevice *vdev, int n);
 uint16_t virtio_queue_get_last_avail_idx(VirtIODevice *vdev, int n);
 void virtio_queue_set_last_avail_idx(VirtIODevice *vdev, int n, uint16_t idx);
+void virtio_queue_restore_last_avail_idx(VirtIODevice *vdev, int n);
 void virtio_queue_invalidate_signalled_used(VirtIODevice *vdev, int n);
 void virtio_queue_update_used_idx(VirtIODevice *vdev, int n);
 VirtQueue *virtio_get_queue(VirtIODevice *vdev, int n);
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 42/55] vhost: restore avail index from vring used index on disconnection
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (40 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 41/55] virtio: Add queue interface to restore avail index from vring used index Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 43/55] hw/ppc: clear pending_events on machine reset Michael Roth
                   ` (12 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Maxime Coquelin, Michael S . Tsirkin

From: Maxime Coquelin <maxime.coquelin@redhat.com>

vhost_virtqueue_stop() gets avail index value from the backend,
except if the backend is not responding.

It happens when the backend crashes, and in this case, internal
state of the virtio queue is inconsistent, making packets
to corrupt the vring state.

With a Linux guest, it results in following error message on
backend reconnection:

[   22.444905] virtio_net virtio0: output.0:id 0 is not a head!
[   22.446746] net enp0s3: Unexpected TXQ (0) queue failure: -5
[   22.476360] net enp0s3: Unexpected TXQ (0) queue failure: -5

Fixes: 283e2c2adcb8 ("net: virtio-net discards TX data after link down")
Cc: qemu-stable@nongnu.org
Signed-off-by: Maxime Coquelin <maxime.coquelin@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit 2ae39a113af311cb56a0c35b7f212dafcef15303)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 hw/virtio/vhost.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index b737ca915b..76f6e1fcaa 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1137,6 +1137,10 @@ static void vhost_virtqueue_stop(struct vhost_dev *dev,
     r = dev->vhost_ops->vhost_get_vring_base(dev, &state);
     if (r < 0) {
         VHOST_OPS_DEBUG("vhost VQ %d ring restore failed: %d", idx, r);
+        /* Connection to the backend is broken, so let's sync internal
+         * last avail idx to the device used idx.
+         */
+        virtio_queue_restore_last_avail_idx(vdev, idx);
     } else {
         virtio_queue_set_last_avail_idx(vdev, idx, state.num);
     }
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 43/55] hw/ppc: clear pending_events on machine reset
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (41 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 42/55] vhost: restore avail index from vring used index on disconnection Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 44/55] spapr: reset DRCs after devices Michael Roth
                   ` (11 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Daniel Henrique Barboza, David Gibson

From: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com>

The sPAPR machine isn't clearing up the pending events QTAILQ on
machine reboot. This allows for unprocessed hotplug/epow events
to persist in the queue after reset and, when reasserting the IRQs in
check_exception later on, these will be being processed by the OS.

This patch implements a new function called 'spapr_clear_pending_events'
that clears up the pending_events QTAILQ. This helper is then called
inside ppc_spapr_reset to clear up the events queue, preventing
old/deprecated events from persisting after a reset.

Signed-off-by: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
(cherry picked from commit 56258174238eb25df629a53a96e1ac16a32dc7d4)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 hw/ppc/spapr.c         |  1 +
 hw/ppc/spapr_events.c  | 11 +++++++++++
 include/hw/ppc/spapr.h |  1 +
 3 files changed, 13 insertions(+)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index cc3901a790..954fd1a747 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1416,6 +1416,7 @@ static void ppc_spapr_reset(void)
     }
 
     qemu_devices_reset();
+    spapr_clear_pending_events(spapr);
 
     /*
      * We place the device tree and RTAS just below either the top of the RMA,
diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c
index f952b78237..66b8164f30 100644
--- a/hw/ppc/spapr_events.c
+++ b/hw/ppc/spapr_events.c
@@ -700,6 +700,17 @@ static void event_scan(PowerPCCPU *cpu, sPAPRMachineState *spapr,
     rtas_st(rets, 0, RTAS_OUT_NO_ERRORS_FOUND);
 }
 
+void spapr_clear_pending_events(sPAPRMachineState *spapr)
+{
+    sPAPREventLogEntry *entry = NULL;
+
+    QTAILQ_FOREACH(entry, &spapr->pending_events, next) {
+        QTAILQ_REMOVE(&spapr->pending_events, entry, next);
+        g_free(entry->extended_log);
+        g_free(entry);
+    }
+}
+
 void spapr_events_init(sPAPRMachineState *spapr)
 {
     QTAILQ_INIT(&spapr->pending_events);
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 2a303a705c..5d161ec580 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -662,6 +662,7 @@ void spapr_cpu_parse_features(sPAPRMachineState *spapr);
 int spapr_hpt_shift_for_ramsize(uint64_t ramsize);
 void spapr_reallocate_hpt(sPAPRMachineState *spapr, int shift,
                           Error **errp);
+void spapr_clear_pending_events(sPAPRMachineState *spapr);
 
 /* CPU and LMB DRC release callbacks. */
 void spapr_core_release(DeviceState *dev);
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 44/55] spapr: reset DRCs after devices
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (42 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 43/55] hw/ppc: clear pending_events on machine reset Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 45/55] scripts/make-release: ship u-boot source as a tarball Michael Roth
                   ` (10 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Greg Kurz, David Gibson

From: Greg Kurz <groug@kaod.org>

A DRC with a pending unplug request releases its associated device at
machine reset time.

In the case of LMB, when all DRCs for a DIMM device have been reset,
the DIMM gets unplugged, causing guest memory to disappear. This may
be very confusing for anything still using this memory.

This is exactly what happens with vhost backends, and QEMU aborts
with:

qemu-system-ppc64: used ring relocated for ring 2
qemu-system-ppc64: qemu/hw/virtio/vhost.c:649: vhost_commit: Assertion
 `r >= 0' failed.

The issue is that each DRC registers a QEMU reset handler, and we
don't control the order in which these handlers are called (ie,
a LMB DRC will unplug a DIMM before the virtio device using the
memory on this DIMM could stop its vhost backend).

To avoid such situations, let's reset DRCs after all devices
have been reset.

Reported-by: Mallesh N. Koti <mallesh@linux.vnet.ibm.com>
Signed-off-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com>
Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
(cherry picked from commit 82512483940c756e2db1bd67ea91b02bc29c5e01)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 hw/ppc/spapr.c     | 21 +++++++++++++++++++++
 hw/ppc/spapr_drc.c |  7 -------
 2 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 954fd1a747..8630281d0e 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1393,6 +1393,19 @@ static void find_unknown_sysbus_device(SysBusDevice *sbdev, void *opaque)
     }
 }
 
+static int spapr_reset_drcs(Object *child, void *opaque)
+{
+    sPAPRDRConnector *drc =
+        (sPAPRDRConnector *) object_dynamic_cast(child,
+                                                 TYPE_SPAPR_DR_CONNECTOR);
+
+    if (drc) {
+        spapr_drc_reset(drc);
+    }
+
+    return 0;
+}
+
 static void ppc_spapr_reset(void)
 {
     MachineState *machine = MACHINE(qdev_get_machine());
@@ -1416,6 +1429,14 @@ static void ppc_spapr_reset(void)
     }
 
     qemu_devices_reset();
+
+    /* DRC reset may cause a device to be unplugged. This will cause troubles
+     * if this device is used by another device (eg, a running vhost backend
+     * will crash QEMU if the DIMM holding the vring goes away). To avoid such
+     * situations, we reset DRCs after all devices have been reset.
+     */
+    object_child_foreach_recursive(object_get_root(), spapr_reset_drcs, NULL);
+
     spapr_clear_pending_events(spapr);
 
     /*
diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c
index 50df361187..85f4e7d324 100644
--- a/hw/ppc/spapr_drc.c
+++ b/hw/ppc/spapr_drc.c
@@ -455,11 +455,6 @@ void spapr_drc_reset(sPAPRDRConnector *drc)
     }
 }
 
-static void drc_reset(void *opaque)
-{
-    spapr_drc_reset(SPAPR_DR_CONNECTOR(opaque));
-}
-
 bool spapr_drc_needed(void *opaque)
 {
     sPAPRDRConnector *drc = (sPAPRDRConnector *)opaque;
@@ -518,7 +513,6 @@ static void realize(DeviceState *d, Error **errp)
     }
     vmstate_register(DEVICE(drc), spapr_drc_index(drc), &vmstate_spapr_drc,
                      drc);
-    qemu_register_reset(drc_reset, drc);
     trace_spapr_drc_realize_complete(spapr_drc_index(drc));
 }
 
@@ -529,7 +523,6 @@ static void unrealize(DeviceState *d, Error **errp)
     char name[256];
 
     trace_spapr_drc_unrealize(spapr_drc_index(drc));
-    qemu_unregister_reset(drc_reset, drc);
     vmstate_unregister(DEVICE(drc), &vmstate_spapr_drc, drc);
     root_container = container_get(object_get_root(), DRC_CONTAINER_PATH);
     snprintf(name, sizeof(name), "%x", spapr_drc_index(drc));
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 45/55] scripts/make-release: ship u-boot source as a tarball
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (43 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 44/55] spapr: reset DRCs after devices Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 46/55] block/nfs: fix nfs_client_open for filesize greater than 1TB Michael Roth
                   ` (9 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-stable, Alexander Graf, Richard Henderson, Thomas Huth,
	Peter Maydell

The u-boot sources we ship currently cause problems with unpacking on
a case-insensitive filesystem due to path conflicts. This has been
fixed in upstream u-boot via commit 610eec7f, but since it is not
yet included in an official release we implement this approach as a
temporary workaround.

Once we move to a u-boot containing commit 610eec7f we should revert
this patch.

Cc: qemu-stable@nongnu.org
Cc: Alexander Graf <agraf@suse.de>
Cc: Richard Henderson <richard.henderson@linaro.org>
Cc: Thomas Huth <thuth@redhat.com>
Cc: Peter Maydell <peter.maydell@linaro.org>
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Message-id: 20171107205201.10207-1-mdroth@linux.vnet.ibm.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit d0dead3b6df7f6cd970ed02e8369ab8730aac9d3)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 scripts/make-release | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/scripts/make-release b/scripts/make-release
index fa6323fda8..3917df7142 100755
--- a/scripts/make-release
+++ b/scripts/make-release
@@ -20,6 +20,10 @@ git checkout "v${version}"
 git submodule update --init
 (cd roms/seabios && git describe --tags --long --dirty > .version)
 rm -rf .git roms/*/.git dtc/.git pixman/.git
+# FIXME: The following line is a workaround for avoiding filename collisions
+# when unpacking u-boot sources on case-insensitive filesystems. Once we
+# update to something with u-boot commit 610eec7f0 we can drop this line.
+tar cfj roms/u-boot.tar.bz2 -C roms u-boot && rm -rf roms/u-boot
 popd
 tar cfj ${destination}.tar.bz2 ${destination}
 rm -rf ${destination}
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 46/55] block/nfs: fix nfs_client_open for filesize greater than 1TB
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (44 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 45/55] scripts/make-release: ship u-boot source as a tarball Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 47/55] virtio-net: don't touch virtqueue if vm is stopped Michael Roth
                   ` (8 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Peter Lieven, Max Reitz

From: Peter Lieven <pl@kamp.de>

DIV_ROUND_UP(st.st_size, BDRV_SECTOR_SIZE) was overflowing ret (int) if
st.st_size is greater than 1TB.

Cc: qemu-stable@nongnu.org
Signed-off-by: Peter Lieven <pl@kamp.de>
Message-id: 1511798407-31129-1-git-send-email-pl@kamp.de
Signed-off-by: Max Reitz <mreitz@redhat.com>
(cherry picked from commit f1a7ff770f7d71ee7833ff019aac9d6cc3d13f71)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 block/nfs.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/block/nfs.c b/block/nfs.c
index bec16b72a6..addea26d56 100644
--- a/block/nfs.c
+++ b/block/nfs.c
@@ -1,7 +1,7 @@
 /*
  * QEMU Block driver for native access to files on NFS shares
  *
- * Copyright (c) 2014-2016 Peter Lieven <pl@kamp.de>
+ * Copyright (c) 2014-2017 Peter Lieven <pl@kamp.de>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -496,7 +496,7 @@ out:
 static int64_t nfs_client_open(NFSClient *client, QDict *options,
                                int flags, int open_flags, Error **errp)
 {
-    int ret = -EINVAL;
+    int64_t ret = -EINVAL;
     QemuOpts *opts = NULL;
     Error *local_err = NULL;
     struct stat st;
@@ -686,8 +686,7 @@ static QemuOptsList nfs_create_opts = {
 
 static int nfs_file_create(const char *url, QemuOpts *opts, Error **errp)
 {
-    int ret = 0;
-    int64_t total_size = 0;
+    int64_t ret, total_size;
     NFSClient *client = g_new0(NFSClient, 1);
     QDict *options = NULL;
 
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 47/55] virtio-net: don't touch virtqueue if vm is stopped
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (45 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 46/55] block/nfs: fix nfs_client_open for filesize greater than 1TB Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 48/55] nbd/server: CVE-2017-15119 Reject options larger than 32M Michael Roth
                   ` (7 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-stable, Jason Wang, Yuri Benditovich, Paolo Bonzini,
	Stefan Hajnoczi, Michael S . Tsirkin

From: Jason Wang <jasowang@redhat.com>

Guest state should not be touched if VM is stopped, unfortunately we
didn't check running state and tried to drain tx queue unconditionally
in virtio_net_set_status(). A crash was then noticed as a migration
destination when user type quit after virtqueue state is loaded but
before region cache is initialized. In this case,
virtio_net_drop_tx_queue_data() tries to access the uninitialized
region cache.

Fix this by only dropping tx queue data when vm is running.

Fixes: 283e2c2adcb80 ("net: virtio-net discards TX data after link down")
Cc: Yuri Benditovich <yuri.benditovich@daynix.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Stefan Hajnoczi <stefanha@redhat.com>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: qemu-stable@nongnu.org
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
(cherry picked from commit 70e53e6e4da3db4b2c31981191753a7e974936d0)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 hw/net/virtio-net.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 148071a396..fbc5e1bd73 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -288,7 +288,8 @@ static void virtio_net_set_status(struct VirtIODevice *vdev, uint8_t status)
                 qemu_bh_cancel(q->tx_bh);
             }
             if ((n->status & VIRTIO_NET_S_LINK_UP) == 0 &&
-                (queue_status & VIRTIO_CONFIG_S_DRIVER_OK)) {
+                (queue_status & VIRTIO_CONFIG_S_DRIVER_OK) &&
+                vdev->vm_running) {
                 /* if tx is waiting we are likely have some packets in tx queue
                  * and disabled notification */
                 q->tx_waiting = 0;
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 48/55] nbd/server: CVE-2017-15119 Reject options larger than 32M
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (46 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 47/55] virtio-net: don't touch virtqueue if vm is stopped Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 49/55] nbd/server: CVE-2017-15118 Stack smash on large export name Michael Roth
                   ` (6 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Eric Blake

From: Eric Blake <eblake@redhat.com>

The NBD spec gives us permission to abruptly disconnect on clients
that send outrageously large option requests, rather than having
to spend the time reading to the end of the option.  No real
option request requires that much data anyways; and meanwhile, we
already have the practice of abruptly dropping the connection on
any client that sends NBD_CMD_WRITE with a payload larger than 32M.

For comparison, nbdkit drops the connection on any request with
more than 4096 bytes; however, that limit is probably too low
(as the NBD spec states an export name can theoretically be up
to 4096 bytes, which means a valid NBD_OPT_INFO could be even
longer) - even if qemu doesn't permit exports longer than 256
bytes.

It could be argued that a malicious client trying to get us to
read nearly 4G of data on a bad request is a form of denial of
service.  In particular, if the server requires TLS, but a client
that does not know the TLS credentials sends any option (other
than NBD_OPT_STARTTLS or NBD_OPT_EXPORT_NAME) with a stated
payload of nearly 4G, then the server was keeping the connection
alive trying to read all the payload, tying up resources that it
would rather be spending on a client that can get past the TLS
handshake.  Hence, this warranted a CVE.

Present since at least 2.5 when handling known options, and made
worse in 2.6 when fixing support for NBD_FLAG_C_FIXED_NEWSTYLE
to handle unknown options.

CC: qemu-stable@nongnu.org
Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit fdad35ef6c5839d50dfc14073364ac893afebc30)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 nbd/server.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/nbd/server.c b/nbd/server.c
index 993ade30bb..b93cb88911 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -661,6 +661,12 @@ static int nbd_negotiate_options(NBDClient *client, uint16_t myflags,
         }
         length = be32_to_cpu(length);
 
+        if (length > NBD_MAX_BUFFER_SIZE) {
+            error_setg(errp, "len (%" PRIu32" ) is larger than max len (%u)",
+                       length, NBD_MAX_BUFFER_SIZE);
+            return -EINVAL;
+        }
+
         trace_nbd_negotiate_options_check_option(option,
                                                  nbd_opt_lookup(option));
         if (client->tlscreds &&
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 49/55] nbd/server: CVE-2017-15118 Stack smash on large export name
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (47 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 48/55] nbd/server: CVE-2017-15119 Reject options larger than 32M Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 50/55] vhost: fix error check in vhost_verify_ring_mappings() Michael Roth
                   ` (5 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Eric Blake

From: Eric Blake <eblake@redhat.com>

Introduced in commit f37708f6b8 (2.10).  The NBD spec says a client
can request export names up to 4096 bytes in length, even though
they should not expect success on names longer than 256.  However,
qemu hard-codes the limit of 256, and fails to filter out a client
that probes for a longer name; the result is a stack smash that can
potentially give an attacker arbitrary control over the qemu
process.

The smash can be easily demonstrated with this client:
$ qemu-io f raw nbd://localhost:10809/$(printf %3000d 1 | tr ' ' a)

If the qemu NBD server binary (whether the standalone qemu-nbd, or
the builtin server of QMP nbd-server-start) was compiled with
-fstack-protector-strong, the ability to exploit the stack smash
into arbitrary execution is a lot more difficult (but still
theoretically possible to a determined attacker, perhaps in
combination with other CVEs).  Still, crashing a running qemu (and
losing the VM) is bad enough, even if the attacker did not obtain
full execution control.

CC: qemu-stable@nongnu.org
Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit 51ae4f8455c9e32c54770c4ebc25bf86a8128183)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 nbd/server.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/nbd/server.c b/nbd/server.c
index b93cb88911..56aed3a735 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -393,6 +393,10 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint32_t length,
         msg = "name length is incorrect";
         goto invalid;
     }
+    if (namelen >= sizeof(name)) {
+        msg = "name too long for qemu";
+        goto invalid;
+    }
     if (nbd_read(client->ioc, name, namelen, errp) < 0) {
         return -EIO;
     }
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 50/55] vhost: fix error check in vhost_verify_ring_mappings()
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (48 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 49/55] nbd/server: CVE-2017-15118 Stack smash on large export name Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 51/55] nbd/server: fix nbd_negotiate_handle_info Michael Roth
                   ` (4 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Greg Kurz, Michael S . Tsirkin

From: Greg Kurz <groug@kaod.org>

Since commit f1f9e6c5 "vhost: adapt vhost_verify_ring_mappings() to
virtio 1 ring layout", we check the mapping of each part (descriptor
table, available ring and used ring) of each virtqueue separately.

The checking of a part is done by the vhost_verify_ring_part_mapping()
function: it returns either 0 on success or a negative errno if the
part cannot be mapped at the same place.

Unfortunately, the vhost_verify_ring_mappings() function checks its
return value the other way round. It means that we either:
- only verify the descriptor table of the first virtqueue, and if it
  is valid we ignore all the other mappings
- or ignore all broken mappings until we reach a valid one

ie, we only raise an error if all mappings are broken, and we consider
all mappings are valid otherwise (false success), which is obviously
wrong.

This patch ensures that vhost_verify_ring_mappings() only returns
success if ALL mappings are okay.

Reported-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit 2fe45ec3bffbd3a26f2ed39f60bab0ca5217d8f6)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 hw/virtio/vhost.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 76f6e1fcaa..fd6f4a878b 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -492,21 +492,21 @@ static int vhost_verify_ring_mappings(struct vhost_dev *dev,
         j = 0;
         r = vhost_verify_ring_part_mapping(dev, vq->desc, vq->desc_phys,
                                            vq->desc_size, start_addr, size);
-        if (!r) {
+        if (r) {
             break;
         }
 
         j++;
         r = vhost_verify_ring_part_mapping(dev, vq->avail, vq->avail_phys,
                                            vq->avail_size, start_addr, size);
-        if (!r) {
+        if (r) {
             break;
         }
 
         j++;
         r = vhost_verify_ring_part_mapping(dev, vq->used, vq->used_phys,
                                            vq->used_size, start_addr, size);
-        if (!r) {
+        if (r) {
             break;
         }
     }
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 51/55] nbd/server: fix nbd_negotiate_handle_info
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (49 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 50/55] vhost: fix error check in vhost_verify_ring_mappings() Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 52/55] nbd-client: Refuse read-only client with BDRV_O_RDWR Michael Roth
                   ` (3 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Vladimir Sementsov-Ogievskiy, Eric Blake

From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>

namelen should be here, length is unrelated, and always 0 at this
point.  Broken in introduction in commit f37708f6, but mostly
harmless (replying with '' as the name does not violate protocol,
and does not confuse qemu as the nbd client since our implementation
does not ask for the name; but might confuse some other client that
does ask for the name especially if the default export is different
than the export name being queried).

Adding an assert makes it obvious that we are not skipping any bytes
in the client's message, as well as making it obvious that we were
using the wrong variable.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
CC: qemu-stable@nongnu.org
Message-Id: <20171101154204.27146-1-vsementsov@virtuozzo.com>
[eblake: improve commit message, squash in assert addition]
Signed-off-by: Eric Blake <eblake@redhat.com>

(cherry picked from commit 46321d6b5f8c880932a6b3d07bd0ff6f892e665c)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 nbd/server.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/nbd/server.c b/nbd/server.c
index 56aed3a735..5042cc4786 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -434,6 +434,7 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint32_t length,
             break;
         }
     }
+    assert(length == 0);
 
     exp = nbd_export_find(name);
     if (!exp) {
@@ -444,7 +445,7 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint32_t length,
 
     /* Don't bother sending NBD_INFO_NAME unless client requested it */
     if (sendname) {
-        rc = nbd_negotiate_send_info(client, opt, NBD_INFO_NAME, length, name,
+        rc = nbd_negotiate_send_info(client, opt, NBD_INFO_NAME, namelen, name,
                                      errp);
         if (rc < 0) {
             return rc;
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 52/55] nbd-client: Refuse read-only client with BDRV_O_RDWR
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (50 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 51/55] nbd/server: fix nbd_negotiate_handle_info Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 53/55] nbd/client: Don't hard-disconnect on ESHUTDOWN from server Michael Roth
                   ` (2 subsequent siblings)
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Eric Blake

From: Eric Blake <eblake@redhat.com>

The NBD spec says that clients should not try to write/trim to
an export advertised as read-only by the server.  But we failed
to check that, and would allow the block layer to use NBD with
BDRV_O_RDWR even when the server is read-only, which meant we
were depending on the server sending a proper EPERM failure for
various commands, and also exposes a leaky abstraction: using
qemu-io in read-write mode would succeed on 'w -z 0 0' because
of local short-circuiting logic, but 'w 0 0' would send a
request over the wire (where it then depends on the server, and
fails at least for qemu-nbd but might pass for other NBD
implementations).

With this patch, a client MUST request read-only mode to access
a server that is doing a read-only export, or else it will get
a message like:

can't open device nbd://localhost:10809/foo: request for write access conflicts with read-only export

It is no longer possible to even attempt writes over the wire
(including the corner case of 0-length writes), because the block
layer enforces the explicit read-only request; this matches the
behavior of qcow2 when backed by a read-only POSIX file.

Fix several iotests to comply with the new behavior (since
qemu-nbd of an internal snapshot, as well as nbd-server-add over QMP,
default to a read-only export, we must tell blockdev-add/qemu-io to
set up a read-only client).

CC: qemu-stable@nongnu.org
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <20171108215703.9295-3-eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
(cherry picked from commit 1104d83c726d2b20f9cec7b99ab3570a2fdbd46d)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 block/nbd-client.c     | 9 +++++++++
 tests/qemu-iotests/058 | 8 ++++----
 tests/qemu-iotests/140 | 4 ++--
 tests/qemu-iotests/147 | 1 +
 4 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/block/nbd-client.c b/block/nbd-client.c
index ea728fffc8..db9d41eb04 100644
--- a/block/nbd-client.c
+++ b/block/nbd-client.c
@@ -256,6 +256,7 @@ int nbd_client_co_pwritev(BlockDriverState *bs, uint64_t offset,
     NBDReply reply;
     ssize_t ret;
 
+    assert(!(client->info.flags & NBD_FLAG_READ_ONLY));
     if (flags & BDRV_REQ_FUA) {
         assert(client->info.flags & NBD_FLAG_SEND_FUA);
         request.flags |= NBD_CMD_FLAG_FUA;
@@ -284,6 +285,7 @@ int nbd_client_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
     };
     NBDReply reply;
 
+    assert(!(client->info.flags & NBD_FLAG_READ_ONLY));
     if (!(client->info.flags & NBD_FLAG_SEND_WRITE_ZEROES)) {
         return -ENOTSUP;
     }
@@ -339,6 +341,7 @@ int nbd_client_co_pdiscard(BlockDriverState *bs, int64_t offset, int bytes)
     NBDReply reply;
     ssize_t ret;
 
+    assert(!(client->info.flags & NBD_FLAG_READ_ONLY));
     if (!(client->info.flags & NBD_FLAG_SEND_TRIM)) {
         return 0;
     }
@@ -403,6 +406,12 @@ int nbd_client_init(BlockDriverState *bs,
         logout("Failed to negotiate with the NBD server\n");
         return ret;
     }
+    if (client->info.flags & NBD_FLAG_READ_ONLY &&
+        !bdrv_is_read_only(bs)) {
+        error_setg(errp,
+                   "request for write access conflicts with read-only export");
+        return -EACCES;
+    }
     if (client->info.flags & NBD_FLAG_SEND_FUA) {
         bs->supported_write_flags = BDRV_REQ_FUA;
         bs->supported_zero_flags |= BDRV_REQ_FUA;
diff --git a/tests/qemu-iotests/058 b/tests/qemu-iotests/058
index 2253c6a6d1..5eb8784669 100755
--- a/tests/qemu-iotests/058
+++ b/tests/qemu-iotests/058
@@ -117,15 +117,15 @@ _export_nbd_snapshot sn1
 
 echo
 echo "== verifying the exported snapshot with patterns, method 1 =="
-$QEMU_IO_NBD -c 'read -P 0xa 0x1000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io
-$QEMU_IO_NBD -c 'read -P 0xb 0x2000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io
+$QEMU_IO_NBD -r -c 'read -P 0xa 0x1000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io
+$QEMU_IO_NBD -r -c 'read -P 0xb 0x2000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io
 
 _export_nbd_snapshot1 sn1
 
 echo
 echo "== verifying the exported snapshot with patterns, method 2 =="
-$QEMU_IO_NBD -c 'read -P 0xa 0x1000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io
-$QEMU_IO_NBD -c 'read -P 0xb 0x2000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io
+$QEMU_IO_NBD -r -c 'read -P 0xa 0x1000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io
+$QEMU_IO_NBD -r -c 'read -P 0xb 0x2000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io
 
 $QEMU_IMG convert "$TEST_IMG" -l sn1 -O qcow2 "$converted_image"
 
diff --git a/tests/qemu-iotests/140 b/tests/qemu-iotests/140
index f89d0d6789..a8fc95145c 100755
--- a/tests/qemu-iotests/140
+++ b/tests/qemu-iotests/140
@@ -78,7 +78,7 @@ _send_qemu_cmd $QEMU_HANDLE \
        'arguments': { 'device': 'drv' }}" \
     'return'
 
-$QEMU_IO_PROG -f raw -c 'read -P 42 0 64k' \
+$QEMU_IO_PROG -f raw -r -c 'read -P 42 0 64k' \
     "nbd+unix:///drv?socket=$TEST_DIR/nbd" 2>&1 \
     | _filter_qemu_io | _filter_nbd
 
@@ -87,7 +87,7 @@ _send_qemu_cmd $QEMU_HANDLE \
        'arguments': { 'device': 'drv' }}" \
     'return'
 
-$QEMU_IO_PROG -f raw -c close \
+$QEMU_IO_PROG -f raw -r -c close \
     "nbd+unix:///drv?socket=$TEST_DIR/nbd" 2>&1 \
     | _filter_qemu_io | _filter_nbd
 
diff --git a/tests/qemu-iotests/147 b/tests/qemu-iotests/147
index db34838cd0..90f40ed245 100755
--- a/tests/qemu-iotests/147
+++ b/tests/qemu-iotests/147
@@ -43,6 +43,7 @@ class NBDBlockdevAddBase(iotests.QMPTestCase):
                     'driver': 'raw',
                     'file': {
                         'driver': 'nbd',
+                        'read-only': True,
                         'server': address
                     } }
         if export is not None:
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 53/55] nbd/client: Don't hard-disconnect on ESHUTDOWN from server
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (51 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 52/55] nbd-client: Refuse read-only client with BDRV_O_RDWR Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 54/55] vga: drop line_offset variable Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 55/55] vga: handle cirrus vbe mode wraparounds Michael Roth
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Eric Blake

From: Eric Blake <eblake@redhat.com>

The NBD spec says that a server may fail any transmission request
with ESHUTDOWN when it is apparent that no further request from
the client can be successfully honored.  The client is supposed
to then initiate a soft shutdown (wait for all remaining in-flight
requests to be answered, then send NBD_CMD_DISC).  However, since
qemu's server never uses ESHUTDOWN errors, this code was mostly
untested since its introduction in commit b6f5d3b5.

More recently, I learned that nbdkit as the NBD server is able to
send ESHUTDOWN errors, so I finally tested this code, and noticed
that our client was special-casing ESHUTDOWN to cause a hard
shutdown (immediate disconnect, with no NBD_CMD_DISC), but only
if the server sends this error as a simple reply.  Further
investigation found that commit d2febedb introduced a regression
where structured replies behave differently than simple replies -
but that the structured reply behavior is more in line with the
spec (even if we still lack code in nbd-client.c to properly quit
sending further requests).  So this patch reverts the portion of
b6f5d3b5 that introduced an improper hard-disconnect special-case
at the lower level, and leaves the future enhancement of a nicer
soft-disconnect at the higher level for another day.

CC: qemu-stable@nongnu.org
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <20171113194857.13933-1-eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
(cherry picked from commit 01b05c66a3616d5a4adc39fc90962e9efaf791d1)
 Conflicts:
	nbd/client.c
*drop dep on d2febedb
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 nbd/client.c | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/nbd/client.c b/nbd/client.c
index 4caff77119..f04e95542f 100644
--- a/nbd/client.c
+++ b/nbd/client.c
@@ -945,12 +945,6 @@ ssize_t nbd_receive_reply(QIOChannel *ioc, NBDReply *reply, Error **errp)
     reply->handle = ldq_be_p(buf + 8);
 
     reply->error = nbd_errno_to_system_errno(reply->error);
-
-    if (reply->error == ESHUTDOWN) {
-        /* This works even on mingw which lacks a native ESHUTDOWN */
-        error_setg(errp, "server shutting down");
-        return -EINVAL;
-    }
     trace_nbd_receive_reply(magic, reply->error, reply->handle);
 
     if (magic != NBD_REPLY_MAGIC) {
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 54/55] vga: drop line_offset variable
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (52 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 53/55] nbd/client: Don't hard-disconnect on ESHUTDOWN from server Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 55/55] vga: handle cirrus vbe mode wraparounds Michael Roth
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Gerd Hoffmann

From: Gerd Hoffmann <kraxel@redhat.com>

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 362f811793ff6cb4d209ab61d76cc4f841bb5e46)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 hw/display/vga.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/hw/display/vga.c b/hw/display/vga.c
index 497c8236d0..895e95c3f4 100644
--- a/hw/display/vga.c
+++ b/hw/display/vga.c
@@ -1464,7 +1464,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
 {
     DisplaySurface *surface = qemu_console_surface(s->con);
     int y1, y, update, linesize, y_start, double_scan, mask, depth;
-    int width, height, shift_control, line_offset, bwidth, bits;
+    int width, height, shift_control, bwidth, bits;
     ram_addr_t page0, page1;
     DirtyBitmapSnapshot *snap = NULL;
     int disp_width, multi_scan, multi_run;
@@ -1614,7 +1614,6 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
         s->cursor_invalidate(s);
     }
 
-    line_offset = s->line_offset;
 #if 0
     printf("w=%d h=%d v=%d line_offset=%d cr[0x09]=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=0x%02x\n",
            width, height, v, line_offset, s->cr[9], s->cr[VGA_CRTC_MODE],
@@ -1629,7 +1628,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
 
     if (!full_update) {
         ram_addr_t region_start = addr1;
-        ram_addr_t region_end = addr1 + line_offset * height;
+        ram_addr_t region_end = addr1 + s->line_offset * height;
         vga_sync_dirty_bitmap(s);
         if (s->line_compare < height) {
             /* split screen mode */
@@ -1681,7 +1680,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
         if (!multi_run) {
             mask = (s->cr[VGA_CRTC_MODE] & 3) ^ 3;
             if ((y1 & mask) == mask)
-                addr1 += line_offset;
+                addr1 += s->line_offset;
             y1++;
             multi_run = multi_scan;
         } else {
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 55/55] vga: handle cirrus vbe mode wraparounds.
  2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
                   ` (53 preceding siblings ...)
  2017-12-06 19:16 ` [Qemu-devel] [PATCH 54/55] vga: drop line_offset variable Michael Roth
@ 2017-12-06 19:16 ` Michael Roth
  54 siblings, 0 replies; 56+ messages in thread
From: Michael Roth @ 2017-12-06 19:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-stable, Gerd Hoffmann, P J P

From: Gerd Hoffmann <kraxel@redhat.com>

Commit "3d90c62548 vga: stop passing pointers to vga_draw_line*
functions" is incomplete.  It doesn't handle the case that the vga
rendering code tries to create a shared surface, i.e. a pixman image
backed by vga video memory.  That can not work in case the guest display
wraps from end of video memory to the start.  So force shadowing in that
case.  Also adjust the snapshot region calculation.

Can trigger with cirrus only, when programming vbe modes using the bochs
api (stdvga, also qxl and virtio-vga in vga compat mode) wrap arounds
can't happen.

Fixes: CVE-2017-13672
Fixes: 3d90c6254863693a6b13d918d2b8682e08bbc681
Cc: P J P <ppandit@redhat.com>
Reported-by: David Buchanan <d@vidbuchanan.co.uk>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Message-id: 20171010141323.14049-3-kraxel@redhat.com
(cherry picked from commit 28f77de26a4f9995458ddeb9d34bb06c0193bdc9)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 hw/display/vga.c | 28 +++++++++++++++++++++-------
 1 file changed, 21 insertions(+), 7 deletions(-)

diff --git a/hw/display/vga.c b/hw/display/vga.c
index 895e95c3f4..06ca3daa4c 100644
--- a/hw/display/vga.c
+++ b/hw/display/vga.c
@@ -1465,13 +1465,13 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
     DisplaySurface *surface = qemu_console_surface(s->con);
     int y1, y, update, linesize, y_start, double_scan, mask, depth;
     int width, height, shift_control, bwidth, bits;
-    ram_addr_t page0, page1;
+    ram_addr_t page0, page1, region_start, region_end;
     DirtyBitmapSnapshot *snap = NULL;
     int disp_width, multi_scan, multi_run;
     uint8_t *d;
     uint32_t v, addr1, addr;
     vga_draw_line_func *vga_draw_line = NULL;
-    bool share_surface;
+    bool share_surface, force_shadow = false;
     pixman_format_code_t format;
 #ifdef HOST_WORDS_BIGENDIAN
     bool byteswap = !s->big_endian_fb;
@@ -1484,6 +1484,15 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
     s->get_resolution(s, &width, &height);
     disp_width = width;
 
+    region_start = (s->start_addr * 4);
+    region_end = region_start + s->line_offset * height;
+    if (region_end > s->vbe_size) {
+        /* wraps around (can happen with cirrus vbe modes) */
+        region_start = 0;
+        region_end = s->vbe_size;
+        force_shadow = true;
+    }
+
     shift_control = (s->gr[VGA_GFX_MODE] >> 5) & 3;
     double_scan = (s->cr[VGA_CRTC_MAX_SCAN] >> 7);
     if (shift_control != 1) {
@@ -1523,7 +1532,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
     format = qemu_default_pixman_format(depth, !byteswap);
     if (format) {
         share_surface = dpy_gfx_check_format(s->con, format)
-            && !s->force_shadow;
+            && !s->force_shadow && !force_shadow;
     } else {
         share_surface = false;
     }
@@ -1627,8 +1636,6 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
     y1 = 0;
 
     if (!full_update) {
-        ram_addr_t region_start = addr1;
-        ram_addr_t region_end = addr1 + s->line_offset * height;
         vga_sync_dirty_bitmap(s);
         if (s->line_compare < height) {
             /* split screen mode */
@@ -1651,10 +1658,17 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
             addr = (addr & ~0x8000) | ((y1 & 2) << 14);
         }
         update = full_update;
-        page0 = addr;
-        page1 = addr + bwidth - 1;
+        page0 = addr & s->vbe_size_mask;
+        page1 = (addr + bwidth - 1) & s->vbe_size_mask;
         if (full_update) {
             update = 1;
+        } else if (page1 < page0) {
+            /* scanline wraps from end of video memory to the start */
+            assert(force_shadow);
+            update = memory_region_snapshot_get_dirty(&s->vram, snap,
+                                                      page0, 0);
+            update |= memory_region_snapshot_get_dirty(&s->vram, snap,
+                                                       page1, 0);
         } else {
             update = memory_region_snapshot_get_dirty(&s->vram, snap,
                                                       page0, page1 - page0);
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 56+ messages in thread

end of thread, other threads:[~2017-12-06 19:18 UTC | newest]

Thread overview: 56+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-12-06 19:15 [Qemu-devel] [PATCH 00/55] Patch Round-up for stable 2.10.2, freeze on 2017-12-13 Michael Roth
2017-12-06 19:15 ` [Qemu-devel] [PATCH 01/55] hw/ppc: CAS reset on early device hotplug Michael Roth
2017-12-06 19:15 ` [Qemu-devel] [PATCH 02/55] hw/usb/bus: Remove bad object_unparent() from usb_try_create_simple() Michael Roth
2017-12-06 19:15 ` [Qemu-devel] [PATCH 03/55] block/mirror: check backing in bdrv_mirror_top_flush Michael Roth
2017-12-06 19:15 ` [Qemu-devel] [PATCH 04/55] kvmclock: use the updated system_timer_msr Michael Roth
2017-12-06 19:15 ` [Qemu-devel] [PATCH 05/55] block: Perform copy-on-read in loop Michael Roth
2017-12-06 19:15 ` [Qemu-devel] [PATCH 06/55] exec: Explicitly export target AS from address_space_translate_internal Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 07/55] memory: Open code FlatView rendering Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 08/55] memory: Move FlatView allocation to a helper Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 09/55] memory: Move AddressSpaceDispatch from AddressSpace to FlatView Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 10/55] memory: Remove AddressSpace pointer from AddressSpaceDispatch Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 11/55] memory: avoid "resurrection" of dead FlatViews Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 12/55] memory: Switch memory from using AddressSpace to FlatView Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 13/55] memory: Cleanup after switching " Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 14/55] memory: Rename mem_begin/mem_commit/mem_add helpers Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 15/55] memory: Store physical root MR in FlatView Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 16/55] memory: Alloc dispatch tree where topology is generared Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 17/55] memory: Move address_space_update_ioeventfds Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 18/55] memory: Share FlatView's and dispatch trees between address spaces Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 19/55] memory: Do not allocate FlatView in address_space_init Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 20/55] memory: Get rid of address_space_init_shareable Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 21/55] memory: Create FlatView directly Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 22/55] memory: trace FlatView creation and destruction Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 23/55] memory: seek FlatView sharing candidates among children subregions Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 24/55] memory: Share special empty FlatView Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 25/55] exec: add page_mask for flatview_do_translate Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 26/55] exec: simplify address_space_get_iotlb_entry Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 27/55] memory: fix off-by-one error in memory_region_notify_one() Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 28/55] hw/sd: fix out-of-bounds check for multi block reads Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 29/55] qcow2: Fix unaligned preallocated truncation Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 30/55] qcow2: Always execute preallocate() in a coroutine Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 31/55] iotests: Add cluster_size=64k to 125 Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 32/55] nios2: define tcg_env Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 33/55] io: monitor encoutput buffer size from websocket GSource Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 34/55] ppc: fix setting of compat mode Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 35/55] translate.c: Fix usermode big-endian AArch32 LDREXD and STREXD Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 36/55] hw/intc/arm_gicv3_its: Don't abort on table save failure Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 37/55] net/socket: fix coverity issue Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 38/55] net: fix check for number of parameters to -netdev socket Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 39/55] nbd/client: Use error_prepend() correctly Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 40/55] util/stats64: Fix min/max comparisons Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 41/55] virtio: Add queue interface to restore avail index from vring used index Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 42/55] vhost: restore avail index from vring used index on disconnection Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 43/55] hw/ppc: clear pending_events on machine reset Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 44/55] spapr: reset DRCs after devices Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 45/55] scripts/make-release: ship u-boot source as a tarball Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 46/55] block/nfs: fix nfs_client_open for filesize greater than 1TB Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 47/55] virtio-net: don't touch virtqueue if vm is stopped Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 48/55] nbd/server: CVE-2017-15119 Reject options larger than 32M Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 49/55] nbd/server: CVE-2017-15118 Stack smash on large export name Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 50/55] vhost: fix error check in vhost_verify_ring_mappings() Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 51/55] nbd/server: fix nbd_negotiate_handle_info Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 52/55] nbd-client: Refuse read-only client with BDRV_O_RDWR Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 53/55] nbd/client: Don't hard-disconnect on ESHUTDOWN from server Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 54/55] vga: drop line_offset variable Michael Roth
2017-12-06 19:16 ` [Qemu-devel] [PATCH 55/55] vga: handle cirrus vbe mode wraparounds Michael Roth

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.