Skip to content

Commit df18756

Browse files
committed
implement uc_mem_unmap with snapshots
still has todos and need tests
1 parent 716c8f1 commit df18756

23 files changed

+198
-17
lines changed

include/uc_priv.h

+3
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,8 @@ struct uc_struct {
289289
uc_memory_mapping_t memory_mapping;
290290
uc_memory_filter_t memory_filter_subregions;
291291
uc_mem_unmap_t memory_unmap;
292+
uc_mem_unmap_t memory_moveout;
293+
uc_mem_unmap_t memory_movein;
292294
uc_readonly_mem_t readonly_mem;
293295
uc_cpus_init cpus_init;
294296
uc_target_page_init target_page;
@@ -412,6 +414,7 @@ struct uc_struct {
412414
PVOID seh_handle;
413415
void *seh_closure;
414416
#endif
417+
GArray *unmapped_regions;
415418
int32_t snapshot_level;
416419
};
417420

qemu/aarch64.h

+2
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@
125125
#define memory_map_ptr memory_map_ptr_aarch64
126126
#define memory_cow memory_cow_aarch64
127127
#define memory_unmap memory_unmap_aarch64
128+
#define memory_moveout memory_moveout_aarch64
129+
#define memory_movein memory_movein_aarch64
128130
#define memory_free memory_free_aarch64
129131
#define flatview_unref flatview_unref_aarch64
130132
#define address_space_get_flatview address_space_get_flatview_aarch64

qemu/arm.h

+2
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@
125125
#define memory_map_ptr memory_map_ptr_arm
126126
#define memory_cow memory_cow_arm
127127
#define memory_unmap memory_unmap_arm
128+
#define memory_moveout memory_moveout_arm
129+
#define memory_movein memory_movein_arm
128130
#define memory_free memory_free_arm
129131
#define flatview_unref flatview_unref_arm
130132
#define address_space_get_flatview address_space_get_flatview_arm

qemu/include/exec/memory.h

+2
Original file line numberDiff line numberDiff line change
@@ -1217,6 +1217,8 @@ MemoryRegion *memory_map_ptr(struct uc_struct *uc, hwaddr begin, size_t size, ui
12171217
uc_cb_mmio_write_t write_cb, void *user_data_read, void *user_data_write);
12181218
MemoryRegion *memory_cow(struct uc_struct *uc, MemoryRegion *parrent, hwaddr begin, size_t size);
12191219
void memory_unmap(struct uc_struct *uc, MemoryRegion *mr);
1220+
void memory_moveout(struct uc_struct *uc, MemoryRegion *mr);
1221+
void memory_movein(struct uc_struct *uc, MemoryRegion *mr);
12201222
int memory_free(struct uc_struct *uc);
12211223

12221224
#endif

qemu/m68k.h

+2
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@
125125
#define memory_map_ptr memory_map_ptr_m68k
126126
#define memory_cow memory_cow_m68k
127127
#define memory_unmap memory_unmap_m68k
128+
#define memory_moveout memory_moveout_m68k
129+
#define memory_movein memory_movein_m68k
128130
#define memory_free memory_free_m68k
129131
#define flatview_unref flatview_unref_m68k
130132
#define address_space_get_flatview address_space_get_flatview_m68k

qemu/mips.h

+2
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@
125125
#define memory_map_ptr memory_map_ptr_mips
126126
#define memory_cow memory_cow_mips
127127
#define memory_unmap memory_unmap_mips
128+
#define memory_moveout memory_moveout_mips
129+
#define memory_movein memory_movein_mips
128130
#define memory_free memory_free_mips
129131
#define flatview_unref flatview_unref_mips
130132
#define address_space_get_flatview address_space_get_flatview_mips

qemu/mips64.h

+2
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@
125125
#define memory_map_ptr memory_map_ptr_mips64
126126
#define memory_cow memory_cow_mips64
127127
#define memory_unmap memory_unmap_mips64
128+
#define memory_moveout memory_moveout_mips64
129+
#define memory_movein memory_movein_mips64
128130
#define memory_free memory_free_mips64
129131
#define flatview_unref flatview_unref_mips64
130132
#define address_space_get_flatview address_space_get_flatview_mips64

qemu/mips64el.h

+2
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@
125125
#define memory_map_ptr memory_map_ptr_mips64el
126126
#define memory_cow memory_cow_mips64el
127127
#define memory_unmap memory_unmap_mips64el
128+
#define memory_moveout memory_moveout_mips64el
129+
#define memory_movein memory_movein_mips64el
128130
#define memory_free memory_free_mips64el
129131
#define flatview_unref flatview_unref_mips64el
130132
#define address_space_get_flatview address_space_get_flatview_mips64el

qemu/mipsel.h

+2
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@
125125
#define memory_map_ptr memory_map_ptr_mipsel
126126
#define memory_cow memory_cow_mipsel
127127
#define memory_unmap memory_unmap_mipsel
128+
#define memory_moveout memory_moveout_mipsel
129+
#define memory_movein memory_movein_mipsel
128130
#define memory_free memory_free_mipsel
129131
#define flatview_unref flatview_unref_mipsel
130132
#define address_space_get_flatview address_space_get_flatview_mipsel

qemu/ppc.h

+2
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@
125125
#define memory_map_ptr memory_map_ptr_ppc
126126
#define memory_cow memory_cow_ppc
127127
#define memory_unmap memory_unmap_ppc
128+
#define memory_moveout memory_moveout_ppc
129+
#define memory_movein memory_movein_ppc
128130
#define memory_free memory_free_ppc
129131
#define flatview_unref flatview_unref_ppc
130132
#define address_space_get_flatview address_space_get_flatview_ppc

qemu/ppc64.h

+2
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@
125125
#define memory_map_ptr memory_map_ptr_ppc64
126126
#define memory_cow memory_cow_ppc64
127127
#define memory_unmap memory_unmap_ppc64
128+
#define memory_moveout memory_moveout_ppc64
129+
#define memory_movein memory_movein_ppc64
128130
#define memory_free memory_free_ppc64
129131
#define flatview_unref flatview_unref_ppc64
130132
#define address_space_get_flatview address_space_get_flatview_ppc64

qemu/riscv32.h

+2
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@
125125
#define memory_map_ptr memory_map_ptr_riscv32
126126
#define memory_cow memory_cow_riscv32
127127
#define memory_unmap memory_unmap_riscv32
128+
#define memory_moveout memory_moveout_riscv32
129+
#define memory_movein memory_movein_riscv32
128130
#define memory_free memory_free_riscv32
129131
#define flatview_unref flatview_unref_riscv32
130132
#define address_space_get_flatview address_space_get_flatview_riscv32

qemu/riscv64.h

+2
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@
125125
#define memory_map_ptr memory_map_ptr_riscv64
126126
#define memory_cow memory_cow_riscv64
127127
#define memory_unmap memory_unmap_riscv64
128+
#define memory_moveout memory_moveout_riscv64
129+
#define memory_movein memory_movein_riscv64
128130
#define memory_free memory_free_riscv64
129131
#define flatview_unref flatview_unref_riscv64
130132
#define address_space_get_flatview address_space_get_flatview_riscv64

qemu/s390x.h

+2
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@
125125
#define memory_map_ptr memory_map_ptr_s390x
126126
#define memory_cow memory_cow_s390x
127127
#define memory_unmap memory_unmap_s390x
128+
#define memory_moveout memory_moveout_s390x
129+
#define memory_movein memory_movein_s390x
128130
#define memory_free memory_free_s390x
129131
#define flatview_unref flatview_unref_s390x
130132
#define address_space_get_flatview address_space_get_flatview_s390x

qemu/softmmu/memory.c

+60-10
Original file line numberDiff line numberDiff line change
@@ -208,10 +208,38 @@ void memory_region_filter_subregions(MemoryRegion *mr, int32_t level)
208208
memory_region_transaction_commit(mr);
209209
}
210210

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)
212229
{
213-
int i;
214230
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+
}
215243

216244
if (uc->cpu) {
217245
// We also need to remove all tb cache
@@ -223,18 +251,40 @@ void memory_unmap(struct uc_struct *uc, MemoryRegion *mr)
223251
tlb_flush_page(uc->cpu, addr);
224252
}
225253
}
254+
226255
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+
}
227263

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);
236284
}
237285
}
286+
memory_region_del_subregion(uc->system_memory, mr);
287+
memory_region_remove_mapped_block(uc, mr, true);
238288
}
239289

240290
int memory_free(struct uc_struct *uc)

qemu/sparc.h

+2
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@
125125
#define memory_map_ptr memory_map_ptr_sparc
126126
#define memory_cow memory_cow_sparc
127127
#define memory_unmap memory_unmap_sparc
128+
#define memory_moveout memory_moveout_sparc
129+
#define memory_movein memory_movein_sparc
128130
#define memory_free memory_free_sparc
129131
#define flatview_unref flatview_unref_sparc
130132
#define address_space_get_flatview address_space_get_flatview_sparc

qemu/sparc64.h

+2
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@
125125
#define memory_map_ptr memory_map_ptr_sparc64
126126
#define memory_cow memory_cow_sparc64
127127
#define memory_unmap memory_unmap_sparc64
128+
#define memory_moveout memory_moveout_sparc64
129+
#define memory_movein memory_movein_sparc64
128130
#define memory_free memory_free_sparc64
129131
#define flatview_unref flatview_unref_sparc64
130132
#define address_space_get_flatview address_space_get_flatview_sparc64

qemu/tricore.h

+2
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@
125125
#define memory_map_ptr memory_map_ptr_tricore
126126
#define memory_cow memory_cow_tricore
127127
#define memory_unmap memory_unmap_tricore
128+
#define memory_moveout memory_moveout_tricore
129+
#define memory_movein memory_movein_tricore
128130
#define memory_free memory_free_tricore
129131
#define flatview_unref flatview_unref_tricore
130132
#define address_space_get_flatview address_space_get_flatview_tricore

qemu/unicorn_common.h

+2
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ static inline void uc_common_init(struct uc_struct* uc)
130130
uc->memory_map = memory_map;
131131
uc->memory_map_ptr = memory_map_ptr;
132132
uc->memory_unmap = memory_unmap;
133+
uc->memory_moveout = memory_moveout;
134+
uc->memory_movein = memory_movein;
133135
uc->readonly_mem = memory_region_set_readonly;
134136
uc->target_page = target_page_init;
135137
uc->softfloat_initialize = softfloat_init;

qemu/x86_64.h

+2
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@
125125
#define memory_map_ptr memory_map_ptr_x86_64
126126
#define memory_cow memory_cow_x86_64
127127
#define memory_unmap memory_unmap_x86_64
128+
#define memory_moveout memory_moveout_x86_64
129+
#define memory_movein memory_movein_x86_64
128130
#define memory_free memory_free_x86_64
129131
#define flatview_unref flatview_unref_x86_64
130132
#define address_space_get_flatview address_space_get_flatview_x86_64

symbols.sh

+2
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ memory_map_io \
125125
memory_map_ptr \
126126
memory_cow \
127127
memory_unmap \
128+
memory_moveout \
129+
memory_movein \
128130
memory_free \
129131
flatview_unref \
130132
address_space_get_flatview \

tests/unit/test_mem.c

+34
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,39 @@ static void test_context_snapshot(void)
346346
OK(uc_close(uc));
347347
}
348348

349+
static void test_snapshot_unmap(void)
350+
{
351+
uc_engine *uc;
352+
uc_context *ctx;
353+
uint64_t tmp;
354+
355+
OK(uc_open(UC_ARCH_X86, UC_MODE_64, &uc));
356+
OK(uc_ctl_context_mode(uc, UC_CTL_CONTEXT_MEMORY|UC_CTL_CONTEXT_CPU));
357+
OK(uc_mem_map(uc, 0x1000, 0x2000, UC_PROT_ALL));
358+
359+
tmp = 1;
360+
OK(uc_mem_write(uc, 0x1000, &tmp, sizeof(tmp)));
361+
tmp = 2;
362+
OK(uc_mem_write(uc, 0x2000, &tmp, sizeof(tmp)));
363+
364+
OK(uc_context_alloc(uc, &ctx));
365+
OK(uc_context_save(uc, ctx));
366+
367+
uc_assert_err(UC_ERR_ARG, uc_mem_unmap(uc, 0x1000, 0x1000));
368+
OK(uc_mem_unmap(uc, 0x1000, 0x2000));
369+
uc_assert_err(UC_ERR_READ_UNMAPPED, uc_mem_read(uc, 0x1000, &tmp, sizeof(tmp)));
370+
uc_assert_err(UC_ERR_READ_UNMAPPED, uc_mem_read(uc, 0x2000, &tmp, sizeof(tmp)));
371+
372+
OK(uc_context_restore(uc, ctx));
373+
OK(uc_mem_read(uc, 0x1000, &tmp, sizeof(tmp)));
374+
TEST_CHECK(tmp == 1);
375+
OK(uc_mem_read(uc, 0x2000, &tmp, sizeof(tmp)));
376+
TEST_CHECK(tmp == 2);
377+
378+
OK(uc_context_free(ctx));
379+
OK(uc_close(uc));
380+
}
381+
349382
TEST_LIST = {{"test_map_correct", test_map_correct},
350383
{"test_map_wrapping", test_map_wrapping},
351384
{"test_mem_protect", test_mem_protect},
@@ -359,4 +392,5 @@ TEST_LIST = {{"test_map_correct", test_map_correct},
359392
{"test_mem_protect_mmio", test_mem_protect_mmio},
360393
{"test_snapshot", test_snapshot},
361394
{"test_context_snapshot", test_context_snapshot},
395+
{"test_snapshot_unmap", test_snapshot_unmap},
362396
{NULL, NULL}};

0 commit comments

Comments
 (0)