From 41d84210d403a686052fb5fc4c9f027e13e92185 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Fri, 24 Feb 2017 18:28:36 +0000 Subject: [PATCH] postcopy: Use temporary for placing zero huge pages The kernel can't do UFFDIO_ZEROPAGE for huge pages, so we have to allocate a temporary (always zero) page and use UFFDIO_COPYPAGE on it. Signed-off-by: Dr. David Alan Gilbert Reviewed-by: Juan Quintela Reviewed-by: Laurent Vivier Message-Id: <20170224182844.32452-9-dgilbert@redhat.com> Signed-off-by: Dr. David Alan Gilbert --- include/migration/migration.h | 1 + migration/postcopy-ram.c | 23 +++++++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/include/migration/migration.h b/include/migration/migration.h index 08b98e9911..5720c884f4 100644 --- a/include/migration/migration.h +++ b/include/migration/migration.h @@ -109,6 +109,7 @@ struct MigrationIncomingState { QEMUFile *to_src_file; QemuMutex rp_mutex; /* We send replies from multiple threads */ void *postcopy_tmp_page; + void *postcopy_tmp_zero_page; QEMUBH *bh; diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c index a8b7fedc99..4c736d28a0 100644 --- a/migration/postcopy-ram.c +++ b/migration/postcopy-ram.c @@ -324,6 +324,10 @@ int postcopy_ram_incoming_cleanup(MigrationIncomingState *mis) munmap(mis->postcopy_tmp_page, mis->largest_page_size); mis->postcopy_tmp_page = NULL; } + if (mis->postcopy_tmp_zero_page) { + munmap(mis->postcopy_tmp_zero_page, mis->largest_page_size); + mis->postcopy_tmp_zero_page = NULL; + } trace_postcopy_ram_incoming_cleanup_exit(); return 0; } @@ -593,8 +597,23 @@ int postcopy_place_page_zero(MigrationIncomingState *mis, void *host, return -e; } } else { - /* TODO: The kernel can't use UFFDIO_ZEROPAGE for hugepages */ - assert(0); + /* The kernel can't use UFFDIO_ZEROPAGE for hugepages */ + if (!mis->postcopy_tmp_zero_page) { + mis->postcopy_tmp_zero_page = mmap(NULL, mis->largest_page_size, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, + -1, 0); + if (mis->postcopy_tmp_zero_page == MAP_FAILED) { + int e = errno; + mis->postcopy_tmp_zero_page = NULL; + error_report("%s: %s mapping large zero page", + __func__, strerror(e)); + return -e; + } + memset(mis->postcopy_tmp_zero_page, '\0', mis->largest_page_size); + } + return postcopy_place_page(mis, host, mis->postcopy_tmp_zero_page, + pagesize); } return 0; -- 2.11.4.GIT