mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-03-24 22: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;
|
unsigned i;
|
||||||
uint32_t ret;
|
uint32_t ret;
|
||||||
|
PhysPageEntry e;
|
||||||
|
PhysPageEntry *p;
|
||||||
|
|
||||||
ret = map->nodes_nb++;
|
ret = map->nodes_nb++;
|
||||||
|
p = map->nodes[ret];
|
||||||
assert(ret != PHYS_MAP_NODE_NIL);
|
assert(ret != PHYS_MAP_NODE_NIL);
|
||||||
assert(ret != map->nodes_nb_alloc);
|
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) {
|
for (i = 0; i < P_L2_SIZE; ++i) {
|
||||||
map->nodes[ret][i].skip = 1;
|
memcpy(&p[i], &e, sizeof(e));
|
||||||
map->nodes[ret][i].ptr = PHYS_MAP_NODE_NIL;
|
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -154,21 +159,12 @@ static void phys_page_set_level(PhysPageMap *map, PhysPageEntry *lp,
|
||||||
int level)
|
int level)
|
||||||
{
|
{
|
||||||
PhysPageEntry *p;
|
PhysPageEntry *p;
|
||||||
int i;
|
|
||||||
hwaddr step = (hwaddr)1 << (level * P_L2_BITS);
|
hwaddr step = (hwaddr)1 << (level * P_L2_BITS);
|
||||||
|
|
||||||
if (lp->skip && lp->ptr == PHYS_MAP_NODE_NIL) {
|
if (lp->skip && lp->ptr == PHYS_MAP_NODE_NIL) {
|
||||||
lp->ptr = phys_map_node_alloc(map);
|
lp->ptr = phys_map_node_alloc(map, level == 0);
|
||||||
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];
|
|
||||||
}
|
}
|
||||||
|
p = map->nodes[lp->ptr];
|
||||||
lp = &p[(*index >> (level * P_L2_BITS)) & (P_L2_SIZE - 1)];
|
lp = &p[(*index >> (level * P_L2_BITS)) & (P_L2_SIZE - 1)];
|
||||||
|
|
||||||
while (*nb && lp < &p[P_L2_SIZE]) {
|
while (*nb && lp < &p[P_L2_SIZE]) {
|
||||||
|
|
Loading…
Reference in a new issue