Revision e44359c3
b/arch_init.c | ||
---|---|---|
105 | 105 |
|
106 | 106 |
static int ram_save_block(QEMUFile *f) |
107 | 107 |
{ |
108 |
static ram_addr_t current_addr = 0; |
|
109 |
ram_addr_t saved_addr = current_addr; |
|
110 |
ram_addr_t addr = 0; |
|
111 |
uint64_t total_ram = ram_bytes_total(); |
|
108 |
static RAMBlock *last_block = NULL; |
|
109 |
static ram_addr_t last_offset = 0; |
|
110 |
RAMBlock *block = last_block; |
|
111 |
ram_addr_t offset = last_offset; |
|
112 |
ram_addr_t current_addr; |
|
112 | 113 |
int bytes_sent = 0; |
113 | 114 |
|
114 |
while (addr < total_ram) { |
|
115 |
if (!block) |
|
116 |
block = QLIST_FIRST(&ram_list.blocks); |
|
117 |
|
|
118 |
current_addr = block->offset + offset; |
|
119 |
|
|
120 |
do { |
|
115 | 121 |
if (cpu_physical_memory_get_dirty(current_addr, MIGRATION_DIRTY_FLAG)) { |
116 |
RAMBlock *block; |
|
117 |
ram_addr_t offset; |
|
118 | 122 |
uint8_t *p; |
119 | 123 |
|
120 | 124 |
cpu_physical_memory_reset_dirty(current_addr, |
121 | 125 |
current_addr + TARGET_PAGE_SIZE, |
122 | 126 |
MIGRATION_DIRTY_FLAG); |
123 | 127 |
|
124 |
QLIST_FOREACH(block, &ram_list.blocks, next) { |
|
125 |
if (current_addr - block->offset < block->length) |
|
126 |
break; |
|
127 |
} |
|
128 |
offset = current_addr - block->offset; |
|
129 | 128 |
p = block->host + offset; |
130 | 129 |
|
131 | 130 |
if (is_dup_page(p, *p)) { |
... | ... | |
146 | 145 |
|
147 | 146 |
break; |
148 | 147 |
} |
149 |
addr += TARGET_PAGE_SIZE; |
|
150 |
current_addr = (saved_addr + addr) % total_ram; |
|
151 |
} |
|
148 |
|
|
149 |
offset += TARGET_PAGE_SIZE; |
|
150 |
if (offset >= block->length) { |
|
151 |
offset = 0; |
|
152 |
block = QLIST_NEXT(block, next); |
|
153 |
if (!block) |
|
154 |
block = QLIST_FIRST(&ram_list.blocks); |
|
155 |
} |
|
156 |
|
|
157 |
current_addr = block->offset + offset; |
|
158 |
|
|
159 |
} while (current_addr != last_block->offset + last_offset); |
|
160 |
|
|
161 |
last_block = block; |
|
162 |
last_offset = offset; |
|
152 | 163 |
|
153 | 164 |
return bytes_sent; |
154 | 165 |
} |
... | ... | |
157 | 168 |
|
158 | 169 |
static ram_addr_t ram_save_remaining(void) |
159 | 170 |
{ |
160 |
ram_addr_t addr;
|
|
171 |
RAMBlock *block;
|
|
161 | 172 |
ram_addr_t count = 0; |
162 |
uint64_t total_ram = ram_bytes_total(); |
|
163 | 173 |
|
164 |
for (addr = 0; addr < total_ram; addr += TARGET_PAGE_SIZE) { |
|
165 |
if (cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) { |
|
166 |
count++; |
|
174 |
QLIST_FOREACH(block, &ram_list.blocks, next) { |
|
175 |
ram_addr_t addr; |
|
176 |
for (addr = block->offset; addr < block->offset + block->length; |
|
177 |
addr += TARGET_PAGE_SIZE) { |
|
178 |
if (cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) { |
|
179 |
count++; |
|
180 |
} |
|
167 | 181 |
} |
168 | 182 |
} |
169 | 183 |
|
... | ... | |
210 | 224 |
|
211 | 225 |
if (stage == 1) { |
212 | 226 |
RAMBlock *block; |
213 |
uint64_t total_ram = ram_bytes_total(); |
|
214 | 227 |
bytes_transferred = 0; |
215 | 228 |
|
216 | 229 |
/* Make sure all dirty bits are set */ |
217 |
for (addr = 0; addr < total_ram; addr += TARGET_PAGE_SIZE) { |
|
218 |
if (!cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) { |
|
219 |
cpu_physical_memory_set_dirty(addr); |
|
230 |
QLIST_FOREACH(block, &ram_list.blocks, next) { |
|
231 |
for (addr = block->offset; addr < block->offset + block->length; |
|
232 |
addr += TARGET_PAGE_SIZE) { |
|
233 |
if (!cpu_physical_memory_get_dirty(addr, |
|
234 |
MIGRATION_DIRTY_FLAG)) { |
|
235 |
cpu_physical_memory_set_dirty(addr); |
|
236 |
} |
|
220 | 237 |
} |
221 | 238 |
} |
222 | 239 |
|
223 | 240 |
/* Enable dirty memory tracking */ |
224 | 241 |
cpu_physical_memory_set_dirty_tracking(1); |
225 | 242 |
|
226 |
qemu_put_be64(f, total_ram | RAM_SAVE_FLAG_MEM_SIZE);
|
|
243 |
qemu_put_be64(f, ram_bytes_total() | RAM_SAVE_FLAG_MEM_SIZE);
|
|
227 | 244 |
|
228 | 245 |
QLIST_FOREACH(block, &ram_list.blocks, next) { |
229 | 246 |
qemu_put_byte(f, strlen(block->idstr)); |
Also available in: Unified diff