@@ -208,10 +208,38 @@ void memory_region_filter_subregions(MemoryRegion *mr, int32_t level)
208
208
memory_region_transaction_commit (mr );
209
209
}
210
210
211
- void memory_unmap (struct uc_struct * uc , MemoryRegion * mr )
211
+ static void memory_region_remove_mapped_block (struct uc_struct * uc , MemoryRegion * mr , bool free )
212
+ {
213
+ size_t i ;
214
+ for (i = 0 ; i < uc -> mapped_block_count ; i ++ ) {
215
+ if (uc -> mapped_blocks [i ] == mr ) {
216
+ uc -> mapped_block_count -- ;
217
+ //shift remainder of array down over deleted pointer
218
+ memmove (& uc -> mapped_blocks [i ], & uc -> mapped_blocks [i + 1 ], sizeof (MemoryRegion * ) * (uc -> mapped_block_count - i ));
219
+ if (free ) {
220
+ mr -> destructor (mr );
221
+ g_free (mr );
222
+ }
223
+ break ;
224
+ }
225
+ }
226
+ }
227
+
228
+ void memory_moveout (struct uc_struct * uc , MemoryRegion * mr )
212
229
{
213
- int i ;
214
230
hwaddr addr ;
231
+ /* A bit dirty, but it works.
232
+ * The first subregion will be the one with the smalest priority.
233
+ * In case of CoW this will always be the region which is mapped initial and later be moved in the subregion of the container.
234
+ * The initial subregion is the one stored in mapped_blocks
235
+ * Because CoW is done after the snapshot level is increased there is only on subregion with
236
+ */
237
+ memory_region_transaction_begin ();
238
+ MemoryRegion * mr_block = QTAILQ_FIRST (& mr -> subregions );
239
+
240
+ if (!mr_block ) {
241
+ mr_block = mr ;
242
+ }
215
243
216
244
if (uc -> cpu ) {
217
245
// We also need to remove all tb cache
@@ -223,18 +251,40 @@ void memory_unmap(struct uc_struct *uc, MemoryRegion *mr)
223
251
tlb_flush_page (uc -> cpu , addr );
224
252
}
225
253
}
254
+
226
255
memory_region_del_subregion (uc -> system_memory , mr );
256
+ g_array_append_val (uc -> unmapped_regions , mr );
257
+ memory_region_remove_mapped_block (uc , mr_block , false);
258
+ uc -> memory_region_update_pending = true;
259
+ memory_region_transaction_commit (uc -> system_memory );
260
+ /* dirty hack to save the snapshot level */
261
+ mr -> container = (void * )(intptr_t )uc -> snapshot_level ;
262
+ }
227
263
228
- for (i = 0 ; i < uc -> mapped_block_count ; i ++ ) {
229
- if (uc -> mapped_blocks [i ] == mr ) {
230
- uc -> mapped_block_count -- ;
231
- //shift remainder of array down over deleted pointer
232
- memmove (& uc -> mapped_blocks [i ], & uc -> mapped_blocks [i + 1 ], sizeof (MemoryRegion * ) * (uc -> mapped_block_count - i ));
233
- mr -> destructor (mr );
234
- g_free (mr );
235
- break ;
264
+ void memory_movein (struct uc_struct * uc , MemoryRegion * mr )
265
+ {
266
+ memory_region_transaction_begin ();
267
+ memory_region_add_subregion_overlap (uc -> system_memory , mr -> addr , mr , mr -> priority );
268
+ uc -> memory_region_update_pending = true;
269
+ memory_region_transaction_commit (uc -> system_memory );
270
+ }
271
+
272
+ void memory_unmap (struct uc_struct * uc , MemoryRegion * mr )
273
+ {
274
+ hwaddr addr ;
275
+
276
+ if (uc -> cpu ) {
277
+ // We also need to remove all tb cache
278
+ uc -> uc_invalidate_tb (uc , mr -> addr , int128_get64 (mr -> size ));
279
+
280
+ // Make sure all pages associated with the MemoryRegion are flushed
281
+ // Only need to do this if we are in a running state
282
+ for (addr = mr -> addr ; (int64_t )(mr -> end - addr ) > 0 ; addr += uc -> target_page_size ) {
283
+ tlb_flush_page (uc -> cpu , addr );
236
284
}
237
285
}
286
+ memory_region_del_subregion (uc -> system_memory , mr );
287
+ memory_region_remove_mapped_block (uc , mr , true);
238
288
}
239
289
240
290
int memory_free (struct uc_struct * uc )
0 commit comments