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. Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
e4afbf4fb4
commit
db94604b20
24
exec.c
24
exec.c
@ -173,17 +173,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;
|
||||
}
|
||||
@ -193,21 +198,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 New Issue
Block a user