Optimize memory handling (#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.
This commit is contained in:
40
qemu/exec.c
40
qemu/exec.c
@@ -957,12 +957,10 @@ void flatview_add_to_dispatch(struct uc_struct *uc, FlatView *fv, MemoryRegionSe
|
||||
|
||||
static ram_addr_t find_ram_offset_last(struct uc_struct *uc, ram_addr_t size)
|
||||
{
|
||||
RAMBlock *block;
|
||||
ram_addr_t result = 0;
|
||||
RAMBlock *block = uc->ram_list.last_block;
|
||||
|
||||
RAMBLOCK_FOREACH(block) {
|
||||
result = MAX(block->offset + block->max_length, result);
|
||||
}
|
||||
result = block->offset + block->max_length;
|
||||
|
||||
if (result + size > RAM_ADDR_MAX) {
|
||||
abort();
|
||||
@@ -1076,18 +1074,26 @@ static void ram_block_add(struct uc_struct *uc, RAMBlock *new_block)
|
||||
* QLIST (which has an RCU-friendly variant) does not have insertion at
|
||||
* tail, so save the last element in last_block.
|
||||
*/
|
||||
RAMBLOCK_FOREACH(block) {
|
||||
last_block = block;
|
||||
if (block->max_length < new_block->max_length) {
|
||||
break;
|
||||
if (uc->ram_list.freed || new_block->max_length > uc->target_page_size) {
|
||||
RAMBLOCK_FOREACH(block) {
|
||||
last_block = block;
|
||||
if (block->max_length < new_block->max_length) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
last_block = uc->ram_list.last_block;
|
||||
block = NULL;
|
||||
}
|
||||
|
||||
if (block) {
|
||||
QLIST_INSERT_BEFORE_RCU(block, new_block, next);
|
||||
} else if (last_block) {
|
||||
QLIST_INSERT_AFTER_RCU(last_block, new_block, next);
|
||||
uc->ram_list.last_block = new_block;
|
||||
} else { /* list is empty */
|
||||
QLIST_INSERT_HEAD_RCU(&uc->ram_list.blocks, new_block, next);
|
||||
uc->ram_list.last_block = new_block;
|
||||
}
|
||||
uc->ram_list.mru_block = NULL;
|
||||
|
||||
@@ -1165,6 +1171,7 @@ void qemu_ram_free(struct uc_struct *uc, RAMBlock *block)
|
||||
QLIST_REMOVE_RCU(block, next);
|
||||
uc->ram_list.mru_block = NULL;
|
||||
uc->ram_list.freed = true;
|
||||
uc->ram_list.last_block = NULL;
|
||||
/* Write list before version */
|
||||
//smp_wmb();
|
||||
// call_rcu(block, reclaim_ramblock, rcu);
|
||||
@@ -1388,6 +1395,7 @@ static subpage_t *subpage_init(struct uc_struct *uc, FlatView *fv, hwaddr base)
|
||||
memory_region_init_io(fv->root->uc, &mmio->iomem, &subpage_ops, mmio,
|
||||
TARGET_PAGE_SIZE);
|
||||
mmio->iomem.subpage = true;
|
||||
mmio->iomem.priority = uc->snapshot_level;
|
||||
#if defined(DEBUG_SUBPAGE)
|
||||
printf("%s: %p base " TARGET_FMT_plx " len %08x\n", __func__,
|
||||
mmio, base, TARGET_PAGE_SIZE);
|
||||
@@ -1448,6 +1456,22 @@ AddressSpaceDispatch *address_space_dispatch_new(struct uc_struct *uc, FlatView
|
||||
return d;
|
||||
}
|
||||
|
||||
void address_space_dispatch_clear(AddressSpaceDispatch *d)
|
||||
{
|
||||
MemoryRegionSection *section;
|
||||
struct uc_struct *uc = d->uc;
|
||||
while (d->map.sections_nb > 0) {
|
||||
d->map.sections_nb--;
|
||||
section = &d->map.sections[d->map.sections_nb];
|
||||
if (section->mr->priority > uc->snapshot_level) {
|
||||
phys_section_destroy(section->mr);
|
||||
}
|
||||
}
|
||||
g_free(d->map.sections);
|
||||
g_free(d->map.nodes);
|
||||
g_free(d);
|
||||
}
|
||||
|
||||
void address_space_dispatch_free(AddressSpaceDispatch *d)
|
||||
{
|
||||
phys_sections_free(&d->map);
|
||||
|
||||
Reference in New Issue
Block a user