Skip to content

Commit 12cf697

Browse files
PhilippTakacshyunmin-furiosa
authored andcommitted
Optimize memory handling (unicorn-engine#1963)
* optimize ram block handling Save the last element of the ram_list. This allows to faster find where to add new elements when they are not bigger then page size. * save ram_list freed this keeps the optimization for find_ram_offset() intact after snapshot restore. * cow only clear the tlb of affected pages * update flatview when possible Building each flatview new when the memory has changed is quite expensive when many MemoryRegions are used. This is an issue when using snapshots. * update benchmark for new api * save flatview in context this avoids rebuilding the flatview when restore a context. * init context flatview with zero * address_space_dispatch_clear remove subpage with higher priority * docutemnt the options for UC_CTL_CONTEXT_MODE Specialy stress that with UC_CTL_CONTEXT_MEMORY it is not possible to use the context with a different unicorn object.
1 parent b92b48b commit 12cf697

27 files changed

+236
-45
lines changed

include/qemu.h

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ typedef struct {
4343
typedef struct RAMList {
4444
bool freed;
4545
RAMBlock *mru_block;
46+
RAMBlock *last_block;
4647
QLIST_HEAD(, RAMBlock) blocks;
4748
} RAMList;
4849

include/uc_priv.h

+6
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ typedef MemoryRegion *(*uc_memory_mapping_t)(struct uc_struct *, hwaddr addr);
106106

107107
typedef void (*uc_memory_filter_t)(MemoryRegion *, int32_t);
108108

109+
typedef bool (*uc_flatview_copy_t)(struct uc_struct *, FlatView *, FlatView *, bool);
110+
109111
typedef void (*uc_readonly_mem_t)(MemoryRegion *mr, bool readonly);
110112

111113
typedef int (*uc_cpus_init)(struct uc_struct *, const char *);
@@ -302,6 +304,7 @@ struct uc_struct {
302304
uc_args_uc_ram_size_ptr_t memory_map_ptr;
303305
uc_memory_mapping_t memory_mapping;
304306
uc_memory_filter_t memory_filter_subregions;
307+
uc_flatview_copy_t flatview_copy;
305308
uc_mem_unmap_t memory_unmap;
306309
uc_mem_unmap_t memory_moveout;
307310
uc_mem_unmap_t memory_movein;
@@ -493,6 +496,9 @@ struct uc_context {
493496
uc_mode mode; // the mode of this context
494497
uc_arch arch; // the arch of this context
495498
int snapshot_level; // the memory snapshot level to restore
499+
bool ramblock_freed; // wheter there was a some ramblock freed
500+
RAMBlock *last_block;// The last element of the ramblock list
501+
FlatView *fv; // The current flatview of the memory
496502
char data[0]; // context
497503
};
498504

include/unicorn/unicorn.h

+10
Original file line numberDiff line numberDiff line change
@@ -1051,6 +1051,16 @@ struct uc_tlb_entry {
10511051
uc_prot perms;
10521052
};
10531053

1054+
/*
1055+
Variables to control which state should be stored in the context.
1056+
Defaults to UC_CTL_CONTEXT_CPU. The options are used in a bitfield
1057+
so to enable more then one content the binary or of the required
1058+
contents can be use.
1059+
The UC_CTL_CONTEXT_MEMORY stores some pointers to internal allocated
1060+
memory. Therefor it's not possible to use this context with another
1061+
unicorn object.
1062+
*/
1063+
10541064
typedef enum uc_context_content {
10551065
UC_CTL_CONTEXT_CPU = 1,
10561066
UC_CTL_CONTEXT_MEMORY = 2,

qemu/aarch64.h

+2
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#define vm_start vm_start_aarch64
5555
#define address_space_dispatch_compact address_space_dispatch_compact_aarch64
5656
#define flatview_translate flatview_translate_aarch64
57+
#define flatview_copy flatview_copy_aarch64
5758
#define address_space_translate_for_iotlb address_space_translate_for_iotlb_aarch64
5859
#define qemu_get_cpu qemu_get_cpu_aarch64
5960
#define cpu_address_space_init cpu_address_space_init_aarch64
@@ -90,6 +91,7 @@
9091
#define iotlb_to_section iotlb_to_section_aarch64
9192
#define address_space_dispatch_new address_space_dispatch_new_aarch64
9293
#define address_space_dispatch_free address_space_dispatch_free_aarch64
94+
#define address_space_dispatch_clear address_space_dispatch_clear_aarch64
9395
#define flatview_read_continue flatview_read_continue_aarch64
9496
#define address_space_read_full address_space_read_full_aarch64
9597
#define address_space_write address_space_write_aarch64

qemu/arm.h

+2
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#define vm_start vm_start_arm
5555
#define address_space_dispatch_compact address_space_dispatch_compact_arm
5656
#define flatview_translate flatview_translate_arm
57+
#define flatview_copy flatview_copy_arm
5758
#define address_space_translate_for_iotlb address_space_translate_for_iotlb_arm
5859
#define qemu_get_cpu qemu_get_cpu_arm
5960
#define cpu_address_space_init cpu_address_space_init_arm
@@ -90,6 +91,7 @@
9091
#define iotlb_to_section iotlb_to_section_arm
9192
#define address_space_dispatch_new address_space_dispatch_new_arm
9293
#define address_space_dispatch_free address_space_dispatch_free_arm
94+
#define address_space_dispatch_clear address_space_dispatch_clear_arm
9395
#define flatview_read_continue flatview_read_continue_arm
9496
#define address_space_read_full address_space_read_full_arm
9597
#define address_space_write address_space_write_arm

qemu/exec.c

+32-8
Original file line numberDiff line numberDiff line change
@@ -957,12 +957,10 @@ void flatview_add_to_dispatch(struct uc_struct *uc, FlatView *fv, MemoryRegionSe
957957

958958
static ram_addr_t find_ram_offset_last(struct uc_struct *uc, ram_addr_t size)
959959
{
960-
RAMBlock *block;
961960
ram_addr_t result = 0;
961+
RAMBlock *block = uc->ram_list.last_block;
962962

963-
RAMBLOCK_FOREACH(block) {
964-
result = MAX(block->offset + block->max_length, result);
965-
}
963+
result = block->offset + block->max_length;
966964

967965
if (result + size > RAM_ADDR_MAX) {
968966
abort();
@@ -1076,18 +1074,26 @@ static void ram_block_add(struct uc_struct *uc, RAMBlock *new_block)
10761074
* QLIST (which has an RCU-friendly variant) does not have insertion at
10771075
* tail, so save the last element in last_block.
10781076
*/
1079-
RAMBLOCK_FOREACH(block) {
1080-
last_block = block;
1081-
if (block->max_length < new_block->max_length) {
1082-
break;
1077+
if (uc->ram_list.freed || new_block->max_length > uc->target_page_size) {
1078+
RAMBLOCK_FOREACH(block) {
1079+
last_block = block;
1080+
if (block->max_length < new_block->max_length) {
1081+
break;
1082+
}
10831083
}
1084+
} else {
1085+
last_block = uc->ram_list.last_block;
1086+
block = NULL;
10841087
}
1088+
10851089
if (block) {
10861090
QLIST_INSERT_BEFORE_RCU(block, new_block, next);
10871091
} else if (last_block) {
10881092
QLIST_INSERT_AFTER_RCU(last_block, new_block, next);
1093+
uc->ram_list.last_block = new_block;
10891094
} else { /* list is empty */
10901095
QLIST_INSERT_HEAD_RCU(&uc->ram_list.blocks, new_block, next);
1096+
uc->ram_list.last_block = new_block;
10911097
}
10921098
uc->ram_list.mru_block = NULL;
10931099

@@ -1165,6 +1171,7 @@ void qemu_ram_free(struct uc_struct *uc, RAMBlock *block)
11651171
QLIST_REMOVE_RCU(block, next);
11661172
uc->ram_list.mru_block = NULL;
11671173
uc->ram_list.freed = true;
1174+
uc->ram_list.last_block = NULL;
11681175
/* Write list before version */
11691176
//smp_wmb();
11701177
// call_rcu(block, reclaim_ramblock, rcu);
@@ -1388,6 +1395,7 @@ static subpage_t *subpage_init(struct uc_struct *uc, FlatView *fv, hwaddr base)
13881395
memory_region_init_io(fv->root->uc, &mmio->iomem, &subpage_ops, mmio,
13891396
TARGET_PAGE_SIZE);
13901397
mmio->iomem.subpage = true;
1398+
mmio->iomem.priority = uc->snapshot_level;
13911399
#if defined(DEBUG_SUBPAGE)
13921400
printf("%s: %p base " TARGET_FMT_plx " len %08x\n", __func__,
13931401
mmio, base, TARGET_PAGE_SIZE);
@@ -1448,6 +1456,22 @@ AddressSpaceDispatch *address_space_dispatch_new(struct uc_struct *uc, FlatView
14481456
return d;
14491457
}
14501458

1459+
void address_space_dispatch_clear(AddressSpaceDispatch *d)
1460+
{
1461+
MemoryRegionSection *section;
1462+
struct uc_struct *uc = d->uc;
1463+
while (d->map.sections_nb > 0) {
1464+
d->map.sections_nb--;
1465+
section = &d->map.sections[d->map.sections_nb];
1466+
if (section->mr->priority > uc->snapshot_level) {
1467+
phys_section_destroy(section->mr);
1468+
}
1469+
}
1470+
g_free(d->map.sections);
1471+
g_free(d->map.nodes);
1472+
g_free(d);
1473+
}
1474+
14511475
void address_space_dispatch_free(AddressSpaceDispatch *d)
14521476
{
14531477
phys_sections_free(&d->map);

qemu/include/exec/memory-internal.h

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ void flatview_add_to_dispatch(struct uc_struct *uc, FlatView *fv, MemoryRegionSe
4545
AddressSpaceDispatch *address_space_dispatch_new(struct uc_struct *uc, FlatView *fv);
4646
void address_space_dispatch_compact(AddressSpaceDispatch *d);
4747
void address_space_dispatch_free(AddressSpaceDispatch *d);
48+
void address_space_dispatch_clear(AddressSpaceDispatch *d);
4849

4950
void mtree_print_dispatch(struct AddressSpaceDispatch *d,
5051
MemoryRegion *root);

qemu/include/exec/memory.h

+1
Original file line numberDiff line numberDiff line change
@@ -1219,5 +1219,6 @@ void memory_unmap(struct uc_struct *uc, MemoryRegion *mr);
12191219
void memory_moveout(struct uc_struct *uc, MemoryRegion *mr);
12201220
void memory_movein(struct uc_struct *uc, MemoryRegion *mr);
12211221
int memory_free(struct uc_struct *uc);
1222+
bool flatview_copy(struct uc_struct *uc, FlatView *dst, FlatView *src, bool update_dispatcher);
12221223

12231224
#endif

qemu/m68k.h

+2
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#define vm_start vm_start_m68k
5555
#define address_space_dispatch_compact address_space_dispatch_compact_m68k
5656
#define flatview_translate flatview_translate_m68k
57+
#define flatview_copy flatview_copy_m68k
5758
#define address_space_translate_for_iotlb address_space_translate_for_iotlb_m68k
5859
#define qemu_get_cpu qemu_get_cpu_m68k
5960
#define cpu_address_space_init cpu_address_space_init_m68k
@@ -90,6 +91,7 @@
9091
#define iotlb_to_section iotlb_to_section_m68k
9192
#define address_space_dispatch_new address_space_dispatch_new_m68k
9293
#define address_space_dispatch_free address_space_dispatch_free_m68k
94+
#define address_space_dispatch_clear address_space_dispatch_clear_m68k
9395
#define flatview_read_continue flatview_read_continue_m68k
9496
#define address_space_read_full address_space_read_full_m68k
9597
#define address_space_write address_space_write_m68k

qemu/mips.h

+2
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#define vm_start vm_start_mips
5555
#define address_space_dispatch_compact address_space_dispatch_compact_mips
5656
#define flatview_translate flatview_translate_mips
57+
#define flatview_copy flatview_copy_mips
5758
#define address_space_translate_for_iotlb address_space_translate_for_iotlb_mips
5859
#define qemu_get_cpu qemu_get_cpu_mips
5960
#define cpu_address_space_init cpu_address_space_init_mips
@@ -90,6 +91,7 @@
9091
#define iotlb_to_section iotlb_to_section_mips
9192
#define address_space_dispatch_new address_space_dispatch_new_mips
9293
#define address_space_dispatch_free address_space_dispatch_free_mips
94+
#define address_space_dispatch_clear address_space_dispatch_clear_mips
9395
#define flatview_read_continue flatview_read_continue_mips
9496
#define address_space_read_full address_space_read_full_mips
9597
#define address_space_write address_space_write_mips

qemu/mips64.h

+2
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#define vm_start vm_start_mips64
5555
#define address_space_dispatch_compact address_space_dispatch_compact_mips64
5656
#define flatview_translate flatview_translate_mips64
57+
#define flatview_copy flatview_copy_mips64
5758
#define address_space_translate_for_iotlb address_space_translate_for_iotlb_mips64
5859
#define qemu_get_cpu qemu_get_cpu_mips64
5960
#define cpu_address_space_init cpu_address_space_init_mips64
@@ -90,6 +91,7 @@
9091
#define iotlb_to_section iotlb_to_section_mips64
9192
#define address_space_dispatch_new address_space_dispatch_new_mips64
9293
#define address_space_dispatch_free address_space_dispatch_free_mips64
94+
#define address_space_dispatch_clear address_space_dispatch_clear_mips64
9395
#define flatview_read_continue flatview_read_continue_mips64
9496
#define address_space_read_full address_space_read_full_mips64
9597
#define address_space_write address_space_write_mips64

qemu/mips64el.h

+2
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#define vm_start vm_start_mips64el
5555
#define address_space_dispatch_compact address_space_dispatch_compact_mips64el
5656
#define flatview_translate flatview_translate_mips64el
57+
#define flatview_copy flatview_copy_mips64el
5758
#define address_space_translate_for_iotlb address_space_translate_for_iotlb_mips64el
5859
#define qemu_get_cpu qemu_get_cpu_mips64el
5960
#define cpu_address_space_init cpu_address_space_init_mips64el
@@ -90,6 +91,7 @@
9091
#define iotlb_to_section iotlb_to_section_mips64el
9192
#define address_space_dispatch_new address_space_dispatch_new_mips64el
9293
#define address_space_dispatch_free address_space_dispatch_free_mips64el
94+
#define address_space_dispatch_clear address_space_dispatch_clear_mips64el
9395
#define flatview_read_continue flatview_read_continue_mips64el
9496
#define address_space_read_full address_space_read_full_mips64el
9597
#define address_space_write address_space_write_mips64el

qemu/mipsel.h

+2
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#define vm_start vm_start_mipsel
5555
#define address_space_dispatch_compact address_space_dispatch_compact_mipsel
5656
#define flatview_translate flatview_translate_mipsel
57+
#define flatview_copy flatview_copy_mipsel
5758
#define address_space_translate_for_iotlb address_space_translate_for_iotlb_mipsel
5859
#define qemu_get_cpu qemu_get_cpu_mipsel
5960
#define cpu_address_space_init cpu_address_space_init_mipsel
@@ -90,6 +91,7 @@
9091
#define iotlb_to_section iotlb_to_section_mipsel
9192
#define address_space_dispatch_new address_space_dispatch_new_mipsel
9293
#define address_space_dispatch_free address_space_dispatch_free_mipsel
94+
#define address_space_dispatch_clear address_space_dispatch_clear_mipsel
9395
#define flatview_read_continue flatview_read_continue_mipsel
9496
#define address_space_read_full address_space_read_full_mipsel
9597
#define address_space_write address_space_write_mipsel

qemu/ppc.h

+2
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#define vm_start vm_start_ppc
5555
#define address_space_dispatch_compact address_space_dispatch_compact_ppc
5656
#define flatview_translate flatview_translate_ppc
57+
#define flatview_copy flatview_copy_ppc
5758
#define address_space_translate_for_iotlb address_space_translate_for_iotlb_ppc
5859
#define qemu_get_cpu qemu_get_cpu_ppc
5960
#define cpu_address_space_init cpu_address_space_init_ppc
@@ -90,6 +91,7 @@
9091
#define iotlb_to_section iotlb_to_section_ppc
9192
#define address_space_dispatch_new address_space_dispatch_new_ppc
9293
#define address_space_dispatch_free address_space_dispatch_free_ppc
94+
#define address_space_dispatch_clear address_space_dispatch_clear_ppc
9395
#define flatview_read_continue flatview_read_continue_ppc
9496
#define address_space_read_full address_space_read_full_ppc
9597
#define address_space_write address_space_write_ppc

qemu/ppc64.h

+2
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#define vm_start vm_start_ppc64
5555
#define address_space_dispatch_compact address_space_dispatch_compact_ppc64
5656
#define flatview_translate flatview_translate_ppc64
57+
#define flatview_copy flatview_copy_ppc64
5758
#define address_space_translate_for_iotlb address_space_translate_for_iotlb_ppc64
5859
#define qemu_get_cpu qemu_get_cpu_ppc64
5960
#define cpu_address_space_init cpu_address_space_init_ppc64
@@ -90,6 +91,7 @@
9091
#define iotlb_to_section iotlb_to_section_ppc64
9192
#define address_space_dispatch_new address_space_dispatch_new_ppc64
9293
#define address_space_dispatch_free address_space_dispatch_free_ppc64
94+
#define address_space_dispatch_clear address_space_dispatch_clear_ppc64
9395
#define flatview_read_continue flatview_read_continue_ppc64
9496
#define address_space_read_full address_space_read_full_ppc64
9597
#define address_space_write address_space_write_ppc64

qemu/riscv32.h

+2
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#define vm_start vm_start_riscv32
5555
#define address_space_dispatch_compact address_space_dispatch_compact_riscv32
5656
#define flatview_translate flatview_translate_riscv32
57+
#define flatview_copy flatview_copy_riscv32
5758
#define address_space_translate_for_iotlb address_space_translate_for_iotlb_riscv32
5859
#define qemu_get_cpu qemu_get_cpu_riscv32
5960
#define cpu_address_space_init cpu_address_space_init_riscv32
@@ -90,6 +91,7 @@
9091
#define iotlb_to_section iotlb_to_section_riscv32
9192
#define address_space_dispatch_new address_space_dispatch_new_riscv32
9293
#define address_space_dispatch_free address_space_dispatch_free_riscv32
94+
#define address_space_dispatch_clear address_space_dispatch_clear_riscv32
9395
#define flatview_read_continue flatview_read_continue_riscv32
9496
#define address_space_read_full address_space_read_full_riscv32
9597
#define address_space_write address_space_write_riscv32

qemu/riscv64.h

+2
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#define vm_start vm_start_riscv64
5555
#define address_space_dispatch_compact address_space_dispatch_compact_riscv64
5656
#define flatview_translate flatview_translate_riscv64
57+
#define flatview_copy flatview_copy_riscv64
5758
#define address_space_translate_for_iotlb address_space_translate_for_iotlb_riscv64
5859
#define qemu_get_cpu qemu_get_cpu_riscv64
5960
#define cpu_address_space_init cpu_address_space_init_riscv64
@@ -90,6 +91,7 @@
9091
#define iotlb_to_section iotlb_to_section_riscv64
9192
#define address_space_dispatch_new address_space_dispatch_new_riscv64
9293
#define address_space_dispatch_free address_space_dispatch_free_riscv64
94+
#define address_space_dispatch_clear address_space_dispatch_clear_riscv64
9395
#define flatview_read_continue flatview_read_continue_riscv64
9496
#define address_space_read_full address_space_read_full_riscv64
9597
#define address_space_write address_space_write_riscv64

qemu/s390x.h

+2
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#define vm_start vm_start_s390x
5555
#define address_space_dispatch_compact address_space_dispatch_compact_s390x
5656
#define flatview_translate flatview_translate_s390x
57+
#define flatview_copy flatview_copy_s390x
5758
#define address_space_translate_for_iotlb address_space_translate_for_iotlb_s390x
5859
#define qemu_get_cpu qemu_get_cpu_s390x
5960
#define cpu_address_space_init cpu_address_space_init_s390x
@@ -90,6 +91,7 @@
9091
#define iotlb_to_section iotlb_to_section_s390x
9192
#define address_space_dispatch_new address_space_dispatch_new_s390x
9293
#define address_space_dispatch_free address_space_dispatch_free_s390x
94+
#define address_space_dispatch_clear address_space_dispatch_clear_s390x
9395
#define flatview_read_continue flatview_read_continue_s390x
9496
#define address_space_read_full address_space_read_full_s390x
9597
#define address_space_write address_space_write_s390x

0 commit comments

Comments
 (0)