Architecture such as ARM use a page size of 1KB, while write protection is done at the granularity of host pages (generally 4KB). All addresses must always be aligned to the size of a host page.
Signed-off-by: Christian Pinto <c.pi...@virtualopensystems.com> Signed-off-by: Baptiste Reynal <b.rey...@virtualopensystems.com> --- migration/postcopy-ram.c | 6 +++--- migration/ram.c | 18 ++++++++++++++---- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c index 9c45f1059f..97382067b3 100644 --- a/migration/postcopy-ram.c +++ b/migration/postcopy-ram.c @@ -373,7 +373,7 @@ int postcopy_ram_prepare_discard(MigrationIncomingState *mis) return 0; } -int ram_set_pages_wp(uint64_t page_addr, +int ram_set_pages_wp(ram_addr_t page_addr, uint64_t size, bool remove, int uffd) @@ -556,10 +556,10 @@ static void *postcopy_ram_fault_thread(void *opaque) * will be an deadlock error. */ if (migration_in_setup(ms)) { - uint64_t host = msg.arg.pagefault.address; + ram_addr_t host = msg.arg.pagefault.address; host &= ~(hostpagesize - 1); - ret = ram_set_pages_wp(host, getpagesize(), true, + ret = ram_set_pages_wp(host, hostpagesize, true, us->userfault_fd); if (ret < 0) { error_report("Remove page's write-protect failed"); diff --git a/migration/ram.c b/migration/ram.c index 3417c56f29..7a3b1c7ed3 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -1383,14 +1383,24 @@ static int ram_find_and_save_block(QEMUFile *f, bool last_stage, /* For snapshot, we will remove the page write-protect here */ if (migration_in_snapshot(ms)) { int ret; - uint64_t host_addr = (uint64_t)(pss.block->host + pss.offset); - + /* + * Some architectures in QEMU use a smaller memory page size + * with respect to the host page size. ARM as an example + * uses 1K memory pages, while Linux supports pages of minimum + * size of 4K. + * Userfault write protection works at the level of a host page + * and thus one full host page has to be protected/unprotected + * every time. + */ + ram_addr_t host_addr = (ram_addr_t)(pss.block->host + + pss.offset) & (~(qemu_host_page_size - 1)); ret = ram_set_pages_wp(host_addr, getpagesize(), true, ms->userfault_state.userfault_fd); if (ret < 0) { error_report("Failed to remove the write-protect for page:" - "%"PRIx64 " length: %d, block: %s", host_addr, - getpagesize(), pss.block->idstr); + "%"PRIx64 " length: %d, offset: %"PRIx64 + ", block: %s", host_addr, getpagesize(), + pss.offset, pss.block->idstr); } } } -- 2.11.0