qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [RFC PATCH 2/4] migration/ram: Fix for ARM/ARM64 page size


From: Christian Pinto
Subject: [Qemu-devel] [RFC PATCH 2/4] migration/ram: Fix for ARM/ARM64 page size
Date: Thu, 9 Mar 2017 12:34:35 +0100

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 <address@hidden>
Signed-off-by: Baptiste Reynal <address@hidden>
---
 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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]