[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v2 12/16] savevm: Use RAM blocks for basis of migrat
From: |
Alex Williamson |
Subject: |
[Qemu-devel] [PATCH v2 12/16] savevm: Use RAM blocks for basis of migration |
Date: |
Fri, 25 Jun 2010 11:09:57 -0600 |
User-agent: |
StGIT/0.14.3 |
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 <address@hidden>
---
arch_init.c | 67 +++++++++++++++++++++++++++++++++++++----------------------
1 files changed, 42 insertions(+), 25 deletions(-)
diff --git a/arch_init.c b/arch_init.c
index 37aad9d..186645b 100644
--- a/arch_init.c
+++ b/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,9 +145,21 @@ 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,13 +168,16 @@ 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) {
- if (cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) {
- count++;
+ 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++;
+ }
}
}
@@ -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)) {
- cpu_physical_memory_set_dirty(addr);
+ 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));
- [Qemu-devel] [PATCH 15/15] ramblocks: No more being lazy about duplicate names, (continued)
- [Qemu-devel] [PATCH v2 00/16] Make migration work with hotplug, Alex Williamson, 2010/06/25
- [Qemu-devel] [PATCH v2 16/16] ramblocks: No more being lazy about duplicate names, Alex Williamson, 2010/06/25
- [Qemu-devel] [PATCH v2 14/16] qemu_ram_free: Implement it, Alex Williamson, 2010/06/25
- [Qemu-devel] [PATCH v2 15/16] pci: Free the space allocated for the option rom on removal, Alex Williamson, 2010/06/25
- [Qemu-devel] [PATCH v2 13/16] savevm: Create a new continue flag to avoid resending block name, Alex Williamson, 2010/06/25
- [Qemu-devel] [PATCH v2 12/16] savevm: Use RAM blocks for basis of migration,
Alex Williamson <=
- [Qemu-devel] [PATCH v2 10/16] ramblocks: Make use of DeviceState pointer and BusInfo.get_dev_path, Alex Williamson, 2010/06/25
- [Qemu-devel] [PATCH v2 11/16] savevm: Migrate RAM based on name/offset, Alex Williamson, 2010/06/25
- [Qemu-devel] [PATCH v2 07/16] eepro100: Add a dev field to eeprom new/free functions, Alex Williamson, 2010/06/25
- [Qemu-devel] [PATCH v2 08/16] virtio-net: Incorporate a DeviceState pointer and let savevm track instances, Alex Williamson, 2010/06/25
- [Qemu-devel] [PATCH v2 09/16] qemu_ram_alloc: Add DeviceState and name parameters, Alex Williamson, 2010/06/25
- [Qemu-devel] [PATCH v2 06/16] savevm: Make use of DeviceState, Alex Williamson, 2010/06/25
- [Qemu-devel] [PATCH v2 04/16] pci: Implement BusInfo.get_dev_path(), Alex Williamson, 2010/06/25
- [Qemu-devel] [PATCH v2 02/16] pc: Allocate all ram in a single qemu_ram_alloc(), Alex Williamson, 2010/06/25
- [Qemu-devel] [PATCH v2 05/16] savevm: Add DeviceState param, Alex Williamson, 2010/06/25
- [Qemu-devel] [PATCH v2 01/16] Remove uses of ram.last_offset (aka last_ram_offset), Alex Williamson, 2010/06/25