diff options
| author | Peter Maydell <peter.maydell@linaro.org> | 2019-01-11 15:46:09 +0000 |
|---|---|---|
| committer | Peter Maydell <peter.maydell@linaro.org> | 2019-01-11 15:46:09 +0000 |
| commit | 15bede554162dda822cd762c689edb6fa32b6e3b (patch) | |
| tree | ba397197336b06e020d9c5b403471e9d82d19c63 /memory.c | |
| parent | e53f7796fbe71a5c7c24ffebf04b4aa9a759da36 (diff) | |
| parent | 7d37435bd5801bb49e1c4b550fedd1c5fe143131 (diff) | |
| download | focaccia-qemu-15bede554162dda822cd762c689edb6fa32b6e3b.tar.gz focaccia-qemu-15bede554162dda822cd762c689edb6fa32b6e3b.zip | |
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
* HAX support for Linux hosts (Alejandro)
* esp bugfixes (Guenter)
* Windows build cleanup (Marc-André)
* checkpatch logic improvements (Paolo)
* coalesced range bugfix (Paolo)
* switch testsuite to TAP (Paolo)
* QTAILQ rewrite (Paolo)
* block/iscsi.c cancellation fixes (Stefan)
* improve selection of the default accelerator (Thomas)
# gpg: Signature made Fri 11 Jan 2019 14:47:40 GMT
# gpg: using RSA key BFFBD25F78C7AE83
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>"
# gpg: aka "Paolo Bonzini <pbonzini@redhat.com>"
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1
# Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83
* remotes/bonzini/tags/for-upstream: (34 commits)
avoid TABs in files that only contain a few
remove space-tab sequences
scripts: add script to convert multiline comments into 4-line format
hw/watchdog/wdt_i6300esb: remove a unnecessary comment
checkpatch: warn about qemu/queue.h head structs that are not typedef-ed
qemu/queue.h: simplify reverse access to QTAILQ
qemu/queue.h: reimplement QTAILQ without pointer-to-pointers
qemu/queue.h: remove Q_TAILQ_{HEAD,ENTRY}
qemu/queue.h: typedef QTAILQ heads
qemu/queue.h: leave head structs anonymous unless necessary
vfio: make vfio_address_spaces static
qemu/queue.h: do not access tqe_prev directly
test: replace gtester with a TAP driver
test: execute g_test_run when tests are skipped
qga: drop < Vista compatibility
build-sys: build with Vista API by default
build-sys: move windows defines in osdep.h header
build-sys: don't include windows.h, osdep.h does it
scsi: esp: Defer command completion until previous interrupts have been handled
esp-pci: Fix status register write erase control
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'memory.c')
| -rw-r--r-- | memory.c | 97 |
1 files changed, 60 insertions, 37 deletions
diff --git a/memory.c b/memory.c index d14c6dec1d..61d66e4441 100644 --- a/memory.c +++ b/memory.c @@ -39,7 +39,7 @@ static bool memory_region_update_pending; static bool ioeventfd_update_pending; static bool global_dirty_log = false; -static QTAILQ_HEAD(memory_listeners, MemoryListener) memory_listeners +static QTAILQ_HEAD(, MemoryListener) memory_listeners = QTAILQ_HEAD_INITIALIZER(memory_listeners); static QTAILQ_HEAD(, AddressSpace) address_spaces @@ -113,8 +113,7 @@ enum ListenerDirection { Forward, Reverse }; } \ break; \ case Reverse: \ - QTAILQ_FOREACH_REVERSE(_listener, &memory_listeners, \ - memory_listeners, link) { \ + QTAILQ_FOREACH_REVERSE(_listener, &memory_listeners, link) { \ if (_listener->_callback) { \ _listener->_callback(_listener, ##_args); \ } \ @@ -128,19 +127,17 @@ enum ListenerDirection { Forward, Reverse }; #define MEMORY_LISTENER_CALL(_as, _callback, _direction, _section, _args...) \ do { \ MemoryListener *_listener; \ - struct memory_listeners_as *list = &(_as)->listeners; \ \ switch (_direction) { \ case Forward: \ - QTAILQ_FOREACH(_listener, list, link_as) { \ + QTAILQ_FOREACH(_listener, &(_as)->listeners, link_as) { \ if (_listener->_callback) { \ _listener->_callback(_listener, _section, ##_args); \ } \ } \ break; \ case Reverse: \ - QTAILQ_FOREACH_REVERSE(_listener, list, memory_listeners_as, \ - link_as) { \ + QTAILQ_FOREACH_REVERSE(_listener, &(_as)->listeners, link_as) { \ if (_listener->_callback) { \ _listener->_callback(_listener, _section, ##_args); \ } \ @@ -217,6 +214,7 @@ struct FlatRange { bool romd_mode; bool readonly; bool nonvolatile; + int has_coalesced_range; }; #define FOR_EACH_FLAT_RANGE(var, view) \ @@ -650,6 +648,7 @@ static void render_memory_region(FlatView *view, fr.romd_mode = mr->romd_mode; fr.readonly = readonly; fr.nonvolatile = nonvolatile; + fr.has_coalesced_range = 0; /* Render the region itself into any gaps left by the current view. */ for (i = 0; i < view->nr && int128_nz(remain); ++i) { @@ -850,6 +849,49 @@ static void address_space_update_ioeventfds(AddressSpace *as) flatview_unref(view); } +static void flat_range_coalesced_io_del(FlatRange *fr, AddressSpace *as) +{ + if (!fr->has_coalesced_range) { + return; + } + + if (--fr->has_coalesced_range > 0) { + return; + } + + MEMORY_LISTENER_UPDATE_REGION(fr, as, Reverse, coalesced_io_del, + int128_get64(fr->addr.start), + int128_get64(fr->addr.size)); +} + +static void flat_range_coalesced_io_add(FlatRange *fr, AddressSpace *as) +{ + MemoryRegion *mr = fr->mr; + CoalescedMemoryRange *cmr; + AddrRange tmp; + + if (QTAILQ_EMPTY(&mr->coalesced)) { + return; + } + + if (fr->has_coalesced_range++) { + return; + } + + QTAILQ_FOREACH(cmr, &mr->coalesced, link) { + tmp = addrrange_shift(cmr->addr, + int128_sub(fr->addr.start, + int128_make64(fr->offset_in_region))); + if (!addrrange_intersects(tmp, fr->addr)) { + continue; + } + tmp = addrrange_intersection(tmp, fr->addr); + MEMORY_LISTENER_UPDATE_REGION(fr, as, Forward, coalesced_io_add, + int128_get64(tmp.start), + int128_get64(tmp.size)); + } +} + static void address_space_update_topology_pass(AddressSpace *as, const FlatView *old_view, const FlatView *new_view, @@ -882,6 +924,7 @@ static void address_space_update_topology_pass(AddressSpace *as, /* In old but not in new, or in both but attributes changed. */ if (!adding) { + flat_range_coalesced_io_del(frold, as); MEMORY_LISTENER_UPDATE_REGION(frold, as, Reverse, region_del); } @@ -889,7 +932,9 @@ static void address_space_update_topology_pass(AddressSpace *as, } else if (frold && frnew && flatrange_equal(frold, frnew)) { /* In both and unchanged (except logging may have changed) */ - if (adding) { + if (!adding) { + flat_range_coalesced_io_del(frold, as); + } else { MEMORY_LISTENER_UPDATE_REGION(frnew, as, Forward, region_nop); if (frnew->dirty_log_mask & ~frold->dirty_log_mask) { MEMORY_LISTENER_UPDATE_REGION(frnew, as, Forward, log_start, @@ -901,6 +946,7 @@ static void address_space_update_topology_pass(AddressSpace *as, frold->dirty_log_mask, frnew->dirty_log_mask); } + flat_range_coalesced_io_add(frnew, as); } ++iold; @@ -910,6 +956,7 @@ static void address_space_update_topology_pass(AddressSpace *as, if (adding) { MEMORY_LISTENER_UPDATE_REGION(frnew, as, Forward, region_add); + flat_range_coalesced_io_add(frnew, as); } ++inew; @@ -2136,34 +2183,12 @@ static void memory_region_update_coalesced_range_as(MemoryRegion *mr, AddressSpa { FlatView *view; FlatRange *fr; - CoalescedMemoryRange *cmr; - AddrRange tmp; - MemoryRegionSection section; view = address_space_get_flatview(as); FOR_EACH_FLAT_RANGE(fr, view) { if (fr->mr == mr) { - section = (MemoryRegionSection) { - .fv = view, - .offset_within_address_space = int128_get64(fr->addr.start), - .size = fr->addr.size, - }; - - MEMORY_LISTENER_CALL(as, coalesced_io_del, Reverse, §ion, - int128_get64(fr->addr.start), - int128_get64(fr->addr.size)); - QTAILQ_FOREACH(cmr, &mr->coalesced, link) { - tmp = addrrange_shift(cmr->addr, - int128_sub(fr->addr.start, - int128_make64(fr->offset_in_region))); - if (!addrrange_intersects(tmp, fr->addr)) { - continue; - } - tmp = addrrange_intersection(tmp, fr->addr); - MEMORY_LISTENER_CALL(as, coalesced_io_add, Forward, §ion, - int128_get64(tmp.start), - int128_get64(tmp.size)); - } + flat_range_coalesced_io_del(fr, as); + flat_range_coalesced_io_add(fr, as); } } flatview_unref(view); @@ -2663,8 +2688,7 @@ void memory_listener_register(MemoryListener *listener, AddressSpace *as) listener->address_space = as; if (QTAILQ_EMPTY(&memory_listeners) - || listener->priority >= QTAILQ_LAST(&memory_listeners, - memory_listeners)->priority) { + || listener->priority >= QTAILQ_LAST(&memory_listeners)->priority) { QTAILQ_INSERT_TAIL(&memory_listeners, listener, link); } else { QTAILQ_FOREACH(other, &memory_listeners, link) { @@ -2676,8 +2700,7 @@ void memory_listener_register(MemoryListener *listener, AddressSpace *as) } if (QTAILQ_EMPTY(&as->listeners) - || listener->priority >= QTAILQ_LAST(&as->listeners, - memory_listeners)->priority) { + || listener->priority >= QTAILQ_LAST(&as->listeners)->priority) { QTAILQ_INSERT_TAIL(&as->listeners, listener, link_as); } else { QTAILQ_FOREACH(other, &as->listeners, link_as) { @@ -2767,7 +2790,7 @@ struct MemoryRegionList { QTAILQ_ENTRY(MemoryRegionList) mrqueue; }; -typedef QTAILQ_HEAD(mrqueue, MemoryRegionList) MemoryRegionListHead; +typedef QTAILQ_HEAD(, MemoryRegionList) MemoryRegionListHead; #define MR_SIZE(size) (int128_nz(size) ? (hwaddr)int128_get64( \ int128_sub((size), int128_one())) : 0) |