From: David Hildenbrand <david@redhat.com>
To: qemu-devel@nongnu.org
Cc: Eduardo Habkost <ehabkost@redhat.com>,
David Hildenbrand <david@redhat.com>,
"Dr . David Alan Gilbert" <dgilbert@redhat.com>,
Peter Xu <peterx@redhat.com>, Igor Mammedov <imammedo@redhat.com>,
Paolo Bonzini <pbonzini@redhat.com>,
Richard Henderson <rth@twiddle.net>
Subject: [PATCH RFC 3/4] memory: Add region_resize() callback to memory notifier
Date: Tue, 3 Mar 2020 15:19:38 +0100 [thread overview]
Message-ID: <20200303141939.352319-4-david@redhat.com> (raw)
In-Reply-To: <20200303141939.352319-1-david@redhat.com>
Let's provide a way for memory notifiers to get notified about a resize.
If the region_resize() callback is not implemented by a notifier, we
mimic the old behavior by removing the old section and adding the
new, resized section.
This callback is helpful when backends (like KVM) want to implement
atomic resizes of memory sections (e.g., resize while VCPUs are running and
using the section).
For now, we won't bother about a resize() callback for coalesced MMIO
regions. The main future use case is for virtio-mem to resize ram memory
regions while the guest is running.
Cc: Richard Henderson <rth@twiddle.net>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Cc: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
Cc: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
---
include/exec/memory.h | 18 +++++++++++
memory.c | 72 ++++++++++++++++++++++++++++++++++++++++---
2 files changed, 85 insertions(+), 5 deletions(-)
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 74805dd448..704eb64d75 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -492,6 +492,24 @@ struct MemoryListener {
*/
void (*region_nop)(MemoryListener *listener, MemoryRegionSection *section);
+ /**
+ * @region_resize:
+ *
+ * Called during an address space update transaction,
+ * for a section of the address space that is in the same place in the
+ * address space as in the last transaction, however, the size changed.
+ * Dirty memory logging can change as well.
+ *
+ * Note: If this callback is not implemented, the resize is communicated
+ * via a region_del(), followed by a region_add() instead.
+ *
+ * @listener: The #MemoryListener.
+ * @section: The old #MemoryRegionSection.
+ * @new: The new size.
+ */
+ void (*region_resize)(MemoryListener *listener,
+ MemoryRegionSection *section, Int128 new);
+
/**
* @log_start:
*
diff --git a/memory.c b/memory.c
index 09be40edd2..097b0db0e4 100644
--- a/memory.c
+++ b/memory.c
@@ -246,6 +246,17 @@ static bool flatrange_equal(FlatRange *a, FlatRange *b)
&& a->nonvolatile == b->nonvolatile;
}
+static bool flatrange_resized(FlatRange *a, FlatRange *b)
+{
+ return a->mr == b->mr
+ && int128_eq(a->addr.start, b->addr.start)
+ && int128_ne(a->addr.size, b->addr.size)
+ && a->offset_in_region == b->offset_in_region
+ && a->romd_mode == b->romd_mode
+ && a->readonly == b->readonly
+ && a->nonvolatile == b->nonvolatile;
+}
+
static FlatView *flatview_new(MemoryRegion *mr_root)
{
FlatView *view;
@@ -887,6 +898,45 @@ static void flat_range_coalesced_io_add(FlatRange *fr, AddressSpace *as)
}
}
+static void memory_listener_resize_region(FlatRange *fr, AddressSpace *as,
+ Int128 new, bool adding)
+{
+ FlatView *as_view = address_space_to_flatview(as);
+ MemoryRegionSection old_mrs = section_from_flat_range(fr, as_view);
+ MemoryRegionSection new_mrs = old_mrs;
+ MemoryListener *listener;
+
+ new_mrs.size = new;
+
+ if (adding) {
+ QTAILQ_FOREACH(listener, &as->listeners, link_as) {
+ if (listener->region_resize) {
+ /* Grow in the adding phase. */
+ if (int128_lt(fr->addr.size, new)) {
+ listener->region_resize(listener, &old_mrs, new);
+ }
+ continue;
+ }
+ if (listener->region_add) {
+ listener->region_add(listener, &new_mrs);
+ }
+ }
+ } else {
+ QTAILQ_FOREACH_REVERSE(listener, &as->listeners, link_as) {
+ if (listener->region_resize) {
+ /* Shrink in the removal phase. */
+ if (int128_gt(fr->addr.size, new)) {
+ listener->region_resize(listener, &old_mrs, new);
+ }
+ continue;
+ }
+ if (listener->region_del) {
+ listener->region_del(listener, &old_mrs);
+ }
+ }
+ }
+}
+
static void address_space_update_topology_pass(AddressSpace *as,
const FlatView *old_view,
const FlatView *new_view,
@@ -911,11 +961,23 @@ static void address_space_update_topology_pass(AddressSpace *as,
frnew = NULL;
}
- if (frold
- && (!frnew
- || int128_lt(frold->addr.start, frnew->addr.start)
- || (int128_eq(frold->addr.start, frnew->addr.start)
- && !flatrange_equal(frold, frnew)))) {
+ if (frold && frnew && flatrange_resized(frold, frnew)) {
+ /* In both and only the size (+ eventually logging) changed. */
+
+ memory_listener_resize_region(frold, as, frnew->addr.size,
+ adding);
+ if (adding) {
+ flat_range_coalesced_io_add(frnew, as);
+ } else {
+ flat_range_coalesced_io_del(frold, as);
+ }
+
+ ++iold;
+ ++inew;
+ } else if (frold && (!frnew
+ || int128_lt(frold->addr.start, frnew->addr.start)
+ || (int128_eq(frold->addr.start, frnew->addr.start)
+ && !flatrange_equal(frold, frnew)))) {
/* In old but not in new, or in both but attributes changed. */
if (!adding) {
--
2.24.1
next prev parent reply other threads:[~2020-03-03 14:21 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-03-03 14:19 [PATCH RFC 0/4] kvm: Implement atomic memory region resizes David Hildenbrand
2020-03-03 14:19 ` [PATCH RFC 1/4] openpic_kvm: Use kvm_device_ioctl() instead of ioctl() David Hildenbrand
2020-03-03 14:19 ` [PATCH RFC 2/4] intc/s390_flic_kvm.c: " David Hildenbrand
2020-03-04 8:22 ` Christian Borntraeger
2020-03-04 8:30 ` David Hildenbrand
2020-03-03 14:19 ` David Hildenbrand [this message]
2020-03-03 14:19 ` [PATCH RFC 4/4] kvm: Implement atomic memory region resizes via region_resize() David Hildenbrand
2020-03-06 9:50 ` Paolo Bonzini
2020-03-06 10:20 ` David Hildenbrand
2020-03-06 11:38 ` Paolo Bonzini
2020-03-06 12:18 ` David Hildenbrand
2020-03-06 14:30 ` David Hildenbrand
2020-03-06 14:39 ` Paolo Bonzini
2020-03-06 14:44 ` David Hildenbrand
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200303141939.352319-4-david@redhat.com \
--to=david@redhat.com \
--cc=dgilbert@redhat.com \
--cc=ehabkost@redhat.com \
--cc=imammedo@redhat.com \
--cc=pbonzini@redhat.com \
--cc=peterx@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=rth@twiddle.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).