[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v3 41/47] Postcopy: Use helpers to map pages during
From: |
Dr. David Alan Gilbert (git) |
Subject: |
[Qemu-devel] [PATCH v3 41/47] Postcopy: Use helpers to map pages during migration |
Date: |
Thu, 28 Aug 2014 16:03:58 +0100 |
From: "Dr. David Alan Gilbert" <address@hidden>
In postcopy, the destination guest is running at the same time
as it's receiving pages; as we receive new pages we must put
them into the guests address space atomically to avoid a running
CPU accessing a partially written page.
Use the helpers in postcopy-ram.c to map these pages.
Signed-off-by: Dr. David Alan Gilbert <address@hidden>
---
arch_init.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 84 insertions(+), 9 deletions(-)
diff --git a/arch_init.c b/arch_init.c
index d592579..b449f6d 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -1328,9 +1328,20 @@ static int load_xbzrle(QEMUFile *f, ram_addr_t addr,
void *host)
return 0;
}
+/*
+ * Read a RAMBlock ID from the stream f, find the host address of the
+ * start of that block and add on 'offset'
+ *
+ * f: Stream to read from
+ * mis: MigrationIncomingState
+ * offset: Offset within the block
+ * flags: Page flags (mostly to see if it's a continuation of previous block)
+ * rb: Pointer to RAMBlock* that gets filled in with the RB we find
+ */
static inline void *host_from_stream_offset(QEMUFile *f,
+ MigrationIncomingState *mis,
ram_addr_t offset,
- int flags)
+ int flags, RAMBlock **rb)
{
static RAMBlock *block = NULL;
char id[256];
@@ -1341,8 +1352,11 @@ static inline void *host_from_stream_offset(QEMUFile *f,
error_report("Ack, bad migration stream!");
return NULL;
}
+ if (rb) {
+ *rb = block;
+ }
- return memory_region_get_ram_ptr(block->mr) + offset;
+ goto gotit;
}
len = qemu_get_byte(f);
@@ -1350,12 +1364,22 @@ static inline void *host_from_stream_offset(QEMUFile *f,
id[len] = 0;
QTAILQ_FOREACH(block, &ram_list.blocks, next) {
- if (!strncmp(id, block->idstr, sizeof(id)))
- return memory_region_get_ram_ptr(block->mr) + offset;
+ if (!strncmp(id, block->idstr, sizeof(id))) {
+ if (rb) {
+ *rb = block;
+ }
+ goto gotit;
+ }
}
error_report("Can't find block %s!", id);
return NULL;
+
+gotit:
+ postcopy_hook_early_receive(mis,
+ (offset + (*rb)->offset) >> TARGET_PAGE_BITS);
+ return memory_region_get_ram_ptr(block->mr) + offset;
+
}
/*
@@ -1385,6 +1409,13 @@ static int ram_load(QEMUFile *f, void *opaque, int
version_id)
ram_addr_t addr;
int flags, ret = 0;
static uint64_t seq_iter;
+ /*
+ * System is running in postcopy mode, page inserts to host memory must be
+ * atomic
+ */
+ MigrationIncomingState *mis = migration_incoming_get_current();
+ bool postcopy_running = mis->postcopy_ram_state >=
+ POSTCOPY_RAM_INCOMING_LISTENING;
seq_iter++;
@@ -1439,8 +1470,9 @@ static int ram_load(QEMUFile *f, void *opaque, int
version_id)
} else if (flags & RAM_SAVE_FLAG_COMPRESS) {
void *host;
uint8_t ch;
+ RAMBlock *rb;
- host = host_from_stream_offset(f, addr, flags);
+ host = host_from_stream_offset(f, mis, addr, flags, &rb);
if (!host) {
error_report("Illegal RAM offset " RAM_ADDR_FMT, addr);
ret = -EINVAL;
@@ -1448,20 +1480,63 @@ static int ram_load(QEMUFile *f, void *opaque, int
version_id)
}
ch = qemu_get_byte(f);
- ram_handle_compressed(host, ch, TARGET_PAGE_SIZE);
+ if (!postcopy_running) {
+ ram_handle_compressed(host, ch, TARGET_PAGE_SIZE);
+ } else {
+ if (!ch) {
+ ret = postcopy_place_zero_page(mis, host,
+ (addr + rb->offset) >> TARGET_PAGE_BITS);
+ } else {
+ void *tmp;
+ tmp = postcopy_get_tmp_page(mis);
+ if (!tmp) {
+ return -ENOMEM;
+ }
+ memset(tmp, ch, TARGET_PAGE_SIZE);
+ ret = postcopy_place_page(mis, host, tmp,
+ (addr + rb->offset) >> TARGET_PAGE_BITS);
+ }
+ if (ret) {
+ error_report("ram_load: Failure in postcopy compress @"
+ "%zx/%p;%s+%zx",
+ addr, host, rb->idstr, rb->offset);
+ return ret;
+ }
+ }
} else if (flags & RAM_SAVE_FLAG_PAGE) {
void *host;
+ RAMBlock *rb;
- host = host_from_stream_offset(f, addr, flags);
+ host = host_from_stream_offset(f, mis, addr, flags, &rb);
if (!host) {
error_report("Illegal RAM offset " RAM_ADDR_FMT, addr);
ret = -EINVAL;
break;
}
- qemu_get_buffer(f, host, TARGET_PAGE_SIZE);
+ if (!postcopy_running) {
+ qemu_get_buffer(f, host, TARGET_PAGE_SIZE);
+ } else {
+ void *tmp = postcopy_get_tmp_page(mis);
+ if (!tmp) {
+ return -ENOMEM;
+ }
+ qemu_get_buffer(f, tmp, TARGET_PAGE_SIZE);
+ ret = postcopy_place_page(mis, host, tmp,
+ (addr + rb->offset) >> TARGET_PAGE_BITS);
+ if (ret) {
+ error_report("ram_load: Failure in postcopy simple"
+ "@%zx/%p;%s+%zx",
+ addr, host, rb->idstr, rb->offset);
+ return ret;
+ }
+ }
} else if (flags & RAM_SAVE_FLAG_XBZRLE) {
- void *host = host_from_stream_offset(f, addr, flags);
+ if (postcopy_running) {
+ error_report("XBZRLE RAM block in postcopy mode @%zx\n", addr);
+ return -EINVAL;
+ }
+ void *host = host_from_stream_offset(f, mis, addr, flags, NULL);
if (!host) {
error_report("Illegal RAM offset " RAM_ADDR_FMT, addr);
ret = -EINVAL;
--
1.9.3
- [Qemu-devel] [PATCH v3 15/47] qemu_loadvm errors and debug, (continued)
- [Qemu-devel] [PATCH v3 15/47] qemu_loadvm errors and debug, Dr. David Alan Gilbert (git), 2014/08/28
- [Qemu-devel] [PATCH v3 19/47] Add wrappers and handlers for sending/receiving the postcopy-ram migration messages., Dr. David Alan Gilbert (git), 2014/08/28
- [Qemu-devel] [PATCH v3 31/47] postcopy: ram_enable_notify to switch on userfault, Dr. David Alan Gilbert (git), 2014/08/28
- [Qemu-devel] [PATCH v3 34/47] mig fd_connect: open return path, Dr. David Alan Gilbert (git), 2014/08/28
- [Qemu-devel] [PATCH v3 33/47] Postcopy: Rework migration thread for postcopy mode, Dr. David Alan Gilbert (git), 2014/08/28
- [Qemu-devel] [PATCH v3 32/47] Postcopy: postcopy_start, Dr. David Alan Gilbert (git), 2014/08/28
- [Qemu-devel] [PATCH v3 36/47] Page request: Add MIG_RPCOMM_REQPAGES reverse command, Dr. David Alan Gilbert (git), 2014/08/28
- [Qemu-devel] [PATCH v3 37/47] Page request: Process incoming page request, Dr. David Alan Gilbert (git), 2014/08/28
- [Qemu-devel] [PATCH v3 39/47] Add assertion to check migration_dirty_pages, Dr. David Alan Gilbert (git), 2014/08/28
- [Qemu-devel] [PATCH v3 38/47] Page request: Consume pages off the post-copy queue, Dr. David Alan Gilbert (git), 2014/08/28
- [Qemu-devel] [PATCH v3 41/47] Postcopy: Use helpers to map pages during migration,
Dr. David Alan Gilbert (git) <=
- [Qemu-devel] [PATCH v3 42/47] qemu_ram_block_from_host, Dr. David Alan Gilbert (git), 2014/08/28
- [Qemu-devel] [PATCH v3 43/47] Don't sync dirty bitmaps in postcopy, Dr. David Alan Gilbert (git), 2014/08/28
- [Qemu-devel] [PATCH v3 44/47] Postcopy; Handle userfault requests, Dr. David Alan Gilbert (git), 2014/08/28
- [Qemu-devel] [PATCH v3 46/47] postcopy: Wire up loadvm_postcopy_ram_handle_{run, end} commands, Dr. David Alan Gilbert (git), 2014/08/28
- [Qemu-devel] [PATCH v3 45/47] Start up a postcopy/listener thread ready for incoming page data, Dr. David Alan Gilbert (git), 2014/08/28
- [Qemu-devel] [PATCH v3 47/47] End of migration for postcopy, Dr. David Alan Gilbert (git), 2014/08/28
- [Qemu-devel] [PATCH v3 35/47] Postcopy: Create a fault handler thread before marking the ram as userfault, Dr. David Alan Gilbert (git), 2014/08/28
- [Qemu-devel] [PATCH v3 40/47] postcopy_ram.c: place_page and helpers, Dr. David Alan Gilbert (git), 2014/08/28
- [Qemu-devel] [PATCH v3 30/47] postcopy: Incoming initialisation, Dr. David Alan Gilbert (git), 2014/08/28