/* * QEMU live migration * * Copyright IBM, Corp. 2008 * * Authors: * Anthony Liguori * * This work is licensed under the terms of the GNU GPL, version 2. See * the COPYING file in the top-level directory. * * Contributions after 2012-01-13 are licensed under the terms of the * GNU GPL, version 2 or (at your option) any later version. */ #include "qemu/osdep.h" #include "qemu/cutils.h" #include "qemu/error-report.h" #include "qemu/main-loop.h" #include "migration/migration.h" #include "migration/qemu-file.h" #include "sysemu/sysemu.h" #include "block/block.h" #include "qapi/qmp/qerror.h" #include "qapi/util.h" #include "qemu/sockets.h" #include "qemu/rcu.h" #include "migration/block.h" #include "migration/postcopy-ram.h" #include "qemu/thread.h" #include "qmp-commands.h" #include "trace.h" #include "qapi-event.h" #include "qom/cpu.h" #include "exec/memory.h" #include "exec/address-spaces.h" #define MAX_THROTTLE (32 << 20) /* Migration transfer speed throttling */ /* Amount of time to allocate to each "chunk" of bandwidth-throttled * data. */ #define BUFFER_DELAY 100 #define XFER_LIMIT_RATIO (1000 / BUFFER_DELAY) /* Default compression thread count */ #define DEFAULT_MIGRATE_COMPRESS_THREAD_COUNT 8 /* Default decompression thread count, usually decompression is at * least 4 times as fast as compression.*/ #define DEFAULT_MIGRATE_DECOMPRESS_THREAD_COUNT 2 /*0: means nocompress, 1: best speed, ... 9: best compress ratio */ #define DEFAULT_MIGRATE_COMPRESS_LEVEL 1 /* Define default autoconverge cpu throttle migration parameters */ #define DEFAULT_MIGRATE_X_CPU_THROTTLE_INITIAL 20 #define DEFAULT_MIGRATE_X_CPU_THROTTLE_INCREMENT 10 /* Migration XBZRLE default cache size */ #define DEFAULT_MIGRATE_CACHE_SIZE (64 * 1024 * 1024) static NotifierList migration_state_notifiers = NOTIFIER_LIST_INITIALIZER(migration_state_notifiers); static bool deferred_incoming; /* * Current state of incoming postcopy; note this is not part of * MigrationIncomingState since it's state is used during cleanup * at the end as MIS is being freed. */ static PostcopyState incoming_postcopy_state; /* When we add fault tolerance, we could have several migrations at once. For now we don't need to add dynamic creation of migration */ /* For outgoing */ MigrationState *migrate_get_current(void) { static bool once; static MigrationState current_migration = { .state = MIGRATION_STATUS_NONE, .bandwidth_limit = MAX_THROTTLE, .xbzrle_cache_size = DEFAULT_MIGRATE_CACHE_SIZE, .mbps = -1, .parameters[MIGRATION_PARAMETER_COMPRESS_LEVEL] = DEFAULT_MIGRATE_COMPRESS_LEVEL, .parameters[MIGRATION_PARAMETER_COMPRESS_THREADS] = DEFAULT_MIGRATE_COMPRESS_THREAD_COUNT, .parameters[MIGRATION_PARAMETER_DECOMPRESS_THREADS] = DEFAULT_MIGRATE_DECOMPRESS_THREAD_COUNT, .parameters[MIGRATION_PARAMETER_X_CPU_THROTTLE_INITIAL] = DEFAULT_MIGRATE_X_CPU_THROTTLE_INITIAL, .parameters[MIGRATION_PARAMETER_X_CPU_THROTTLE_INCREMENT] = DEFAULT_MIGRATE_X_CPU_THROTTLE_INCREMENT, }; if (!once) { qemu_mutex_init(¤t_migration.src_page_req_mutex); once = true; } return ¤t_migration; } /* For incoming */ static MigrationIncomingState *mis_current; MigrationIncomingState *migration_incoming_get_current(void) { return mis_current; } MigrationIncomingState *migration_incoming_state_new(QEMUFile* f) { mis_current = g_new0(MigrationIncomingState, 1); mis_current->from_src_file = f; mis_current->state = MIGRATION_STATUS_NONE; QLIST_INIT(&mis_current->loadvm_handlers); qemu_mutex_init(&mis_current->rp_mutex); qemu_event_init(&mis_current->main_thread_load_event, false); return mis_current; } void migration_incoming_state_destroy(void) { qemu_event_destroy(&mis_current->main_thread_load_event); loadvm_free_handlers(mis_current); g_free(mis_current); mis_current = NULL; } typedef struct { bool optional; uint32_t size; uint8_t runstate[100]; RunState state; bool received; } GlobalState; static GlobalState global_state; int global_state_store(void) { if (!runstate_store((char *)global_state.runstate, sizeof(global_state.runstate))) { error_report("runstate name too big: %s", global_state.runstate); trace_migrate_state_too_big(); return -EINVAL; } return 0; } void global_state_store_running(void) { const char *state = RunState_lookup[RUN_STATE_RUNNING]; strncpy((char *)global_state.runstate, state, sizeof(global_state.runstate)); } static bool global_state_received(void) { return global_state.received; } static RunState global_state_get_runstate(void) { return global_state.state; } void global_state_set_optional(void) { global_state.optional = true; } static bool global_state_needed(void *opaque) { GlobalState *s = opaque; char *runstate = (char *)s->runstate; /* If it is not optional, it is mandatory */ if (s->optional == false) { return true; } /* If state is running or paused, it is not needed */ if (strcmp(runstate, "running") == 0 || strcmp(runstate, "paused") == 0) { return false; } /* for any other state it is needed */ return true; } static int global_state_post_load(void *opaque, int version_id) { GlobalState *s = opaque; Error *local_err = NULL; int r; char *runstate = (char *)s->runstate; s->received = true; trace_migrate_global_state_post_load(runstate); r = qapi_enum_parse(RunState_lookup, runstate, RUN_STATE__MAX, -1, &local_err); if (r == -1) { if (local_err) { error_report_err(local_err); } return -EINVAL; } s->state = r; return 0; } static void global_state_pre_save(void *opaque) { GlobalState *s = opaque; trace_migrate_global_state_pre_save((char *)s->runstate); s->size = strlen((char *)s->runstate) + 1; } static const VMStateDescription vmstate_globalstate = { .name = "globalstate", .version_id = 1, .minimum_version_id = 1, .post_load = global_state_post_load, .pre_save = global_state_pre_save, .needed = global_state_needed, .fields = (VMStateField[]) { VMSTATE_UINT32(size, GlobalState), VMSTATE_BUFFER(runstate, GlobalState), VMSTATE_END_OF_LIST() }, }; void register_global_state(void) { /* We would use it independently that we receive it */ strcpy((char *)&global_state.runstate, ""); global_state.received = false; vmstate_register(NULL, 0, &vmstate_globalstate, &global_state); } static void migrate_generate_event(int new_state) { if (migrate_use_events()) { qapi_event_send_migration(new_state, &error_abort); } } /* * Called on -incoming with a defer: uri. * The migration can be started later after any parameters have been * changed. */ static void deferred_incoming_migration(Error **errp) { if (deferred_incoming) { error_setg(errp, "Incoming migration already deferred"); } deferred_incoming = true; } /* Request a range of pages from the source VM at the given * start address. * rbname: Name of the RAMBlock to request the page in, if NULL it's the same * as the last request (a name must have been given previously) * Start: Address offset within the RB * Len: Length in bytes required - must be a multiple of pagesize */ void migrate_send_rp_req_pages(MigrationIncomingState *mis, const char *rbname, ram_addr_t start, size_t len) { uint8_t bufc[12 + 1 + 255]; /* start (8), len (4), rbname upto 256 */ size_t msglen = 12; /* start + len */ *(uint64_t *)bufc = cpu_to_be64((uint64_t)start); *(uint32_t *)(bufc + 8) = cpu_to_be32((uint32_t)len); if (rbname) { int rbname_len = strlen(rbname); assert(rbname_len < 256); bufc[msglen++] = rbname_len; memcpy(bufc + msglen, rbname, rbname_len); msglen += rbname_len; migrate_send_rp_message(mis, MIG_RP_MSG_REQ_PAGES_ID, msglen, bufc); } else { migrate_send_rp_message(mis, MIG_RP_MSG_REQ_PAGES, msglen, bufc); } } void qemu_start_incoming_migration(const char *uri, Error **errp) { const char *p; qapi_event_send_migration(MIGRATION_STATUS_SETUP, &error_abort); if (!strcmp(uri, "defer")) { deferred_incoming_migration(errp); } else if (strstart(uri, "tcp:", &p)) { tcp_start_incoming_migration(p, errp); #ifdef CONFIG_RDMA } else if (strstart(uri, "rdma:", &p)) { rdma_start_incoming_migration(p, errp); #endif #if !defined(WIN32) } else if (strstart(uri, "exec:", &p)) { exec_start_incoming_migration(p, errp); } else if (strstart(uri, "unix:", &p)) { unix_start_incoming_migration(p, errp); } else if (strstart(uri, "fd:", &p)) { fd_start_incoming_migration(p, errp); #endif } else { error_setg(errp, "unknown migration protocol: %s", uri); } } static void process_incoming_migration_bh(void *opaque) { Error *local_err = NULL; MigrationIncomingState *mis = opaque; /* Make sure all file formats flush their mutable metadata */ bdrv_invalidate_cache_all(&local_err); if (local_err) { migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE, MIGRATION_STATUS_FAILED); error_report_err(local_err); migrate_decompress_threads_join(); exit(EXIT_FAILURE); } /* * This must happen after all error conditions are dealt with and * we're sure the VM is going to be running on this host. */ qemu_announce_self(); /* If global state section was not received or we are in running state, we need to obey autostart. Any other state is set with runstate_set. */ if (!global_state_received() || global_state_get_runstate() == RUN_STATE_RUNNING) { if (autostart) { vm_start(); } else { runstate_set(RUN_STATE_PAUSED); } } else { runstate_set(global_state_get_runstate()); } migrate_decompress_threads_join(); /* * This must happen after any state changes since as soon as an external * observer sees this event they might start to prod at the VM assuming * it's ready to use. */ migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE, MIGRATION_STATUS_COMPLETED); qemu_bh_delete(mis->bh); migration_incoming_state_destroy(); } static void process_incoming_migration_co(void *opaque) { QEMUFile *f = opaque; MigrationIncomingState *mis; PostcopyState ps; int ret; mis = migration_incoming_state_new(f); postcopy_state_set(POSTCOPY_INCOMING_NONE); migrate_set_state(&mis->state, MIGRATION_STATUS_NONE, MIGRATION_STATUS_ACTIVE); ret = qemu_loadvm_state(f); ps = postcopy_state_get(); trace_process_incoming_migration_co_end(ret, ps); if (ps != POSTCOPY_INCOMING_NONE) { if (ps == POSTCOPY_INCOMING_ADVISE) { /* * Where a migration had postcopy enabled (and thus went to advise) * but managed to complete within the precopy period, we can use * the normal exit. */ postcopy_ram_incoming_cleanup(mis); } else if (ret >= 0) { /* * Postcopy was started, cleanup should happen at the end of the * postcopy thread. */ trace_process_incoming_migration_co_postcopy_end_main(); return; } /* Else if something went wrong then just fall out of the normal exit */ } qemu_fclose(f); free_xbzrle_decoded_buf(); if (ret < 0) { migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE, MIGRATION_STATUS_FAILED); error_report("load of migration failed: %s", strerror(-ret)); migrate_decompress_threads_join(); exit(EXIT_FAILURE); } mis->bh = qemu_bh_new(process_incoming_migration_bh, mis); qemu_bh_schedule(mis->bh); } void process_incoming_migration(QEMUFile *f) { Coroutine *co = qemu_coroutine_create(process_incoming_migration_co); int fd = qemu_get_fd(f); assert(fd != -1); migrate_decompress_threads_create(); qemu_set_nonblock(fd); qemu_coroutine_enter(co, f); } /* * Send a message on the return channel back to the source * of the migration. */ void migrate_send_rp_message(MigrationIncomingState *mis, enum mig_rp_message_type message_type, uint16_t len, void *data) { trace_migrate_send_rp_message((int)message_type, len); qemu_mutex_lock(&mis->rp_mutex); qemu_put_be16(mis->to_src_file, (unsigned int)message_type); qemu_put_be16(mis->to_src_file, len); qemu_put_buffer(mis->to_src_file, data, len); qemu_fflush(mis->to_src_file); qemu_mutex_unlock(&mis->rp_mutex); } /* * Send a 'SHUT' message on the return channel with the given value * to indicate that we've finished with the RP. Non-0 value indicates * error. */ void migrate_send_rp_shut(MigrationIncomingState *mis, uint32_t value) { uint32_t buf; buf = cpu_to_be32(value); migrate_send_rp_message(mis, MIG_RP_MSG_SHUT, sizeof(buf), &buf); } /* * Send a 'PONG' message on the return channel with the given value * (normally in response to a 'PING') */ void migrate_send_rp_pong(MigrationIncomingState *mis, uint32_t value) { uint32_t buf; buf = cpu_to_be32(value); migrate_send_rp_message(mis, MIG_RP_MSG_PONG, sizeof(buf), &buf); } /* amount of nanoseconds we are willing to wait for migration to be down. * the choice of nanoseconds is because it is the maximum resolution that * get_clock() can achieve. It is an internal measure. All user-visible * units must be in seconds */ static uint64_t max_downtime = 300000000; uint64_t migrate_max_downtime(void) { return max_downtime; } MigrationCapabilityStatusList *qmp_query_migrate_capabilities(Error **errp) { MigrationCapabilityStatusList *head = NULL
/*
 *  linux/arch/arm/mach-pxa/pxa27x.c
 *
 *  Author:	Nicolas Pitre
 *  Created:	Nov 05, 2002
 *  Copyright:	MontaVista Software Inc.
 *
 * Code specific to PXA27x aka Bulverde.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
#include <linux/gpio.h>
#include <linux/gpio-pxa.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/suspend.h>
#include <linux/platform_device.h>
#include <linux/syscore_ops.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/i2c/pxa-i2c.h>

#include <asm/mach/map.h>
#include <mach/hardware.h>
#include <asm/irq.h>
#include <asm/suspend.h>
#include <mach/irqs.h>
#include <mach/pxa27x.h>
#include <mach/reset.h>
#include <linux/platform_data/usb-ohci-pxa27x.h>
#include <mach/pm.h>
#include <mach/dma.h>
#include <mach/smemc.h>

#include "generic.h"
#include "devices.h"
#include <linux/clk-provider.h>
#include <linux/clkdev.h>

void pxa27x_clear_otgph(void)
{
	if (cpu_is_pxa27x() && (PSSR & PSSR_OTGPH))
		PSSR |= PSSR_OTGPH;
}
EXPORT_SYMBOL(pxa27x_clear_otgph);

static unsigned long ac97_reset_config[] = {
	GPIO113_AC97_nRESET_GPIO_HIGH,
	GPIO113_AC97_nRESET,
	GPIO95_AC97_nRESET_GPIO_HIGH,
	GPIO95_AC97_nRESET,
};

void pxa27x_configure_ac97reset(int reset_gpio, bool to_gpio)
{
	/*
	 * This helper function is used to work around a bug in the pxa27x's
	 * ac97 controller during a warm reset.  The configuration of the
	 * reset_gpio is changed as follows:
	 * to_gpio == true: configured to generic output gpio and driven high
	 * to_gpio == false: configured to ac97 controller alt fn AC97_nRESET
	 */

	if (reset_gpio == 113)
		pxa2xx_mfp_config(to_gpio ? &ac97_reset_config[0] :
				  &ac97_reset_config[1], 1);

	if (reset_gpio == 95)
		pxa2xx_mfp_config(to_gpio ? &ac97_reset_config[2] :
				  &ac97_reset_config[3], 1);
}
EXPORT_SYMBOL_GPL(pxa27x_configure_ac97reset);

#ifdef CONFIG_PM

#define SAVE(x)		sleep_save[SLEEP_SAVE_##x] = x
#define RESTORE(x)	x = sleep_save[SLEEP_SAVE_##x]

/*
 * allow platforms to override default PWRMODE setting used for PM_SUSPEND_MEM
 */
static unsigned int pwrmode = PWRMODE_SLEEP;

int pxa27x_set_pwrmode(unsigned int mode)
{
	switch (mode) {
	case PWRMODE_SLEEP:
	case PWRMODE_DEEPSLEEP:
		pwrmode = mode;
		return 0;
	}

	return -EINVAL;
}

/*
 * List of global PXA peripheral registers to preserve.
 * More ones like CP and general purpose register values are preserved
 * with the stack pointer in sleep.S.
 */
enum {
	SLEEP_SAVE_PSTR,
	SLEEP_SAVE_MDREFR,
	SLEEP_SAVE_PCFR,
	SLEEP_SAVE_COUNT
};

void pxa27x_cpu_pm_save(unsigned long *sleep_save)
{
	sleep_save[SLEEP_SAVE_MDREFR] = __raw_readl(MDREFR);
	SAVE(PCFR);

	SAVE(PSTR);
}

void pxa27x_cpu_pm_restore(unsigned long *sleep_save)
{
	__raw_writel(sleep_save[SLEEP_SAVE_MDREFR], MDREFR);
	RESTORE(PCFR);

	PSSR = PSSR_RDH | PSSR_PH;

	RESTORE(PSTR);
}

void pxa27x_cpu_pm_enter(suspend_state_t state)
{
	extern void pxa_cpu_standby(void);
#ifndef CONFIG_IWMMXT
	u64 acc0;

	asm volatile("mra %Q0, %R0, acc0" : "=r" (acc0));
#endif

	/* ensure voltage-change sequencer not initiated, which hangs */
	PCFR &= ~PCFR_FVC;

	/* Clear edge-detect status register. */
	PEDR = 0xDF12FE1B;

	/* Clear reset status */
	RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;

	switch (state) {
	case PM_SUSPEND_STANDBY:
		pxa_cpu_standby();
		break;
	case PM_SUSPEND_MEM:
		cpu_suspend(pwrmode, pxa27x_finish_suspend);
#ifndef CONFIG_IWMMXT
		asm volatile("mar acc0, %Q0, %R0" : "=r" (acc0));
#endif
		break;
	}
}

static int pxa27x_cpu_pm_valid(suspend_state_t state)
{
	return state == PM_SUSPEND_MEM || state == PM_SUSPEND_STANDBY;
}

static int pxa27x_cpu_pm_prepare(void)
{
	/* set resume return address */
	PSPR = virt_to_phys(cpu_resume);
	return 0;
}

static void pxa27x_cpu_pm_finish(void)
{
	/* ensure not to come back here if it wasn't intended */
	PSPR = 0;
}

static struct pxa_cpu_pm_fns pxa27x_cpu_pm_fns = {
	.save_count	= SLEEP_SAVE_COUNT,
	.save		= pxa27x_cpu_pm_save,
	.restore	= pxa27x_cpu_pm_restore,
	.valid		= pxa27x_cpu_pm_valid,
	.enter		= pxa27x_cpu_pm_enter,
	.prepare	= pxa27x_cpu_pm_prepare,
	.finish		= pxa27x_cpu_pm_finish,
};

static void __init pxa27x_init_pm(void)
{
	pxa_cpu_pm_fns = &pxa27x_cpu_pm_fns;
}
#else
static inline void pxa27x_init_pm(void) {}
#endif

/* PXA27x:  Various gpios can issue wakeup events.  This logic only
 * handles the simple cases, not the WEMUX2 and WEMUX3 options
 */
static int pxa27x_set_wake(struct irq_data *d, unsigned int on)
{
	int gpio = pxa_irq_to_gpio(d->irq);
	uint32_t mask;

	if (gpio >= 0 && gpio < 128)
		return gpio_set_wake(gpio, on);

	if (d->irq == IRQ_KEYPAD)
		return keypad_set_wake(on);

	switch (d->irq) {
	case IRQ_RTCAlrm:
		mask = PWER_RTC;
		break;
	case IRQ_USB:
		mask = 1u << 26;
		break;
	default:
		return -EINVAL;
	}

	if (on)
		PWER |= mask;
	else
		PWER &=~mask;

	return 0;
}

void __init pxa27x_init_irq(void)
{
	pxa_init_irq(34, pxa27x_set_wake);
}

void __init pxa27x_dt_init_irq(void)
{
	if (IS_ENABLED(CONFIG_OF))
		pxa_dt_irq_init(pxa27x_set_wake);
}

static struct map_desc pxa27x_io_desc[] __initdata = {
	{	/* Mem Ctl */
		.virtual	= (unsigned long)SMEMC_VIRT,
		.pfn		= __phys_to_pfn(PXA2XX_SMEMC_BASE),
		.length		= SMEMC_SIZE,
		.type		= MT_DEVICE
	}, {	/* UNCACHED_PHYS_0 */
		.virtual	= UNCACHED_PHYS_0,
		.pfn		= __phys_to_pfn(0x00000000),
		.length		= UNCACHED_PHYS_0_SIZE,
		.type		= MT_DEVICE
	},
};

void __init pxa27x_map_io(void)
{
	pxa_map_io();
	iotable_init(ARRAY_AND_SIZE(pxa27x_io_desc));
	pxa27x_get_clk_frequency_khz(1);
}

/*
 * device registration specific to PXA27x.
 */
void __init pxa27x_set_i2c_power_info(struct i2c_pxa_platform_data *info)
{
	local_irq_disable();
	PCFR |= PCFR_PI2CEN;
	local_irq_enable();
	pxa_register_device(&pxa27x_device_i2c_power, info);
}

static struct pxa_gpio_platform_data pxa27x_gpio_info __initdata = {
	.irq_base	= PXA_GPIO_TO_IRQ(0),
	.gpio_set_wake	= gpio_set_wake,
};

static struct platform_device *devices[] __initdata = {
	&pxa27x_device_udc,
	&pxa_device_pmu,
	&pxa_device_i2s,
	&pxa_device_asoc_ssp1,
	&pxa_device_asoc_ssp2,
	&pxa_device_asoc_ssp3,
	&pxa_device_asoc_platform,
	&pxa_device_rtc,
	&pxa27x_device_ssp1,
	&pxa27x_device_ssp2,
	&pxa27x_device_ssp3,
	&pxa27x_device_pwm0,
	&pxa27x_device_pwm1,
};

static int __init pxa27x_init(void)
{
	int ret = 0;

	if (cpu_is_pxa27x()) {

		reset_status = RCSR;

		if ((ret = pxa_init_dma(IRQ_DMA, 32)))
			return ret;

		pxa27x_init_pm();

		register_syscore_ops(&pxa_irq_syscore_ops);
		register_syscore_ops(&pxa2xx_mfp_syscore_ops);

		if (!of_have_populated_dt()) {
			pxa_register_device(&pxa27x_device_gpio,
					    &pxa27x_gpio_info);
			pxa2xx_set_dmac_info(32);
			ret = platform_add_devices(devices,
						   ARRAY_SIZE(devices));
		}
	}

	return ret;
}

postcore_initcall(pxa27x_init);
/ 1000000; s->mbps = (((double) transferred_bytes * 8.0) / ((double) time_spent / 1000.0)) / 1000.0 / 1000.0; trace_migrate_transferred(transferred_bytes, time_spent, bandwidth, max_size); /* if we haven't sent anything, we don't want to recalculate 10000 is a small enough number for our purposes */ if (s->dirty_bytes_rate && transferred_bytes > 10000) { s->expected_downtime = s->dirty_bytes_rate / bandwidth; } qemu_file_reset_rate_limit(s->to_dst_file); initial_time = current_time; initial_bytes = qemu_ftell(s->to_dst_file); } if (qemu_file_rate_limit(s->to_dst_file)) { /* usleep expects microseconds */ g_usleep((initial_time + BUFFER_DELAY - current_time)*1000); } } trace_migration_thread_after_loop(); /* If we enabled cpu throttling for auto-converge, turn it off. */ cpu_throttle_stop(); end_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); qemu_mutex_lock_iothread(); qemu_savevm_state_cleanup(); if (s->state == MIGRATION_STATUS_COMPLETED) { uint64_t transferred_bytes = qemu_ftell(s->to_dst_file); s->total_time = end_time - s->total_time; if (!entered_postcopy) { s->downtime = end_time - start_time; } if (s->total_time) { s->mbps = (((double) transferred_bytes * 8.0) / ((double) s->total_time)) / 1000; } runstate_set(RUN_STATE_POSTMIGRATE); } else { if (old_vm_running && !entered_postcopy) { vm_start(); } } qemu_bh_schedule(s->cleanup_bh); qemu_mutex_unlock_iothread(); rcu_unregister_thread(); return NULL; } void migrate_fd_connect(MigrationState *s) { /* This is a best 1st approximation. ns to ms */ s->expected_downtime = max_downtime/1000000; s->cleanup_bh = qemu_bh_new(migrate_fd_cleanup, s); qemu_file_set_rate_limit(s->to_dst_file, s->bandwidth_limit / XFER_LIMIT_RATIO); /* Notify before starting migration thread */ notifier_list_notify(&migration_state_notifiers, s); /* * Open the return path; currently for postcopy but other things might * also want it. */ if (migrate_postcopy_ram()) { if (open_return_path_on_source(s)) { error_report("Unable to open return-path for postcopy"); migrate_set_state(&s->state, MIGRATION_STATUS_SETUP, MIGRATION_STATUS_FAILED); migrate_fd_cleanup(s); return; } } migrate_compress_threads_create(); qemu_thread_create(&s->thread, "migration", migration_thread, s, QEMU_THREAD_JOINABLE); s->migration_thread_running = true; } PostcopyState postcopy_state_get(void) { return atomic_mb_read(&incoming_postcopy_state); } /* Set the state and return the old state */ PostcopyState postcopy_state_set(PostcopyState new_state) { return atomic_xchg(&incoming_postcopy_state, new_state); }