aboutsummaryrefslogtreecommitdiff
path: root/migration
diff options
context:
space:
mode:
authorPeter Xu <peterx@redhat.com>2023-01-20 11:31:47 -0500
committerJuan Quintela <quintela@redhat.com>2023-02-06 19:22:56 +0100
commit301d7ffe5f630dc5d0e2a3638b9eae7a00b1088a (patch)
treea8cd4918a0505460881c0e9f8a52e379bdda12a7 /migration
parent6661b8c7fe3f8b5687d2d90f7b4f3f23d70e3e8b (diff)
migration: Fix migration crash when target psize larger than host
Commit d9e474ea56 overlooked the case where the target psize is even larger than the host psize. One example is Alpha has 8K page size and migration will start to crash the source QEMU when running Alpha migration on x86. Fix it by detecting that case and set host start/end just to cover the single page to be migrated. This will slightly optimize the common case where host psize equals to guest psize so we don't even need to do the roundups, but that's trivial. Cc: qemu-stable@nongnu.org Reported-by: Thomas Huth <thuth@redhat.com> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1456 Fixes: d9e474ea56 ("migration: Teach PSS about host page") Signed-off-by: Peter Xu <peterx@redhat.com> Reviewed-by: Thomas Huth <thuth@redhat.com> Reviewed-by: Juan Quintela <quintela@redhat.com> Signed-off-by: Juan Quintela <quintela@redhat.com>
Diffstat (limited to 'migration')
-rw-r--r--migration/ram.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/migration/ram.c b/migration/ram.c
index 334309f1c6..68a45338e3 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -2319,8 +2319,25 @@ static void pss_host_page_prepare(PageSearchStatus *pss)
size_t guest_pfns = qemu_ram_pagesize(pss->block) >> TARGET_PAGE_BITS;
pss->host_page_sending = true;
- pss->host_page_start = ROUND_DOWN(pss->page, guest_pfns);
- pss->host_page_end = ROUND_UP(pss->page + 1, guest_pfns);
+ if (guest_pfns <= 1) {
+ /*
+ * This covers both when guest psize == host psize, or when guest
+ * has larger psize than the host (guest_pfns==0).
+ *
+ * For the latter, we always send one whole guest page per
+ * iteration of the host page (example: an Alpha VM on x86 host
+ * will have guest psize 8K while host psize 4K).
+ */
+ pss->host_page_start = pss->page;
+ pss->host_page_end = pss->page + 1;
+ } else {
+ /*
+ * The host page spans over multiple guest pages, we send them
+ * within the same host page iteration.
+ */
+ pss->host_page_start = ROUND_DOWN(pss->page, guest_pfns);
+ pss->host_page_end = ROUND_UP(pss->page + 1, guest_pfns);
+ }
}
/*