[Qemu-devel] [PULL 36/57] postcopy: Incoming initialisation
From: "Dr. David Alan Gilbert" Signed-off-by: Dr. David Alan Gilbert Reviewed-by: David Gibson Reviewed-by: Amit Shah Reviewed-by: Juan Quintela Signed-off-by: Juan Quintela --- include/migration/migration.h| 3 ++ include/migration/postcopy-ram.h | 12 + migration/postcopy-ram.c | 104 +++ migration/ram.c | 11 + migration/savevm.c | 6 +++ trace-events | 2 + 6 files changed, 138 insertions(+) diff --git a/include/migration/migration.h b/include/migration/migration.h index b382d77..6e42b58 100644 --- a/include/migration/migration.h +++ b/include/migration/migration.h @@ -86,6 +86,8 @@ struct MigrationIncomingState { */ QemuEvent main_thread_load_event; +/* For the kernel to send us notifications */ +int userfault_fd; QEMUFile *to_src_file; QemuMutex rp_mutex;/* We send replies from multiple threads */ @@ -204,6 +206,7 @@ int ram_postcopy_send_discard_bitmap(MigrationState *ms); /* For incoming postcopy discard */ int ram_discard_range(MigrationIncomingState *mis, const char *block_name, uint64_t start, size_t length); +int ram_postcopy_incoming_init(MigrationIncomingState *mis); /** * @migrate_add_blocker - prevent migration from proceeding diff --git a/include/migration/postcopy-ram.h b/include/migration/postcopy-ram.h index de79fa7..f87020c 100644 --- a/include/migration/postcopy-ram.h +++ b/include/migration/postcopy-ram.h @@ -17,6 +17,18 @@ bool postcopy_ram_supported_by_host(void); /* + * Initialise postcopy-ram, setting the RAM to a state where we can go into + * postcopy later; must be called prior to any precopy. + * called from ram.c's similarly named ram_postcopy_incoming_init + */ +int postcopy_ram_incoming_init(MigrationIncomingState *mis, size_t ram_pages); + +/* + * At the end of a migration where postcopy_ram_incoming_init was called. + */ +int postcopy_ram_incoming_cleanup(MigrationIncomingState *mis); + +/* * Discard the contents of 'length' bytes from 'start' * We can assume that if we've been called postcopy_ram_hosttest returned true */ diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c index 261feda..8478bfd 100644 --- a/migration/postcopy-ram.c +++ b/migration/postcopy-ram.c @@ -184,6 +184,97 @@ int postcopy_ram_discard_range(MigrationIncomingState *mis, uint8_t *start, return 0; } +/* + * Setup an area of RAM so that it *can* be used for postcopy later; this + * must be done right at the start prior to pre-copy. + * opaque should be the MIS. + */ +static int init_range(const char *block_name, void *host_addr, + ram_addr_t offset, ram_addr_t length, void *opaque) +{ +MigrationIncomingState *mis = opaque; + +trace_postcopy_init_range(block_name, host_addr, offset, length); + +/* + * We need the whole of RAM to be truly empty for postcopy, so things + * like ROMs and any data tables built during init must be zero'd + * - we're going to get the copy from the source anyway. + * (Precopy will just overwrite this data, so doesn't need the discard) + */ +if (postcopy_ram_discard_range(mis, host_addr, length)) { +return -1; +} + +return 0; +} + +/* + * At the end of migration, undo the effects of init_range + * opaque should be the MIS. + */ +static int cleanup_range(const char *block_name, void *host_addr, +ram_addr_t offset, ram_addr_t length, void *opaque) +{ +MigrationIncomingState *mis = opaque; +struct uffdio_range range_struct; +trace_postcopy_cleanup_range(block_name, host_addr, offset, length); + +/* + * We turned off hugepage for the precopy stage with postcopy enabled + * we can turn it back on now. + */ +#ifdef MADV_HUGEPAGE +if (madvise(host_addr, length, MADV_HUGEPAGE)) { +error_report("%s HUGEPAGE: %s", __func__, strerror(errno)); +return -1; +} +#endif + +/* + * We can also turn off userfault now since we should have all the + * pages. It can be useful to leave it on to debug postcopy + * if you're not sure it's always getting every page. + */ +range_struct.start = (uintptr_t)host_addr; +range_struct.len = length; + +if (ioctl(mis->userfault_fd, UFFDIO_UNREGISTER, &range_struct)) { +error_report("%s: userfault unregister %s", __func__, strerror(errno)); + +return -1; +} + +return 0; +} + +/* + * Initialise postcopy-ram, setting the RAM to a state where we can go into + * postcopy later; must be called prior to any precopy. + * called from arch_init's similarly named ram_postcopy_incoming_init + */ +int postcopy_ram_incoming_init(MigrationIncomingState *mis, size_t ram_pages) +{ +if (qemu_ram_foreach_block(init_range, mis)) { +return -1; +} + +return 0; +} + +/* + * At the end of a migration where postcopy_ram_incoming_init was call
[Qemu-devel] [PULL 36/57] postcopy: Incoming initialisation
From: "Dr. David Alan Gilbert" Signed-off-by: Dr. David Alan Gilbert Reviewed-by: David Gibson Reviewed-by: Amit Shah Reviewed-by: Juan Quintela Signed-off-by: Juan Quintela --- include/migration/migration.h| 3 ++ include/migration/postcopy-ram.h | 12 + migration/postcopy-ram.c | 104 +++ migration/ram.c | 11 + migration/savevm.c | 6 +++ trace-events | 2 + 6 files changed, 138 insertions(+) diff --git a/include/migration/migration.h b/include/migration/migration.h index b382d77..6e42b58 100644 --- a/include/migration/migration.h +++ b/include/migration/migration.h @@ -86,6 +86,8 @@ struct MigrationIncomingState { */ QemuEvent main_thread_load_event; +/* For the kernel to send us notifications */ +int userfault_fd; QEMUFile *to_src_file; QemuMutex rp_mutex;/* We send replies from multiple threads */ @@ -204,6 +206,7 @@ int ram_postcopy_send_discard_bitmap(MigrationState *ms); /* For incoming postcopy discard */ int ram_discard_range(MigrationIncomingState *mis, const char *block_name, uint64_t start, size_t length); +int ram_postcopy_incoming_init(MigrationIncomingState *mis); /** * @migrate_add_blocker - prevent migration from proceeding diff --git a/include/migration/postcopy-ram.h b/include/migration/postcopy-ram.h index de79fa7..f87020c 100644 --- a/include/migration/postcopy-ram.h +++ b/include/migration/postcopy-ram.h @@ -17,6 +17,18 @@ bool postcopy_ram_supported_by_host(void); /* + * Initialise postcopy-ram, setting the RAM to a state where we can go into + * postcopy later; must be called prior to any precopy. + * called from ram.c's similarly named ram_postcopy_incoming_init + */ +int postcopy_ram_incoming_init(MigrationIncomingState *mis, size_t ram_pages); + +/* + * At the end of a migration where postcopy_ram_incoming_init was called. + */ +int postcopy_ram_incoming_cleanup(MigrationIncomingState *mis); + +/* * Discard the contents of 'length' bytes from 'start' * We can assume that if we've been called postcopy_ram_hosttest returned true */ diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c index 261feda..8478bfd 100644 --- a/migration/postcopy-ram.c +++ b/migration/postcopy-ram.c @@ -184,6 +184,97 @@ int postcopy_ram_discard_range(MigrationIncomingState *mis, uint8_t *start, return 0; } +/* + * Setup an area of RAM so that it *can* be used for postcopy later; this + * must be done right at the start prior to pre-copy. + * opaque should be the MIS. + */ +static int init_range(const char *block_name, void *host_addr, + ram_addr_t offset, ram_addr_t length, void *opaque) +{ +MigrationIncomingState *mis = opaque; + +trace_postcopy_init_range(block_name, host_addr, offset, length); + +/* + * We need the whole of RAM to be truly empty for postcopy, so things + * like ROMs and any data tables built during init must be zero'd + * - we're going to get the copy from the source anyway. + * (Precopy will just overwrite this data, so doesn't need the discard) + */ +if (postcopy_ram_discard_range(mis, host_addr, length)) { +return -1; +} + +return 0; +} + +/* + * At the end of migration, undo the effects of init_range + * opaque should be the MIS. + */ +static int cleanup_range(const char *block_name, void *host_addr, +ram_addr_t offset, ram_addr_t length, void *opaque) +{ +MigrationIncomingState *mis = opaque; +struct uffdio_range range_struct; +trace_postcopy_cleanup_range(block_name, host_addr, offset, length); + +/* + * We turned off hugepage for the precopy stage with postcopy enabled + * we can turn it back on now. + */ +#ifdef MADV_HUGEPAGE +if (madvise(host_addr, length, MADV_HUGEPAGE)) { +error_report("%s HUGEPAGE: %s", __func__, strerror(errno)); +return -1; +} +#endif + +/* + * We can also turn off userfault now since we should have all the + * pages. It can be useful to leave it on to debug postcopy + * if you're not sure it's always getting every page. + */ +range_struct.start = (uintptr_t)host_addr; +range_struct.len = length; + +if (ioctl(mis->userfault_fd, UFFDIO_UNREGISTER, &range_struct)) { +error_report("%s: userfault unregister %s", __func__, strerror(errno)); + +return -1; +} + +return 0; +} + +/* + * Initialise postcopy-ram, setting the RAM to a state where we can go into + * postcopy later; must be called prior to any precopy. + * called from arch_init's similarly named ram_postcopy_incoming_init + */ +int postcopy_ram_incoming_init(MigrationIncomingState *mis, size_t ram_pages) +{ +if (qemu_ram_foreach_block(init_range, mis)) { +return -1; +} + +return 0; +} + +/* + * At the end of a migration where postcopy_ram_incoming_init was call