From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:32973) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X37Vw-000888-PV for qemu-devel@nongnu.org; Fri, 04 Jul 2014 13:43:18 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1X37Vq-0000b0-FD for qemu-devel@nongnu.org; Fri, 04 Jul 2014 13:43:12 -0400 Received: from mx1.redhat.com ([209.132.183.28]:56162) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X37Vq-0000a4-78 for qemu-devel@nongnu.org; Fri, 04 Jul 2014 13:43:06 -0400 From: "Dr. David Alan Gilbert (git)" Date: Fri, 4 Jul 2014 18:41:49 +0100 Message-Id: <1404495717-4239-39-git-send-email-dgilbert@redhat.com> In-Reply-To: <1404495717-4239-1-git-send-email-dgilbert@redhat.com> References: <1404495717-4239-1-git-send-email-dgilbert@redhat.com> Subject: [Qemu-devel] [PATCH 38/46] postcopy_ram.c: place_page and helpers List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: aarcange@redhat.com, yamahata@private.email.ne.jp, lilei@linux.vnet.ibm.com, quintela@redhat.com From: "Dr. David Alan Gilbert" postcopy_place_page (etc) provide a way for postcopy to place a page into guests memory atomically (using the new remap_anon_pages syscall). Signed-off-by: Dr. David Alan Gilbert --- include/migration/migration.h | 1 + include/migration/postcopy-ram.h | 23 +++++++++ postcopy-ram.c | 105 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+) diff --git a/include/migration/migration.h b/include/migration/migration.h index fe639b4..1a33b05 100644 --- a/include/migration/migration.h +++ b/include/migration/migration.h @@ -93,6 +93,7 @@ struct MigrationIncomingState { QEMUFile *return_path; QemuMutex rp_mutex; /* We send replies from multiple threads */ PostcopyPMI postcopy_pmi; + void *postcopy_tmp_page; }; MigrationIncomingState *migration_incoming_state_init(QEMUFile *f); diff --git a/include/migration/postcopy-ram.h b/include/migration/postcopy-ram.h index 383b1e8..57a74f0 100644 --- a/include/migration/postcopy-ram.h +++ b/include/migration/postcopy-ram.h @@ -53,6 +53,29 @@ int postcopy_ram_incoming_cleanup(MigrationIncomingState *mis); int postcopy_send_discard_bm_ram(MigrationState *ms, const char *name, unsigned long start, unsigned long end); +/* + * Place a zero'd page of memory at *host + * returns 0 on success + */ +int postcopy_place_zero_page(MigrationIncomingState *mis, void *host, + long bitmap_offset); + +/* + * Place a page (from) at (host) efficiently + * There are restrictions on how 'from' must be mapped, in general best + * to use other postcopy_ routines to allocate. + * returns 0 on success + */ +int postcopy_place_page(MigrationIncomingState *mis, void *host, void *from, + long bitmap_offset); + +/* + * Allocate a page of memory that can be mapped at a later point in time + * using postcopy_place_page + * Returns: Pointer to allocated page + */ +void *postcopy_get_tmp_page(MigrationIncomingState *mis); + void postcopy_pmi_destroy(MigrationIncomingState *mis); void postcopy_pmi_discard_range(MigrationIncomingState *mis, size_t start, size_t npages); diff --git a/postcopy-ram.c b/postcopy-ram.c index fb7b02b..de3534f 100644 --- a/postcopy-ram.c +++ b/postcopy-ram.c @@ -334,6 +334,10 @@ int postcopy_ram_incoming_cleanup(MigrationIncomingState *mis) return -1; } + if (mis->postcopy_tmp_page) { + munmap(mis->postcopy_tmp_page, getpagesize()); + mis->postcopy_tmp_page = NULL; + } return 0; } @@ -390,6 +394,88 @@ int postcopy_ram_enable_notify(MigrationIncomingState *mis) return 0; } +/* + * Place a zero'd page of memory at *host + * returns 0 on success + * bitmap_offset: Index into the migration bitmaps + */ +int postcopy_place_zero_page(MigrationIncomingState *mis, void *host, + long bitmap_offset) +{ + void *tmp = postcopy_get_tmp_page(mis); + if (!tmp) { + return -ENOMEM; + } + *(char *)tmp = 0; + return postcopy_place_page(mis, host, tmp, bitmap_offset); +} + +/* + * Place a page (from) at (host) efficiently + * There are restrictions on how 'from' must be mapped, in general best + * to use other postcopy_ routines to allocate. + * returns 0 on success + * bitmap_offset: Index into the migration bitmaps + */ +int postcopy_place_page(MigrationIncomingState *mis, void *host, void *from, + long bitmap_offset) +{ + PostcopyPMIState old_state, tmp_state; + + if (syscall(__NR_remap_anon_pages, host, from, getpagesize(), 0) != + getpagesize()) { + perror("remap_anon_pages in postcopy_place_page"); + fprintf(stderr, "host: %p from: %p pmi=%d\n", host, from, + postcopy_pmi_get_state(mis, bitmap_offset)); + + return -errno; + } + + tmp_state = postcopy_pmi_get_state(mis, bitmap_offset); + do { + old_state = tmp_state; + tmp_state = postcopy_pmi_change_state(mis, bitmap_offset, old_state, + POSTCOPY_PMI_RECEIVED); + + } while (old_state != tmp_state); + + + if (old_state == POSTCOPY_PMI_REQUESTED) { + /* TODO: Notify kernel */ + } + + /* TODO: hostpagesize!=targetpagesize case */ + return 0; +} + +/* + * Returns a page of memory that can be mapped at a later point in time + * using postcopy_place_page + * The same address is used repeatedly, postcopy_place_page just takes the + * backing page away. + * Returns: Pointer to allocated page + */ +void *postcopy_get_tmp_page(MigrationIncomingState *mis) +{ + + if (!mis->postcopy_tmp_page) { + mis->postcopy_tmp_page = mmap(NULL, getpagesize(), + PROT_READ | PROT_WRITE, MAP_PRIVATE | + MAP_ANONYMOUS, -1, 0); + if (!mis->postcopy_tmp_page) { + perror("mapping postcopy tmp page"); + return NULL; + } + if (madvise(mis->postcopy_tmp_page, getpagesize(), MADV_DONTFORK)) { + munmap(mis->postcopy_tmp_page, getpagesize()); + perror("postcpy tmp page DONTFORK"); + return NULL; + } + } + + return mis->postcopy_tmp_page; +} + #else /* No target OS support, stubs just fail */ int postcopy_ram_hosttest(void) @@ -422,6 +508,25 @@ int postcopy_ram_enable_notify(MigrationIncomingState *mis) fprintf(stderr, "postcopy_ram_enable_notify: No OS support\n"); return -1; } + +int postcopy_place_zero_page(MigrationIncomingState *mis, void *host) +{ + error_report("postcopy_place_zero_page: No OS support"); + return -1; +} + +int postcopy_place_page(MigrationIncomingState *mis, void *host, void *from) +{ + error_report("postcopy_place_page: No OS support"); + return -1; +} + +void *postcopy_get_tmp_page(MigrationIncomingState *mis) +{ + error_report("postcopy_get_tmp_page: No OS support"); + return -1; +} + #endif /* ------------------------------------------------------------------------- */ -- 1.9.3