mirror of https://github.com/xemu-project/xemu.git
savevm: Use RAM blocks for basis of migration
We don't want to assume a contiguous address space, so migrate based on RAM blocks instead of a fixed linear address map. This will allow us to have holes in the ram_addr_t namespace, so we can implement qemu_ram_free(). Signed-off-by: Alex Williamson <alex.williamson@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
parent
97ab12d466
commit
e44359c35e
59
arch_init.c
59
arch_init.c
|
@ -105,27 +105,26 @@ static int is_dup_page(uint8_t *page, uint8_t ch)
|
|||
|
||||
static int ram_save_block(QEMUFile *f)
|
||||
{
|
||||
static ram_addr_t current_addr = 0;
|
||||
ram_addr_t saved_addr = current_addr;
|
||||
ram_addr_t addr = 0;
|
||||
uint64_t total_ram = ram_bytes_total();
|
||||
static RAMBlock *last_block = NULL;
|
||||
static ram_addr_t last_offset = 0;
|
||||
RAMBlock *block = last_block;
|
||||
ram_addr_t offset = last_offset;
|
||||
ram_addr_t current_addr;
|
||||
int bytes_sent = 0;
|
||||
|
||||
while (addr < total_ram) {
|
||||
if (!block)
|
||||
block = QLIST_FIRST(&ram_list.blocks);
|
||||
|
||||
current_addr = block->offset + offset;
|
||||
|
||||
do {
|
||||
if (cpu_physical_memory_get_dirty(current_addr, MIGRATION_DIRTY_FLAG)) {
|
||||
RAMBlock *block;
|
||||
ram_addr_t offset;
|
||||
uint8_t *p;
|
||||
|
||||
cpu_physical_memory_reset_dirty(current_addr,
|
||||
current_addr + TARGET_PAGE_SIZE,
|
||||
MIGRATION_DIRTY_FLAG);
|
||||
|
||||
QLIST_FOREACH(block, &ram_list.blocks, next) {
|
||||
if (current_addr - block->offset < block->length)
|
||||
break;
|
||||
}
|
||||
offset = current_addr - block->offset;
|
||||
p = block->host + offset;
|
||||
|
||||
if (is_dup_page(p, *p)) {
|
||||
|
@ -146,10 +145,22 @@ static int ram_save_block(QEMUFile *f)
|
|||
|
||||
break;
|
||||
}
|
||||
addr += TARGET_PAGE_SIZE;
|
||||
current_addr = (saved_addr + addr) % total_ram;
|
||||
|
||||
offset += TARGET_PAGE_SIZE;
|
||||
if (offset >= block->length) {
|
||||
offset = 0;
|
||||
block = QLIST_NEXT(block, next);
|
||||
if (!block)
|
||||
block = QLIST_FIRST(&ram_list.blocks);
|
||||
}
|
||||
|
||||
current_addr = block->offset + offset;
|
||||
|
||||
} while (current_addr != last_block->offset + last_offset);
|
||||
|
||||
last_block = block;
|
||||
last_offset = offset;
|
||||
|
||||
return bytes_sent;
|
||||
}
|
||||
|
||||
|
@ -157,15 +168,18 @@ static uint64_t bytes_transferred;
|
|||
|
||||
static ram_addr_t ram_save_remaining(void)
|
||||
{
|
||||
ram_addr_t addr;
|
||||
RAMBlock *block;
|
||||
ram_addr_t count = 0;
|
||||
uint64_t total_ram = ram_bytes_total();
|
||||
|
||||
for (addr = 0; addr < total_ram; addr += TARGET_PAGE_SIZE) {
|
||||
QLIST_FOREACH(block, &ram_list.blocks, next) {
|
||||
ram_addr_t addr;
|
||||
for (addr = block->offset; addr < block->offset + block->length;
|
||||
addr += TARGET_PAGE_SIZE) {
|
||||
if (cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
@ -210,20 +224,23 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
|
|||
|
||||
if (stage == 1) {
|
||||
RAMBlock *block;
|
||||
uint64_t total_ram = ram_bytes_total();
|
||||
bytes_transferred = 0;
|
||||
|
||||
/* Make sure all dirty bits are set */
|
||||
for (addr = 0; addr < total_ram; addr += TARGET_PAGE_SIZE) {
|
||||
if (!cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) {
|
||||
QLIST_FOREACH(block, &ram_list.blocks, next) {
|
||||
for (addr = block->offset; addr < block->offset + block->length;
|
||||
addr += TARGET_PAGE_SIZE) {
|
||||
if (!cpu_physical_memory_get_dirty(addr,
|
||||
MIGRATION_DIRTY_FLAG)) {
|
||||
cpu_physical_memory_set_dirty(addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable dirty memory tracking */
|
||||
cpu_physical_memory_set_dirty_tracking(1);
|
||||
|
||||
qemu_put_be64(f, total_ram | RAM_SAVE_FLAG_MEM_SIZE);
|
||||
qemu_put_be64(f, ram_bytes_total() | RAM_SAVE_FLAG_MEM_SIZE);
|
||||
|
||||
QLIST_FOREACH(block, &ram_list.blocks, next) {
|
||||
qemu_put_byte(f, strlen(block->idstr));
|
||||
|
|
Loading…
Reference in New Issue