[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 04/62] exec: optimize phys_page_set_level
From: |
Paolo Bonzini |
Subject: |
[Qemu-devel] [PULL 04/62] exec: optimize phys_page_set_level |
Date: |
Fri, 5 Jun 2015 17:15:05 +0200 |
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 <address@hidden>
Signed-off-by: Paolo Bonzini <address@hidden>
---
exec.c | 24 ++++++++++--------------
1 file changed, 10 insertions(+), 14 deletions(-)
diff --git a/exec.c b/exec.c
index e19ab22..fc8d05d 100644
--- a/exec.c
+++ b/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]) {
--
2.4.1
- [Qemu-devel] [PULL 00/62] KVM, dirty bitmap, build system, SMM, icount changes for 2015-06-05, Paolo Bonzini, 2015/06/05
- [Qemu-devel] [PULL 01/62] Move parallel_hds_isa_init to hw/isa/isa-bus.c, Paolo Bonzini, 2015/06/05
- [Qemu-devel] [PULL 02/62] ppc: add helpful message when KVM fails to start VCPU, Paolo Bonzini, 2015/06/05
- [Qemu-devel] [PULL 04/62] exec: optimize phys_page_set_level,
Paolo Bonzini <=
- [Qemu-devel] [PULL 03/62] qemu-nbd: Switch to qemu_set_fd_handler, Paolo Bonzini, 2015/06/05
- [Qemu-devel] [PULL 06/62] memory: the only dirty memory flag for users is DIRTY_MEMORY_VGA, Paolo Bonzini, 2015/06/05
- [Qemu-devel] [PULL 05/62] Makefile.target: set master BUILD_DIR, Paolo Bonzini, 2015/06/05
- [Qemu-devel] [PULL 07/62] g364fb: remove pointless call to memory_region_set_coalescing, Paolo Bonzini, 2015/06/05
- [Qemu-devel] [PULL 08/62] display: enable DIRTY_MEMORY_VGA tracking explicitly, Paolo Bonzini, 2015/06/05
- [Qemu-devel] [PULL 09/62] display: add memory_region_sync_dirty_bitmap calls, Paolo Bonzini, 2015/06/05
- [Qemu-devel] [PULL 10/62] memory: differentiate memory_region_is_logging and memory_region_get_dirty_log_mask, Paolo Bonzini, 2015/06/05
- [Qemu-devel] [PULL 11/62] memory: prepare for multiple bits in the dirty log mask, Paolo Bonzini, 2015/06/05
- [Qemu-devel] [PULL 12/62] framebuffer: check memory_region_is_logging, Paolo Bonzini, 2015/06/05
- [Qemu-devel] [PULL 14/62] memory: track DIRTY_MEMORY_CODE in mr->dirty_log_mask, Paolo Bonzini, 2015/06/05