mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-03-23 05:25:11 +00:00
exec: optimize phys_page_set_level
phys_page_set_level is writing zeroes to a struct that has just been filled in by phys_map_node_alloc. Instead, tell phys_map_node_alloc whether to fill in the page "as a leaf" or "as a non-leaf". memcpy is faster than struct assignment, which copies each bitfield individually. A compiler bug (https://gcc.gnu.org/PR66391), and small memcpys like this one are special-cased anyway, and optimized to a register move, so just use the memcpy. This cuts the cost of phys_page_set_level from 25% to 5% when booting qboot. Backports commit db94604b20278c1dc227a04e4c564d80230e6c3f from qemu
This commit is contained in:
parent
96e7e32972
commit
9847ba46d6
24
qemu/exec.c
24
qemu/exec.c
|
@ -134,17 +134,22 @@ static void phys_map_node_reserve(PhysPageMap *map, unsigned nodes)
|
|||
}
|
||||
}
|
||||
|
||||
static uint32_t phys_map_node_alloc(PhysPageMap *map)
|
||||
static uint32_t phys_map_node_alloc(PhysPageMap *map, bool leaf)
|
||||
{
|
||||
unsigned i;
|
||||
uint32_t ret;
|
||||
PhysPageEntry e;
|
||||
PhysPageEntry *p;
|
||||
|
||||
ret = map->nodes_nb++;
|
||||
p = map->nodes[ret];
|
||||
assert(ret != PHYS_MAP_NODE_NIL);
|
||||
assert(ret != map->nodes_nb_alloc);
|
||||
|
||||
e.skip = leaf ? 0 : 1;
|
||||
e.ptr = leaf ? PHYS_SECTION_UNASSIGNED : PHYS_MAP_NODE_NIL;
|
||||
for (i = 0; i < P_L2_SIZE; ++i) {
|
||||
map->nodes[ret][i].skip = 1;
|
||||
map->nodes[ret][i].ptr = PHYS_MAP_NODE_NIL;
|
||||
memcpy(&p[i], &e, sizeof(e));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -154,21 +159,12 @@ static void phys_page_set_level(PhysPageMap *map, PhysPageEntry *lp,
|
|||
int level)
|
||||
{
|
||||
PhysPageEntry *p;
|
||||
int i;
|
||||
hwaddr step = (hwaddr)1 << (level * P_L2_BITS);
|
||||
|
||||
if (lp->skip && lp->ptr == PHYS_MAP_NODE_NIL) {
|
||||
lp->ptr = phys_map_node_alloc(map);
|
||||
p = map->nodes[lp->ptr];
|
||||
if (level == 0) {
|
||||
for (i = 0; i < P_L2_SIZE; i++) {
|
||||
p[i].skip = 0;
|
||||
p[i].ptr = PHYS_SECTION_UNASSIGNED;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
p = map->nodes[lp->ptr];
|
||||
lp->ptr = phys_map_node_alloc(map, level == 0);
|
||||
}
|
||||
p = map->nodes[lp->ptr];
|
||||
lp = &p[(*index >> (level * P_L2_BITS)) & (P_L2_SIZE - 1)];
|
||||
|
||||
while (*nb && lp < &p[P_L2_SIZE]) {
|
||||
|
|
Loading…
Reference in a new issue