or even this: diff --git a/include/exec/memory.h b/include/exec/memory.h index 1d55ad9..3003875 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -161,6 +161,7 @@ struct MemoryRegion { unsigned ioeventfd_nb; MemoryRegionIoeventfd *ioeventfds; NotifierList iommu_notify; + void *ram_ptr; }; /** diff --git a/memory.c b/memory.c index 3f1df23..6c1e413 100644 --- a/memory.c +++ b/memory.c @@ -862,6 +862,7 @@ void memory_region_init(MemoryRegion *mr, mr->ioeventfd_nb = 0; mr->ioeventfds = NULL; mr->flush_coalesced_mmio = false; + mr->ram_ptr = NULL; } static uint64_t unassigned_mem_read(void *opaque, hwaddr addr, @@ -1241,17 +1242,23 @@ void memory_region_reset_dirty(MemoryRegion *mr, hwaddr addr, cpu_physical_memory_reset_dirty(mr->ram_addr + addr, size, client); } -void *memory_region_get_ram_ptr(MemoryRegion *mr) +static void *memory_region_get_ram_ptr2(MemoryRegion *mr) { if (mr->alias) { return memory_region_get_ram_ptr(mr->alias) + mr->alias_offset; } - assert(mr->terminates); - return qemu_get_ram_ptr(mr->ram_addr & TARGET_PAGE_MASK); } +inline void *memory_region_get_ram_ptr(MemoryRegion *mr) +{ + if (!mr->ram_ptr) { + mr->ram_ptr = memory_region_get_ram_ptr2(mr); + } + return mr->ram_ptr; +} + static void memory_region_update_coalesced_range_as(MemoryRegion *mr, AddressSpace *as) { FlatView *view;
Am 10.05.2014 18:32, schrieb Peter Lieven: > Am 10.05.2014 17:33, schrieb Paolo Bonzini: >> Il 10/05/2014 12:51, Peter Lieven ha scritto: >>> we currently look up the ram ptr for each single page. Cache >>> the pointer while we operate on the same block. >> Why don't you instead cache the result in the MemoryRegion, so that >> memory_region_get_ram_ptr becomes a simple, inline field access? > This seems to work. Wondering if it has other side implications. Basic tests > like booting vServers and migration work. What about XEN? > > diff --git a/include/exec/memory.h b/include/exec/memory.h > index 1d55ad9..3003875 100644 > --- a/include/exec/memory.h > +++ b/include/exec/memory.h > @@ -161,6 +161,7 @@ struct MemoryRegion { > unsigned ioeventfd_nb; > MemoryRegionIoeventfd *ioeventfds; > NotifierList iommu_notify; > + void *ram_ptr; > }; > > /** > diff --git a/memory.c b/memory.c > index 3f1df23..78d4032 100644 > --- a/memory.c > +++ b/memory.c > @@ -862,6 +862,7 @@ void memory_region_init(MemoryRegion *mr, > mr->ioeventfd_nb = 0; > mr->ioeventfds = NULL; > mr->flush_coalesced_mmio = false; > + mr->ram_ptr = NULL; > } > > static uint64_t unassigned_mem_read(void *opaque, hwaddr addr, > @@ -1249,7 +1250,12 @@ void *memory_region_get_ram_ptr(MemoryRegion *mr) > > assert(mr->terminates); > > - return qemu_get_ram_ptr(mr->ram_addr & TARGET_PAGE_MASK); > + if (mr->ram_ptr) { > + return mr->ram_ptr; > + } > + > + mr->ram_ptr = qemu_get_ram_ptr(mr->ram_addr & TARGET_PAGE_MASK); > + return mr->ram_ptr; > } > > static void memory_region_update_coalesced_range_as(MemoryRegion *mr, > AddressSpace *as) > > > Peter > >> Paolo >> >>> Signed-off-by: Peter Lieven <p...@kamp.de> >>> --- >>> arch_init.c | 23 ++++++++++++++++------- >>> 1 file changed, 16 insertions(+), 7 deletions(-) >>> >>> diff --git a/arch_init.c b/arch_init.c >>> index 582b716..ce338aa 100644 >>> --- a/arch_init.c >>> +++ b/arch_init.c >>> @@ -594,13 +594,19 @@ static int ram_save_block(QEMUFile *f, bool >>> last_stage) >>> ram_bulk_stage = false; >>> } >>> } else { >>> + static uint8_t *ram_ptr; >>> int ret; >>> uint8_t *p; >>> bool send_async = true; >>> - int cont = (block == last_sent_block) ? >>> - RAM_SAVE_FLAG_CONTINUE : 0; >>> + int cont = 0; >>> >>> - p = memory_region_get_ram_ptr(mr) + offset; >>> + if (block != last_sent_block) { >>> + ram_ptr = memory_region_get_ram_ptr(mr); >>> + } else { >>> + cont = RAM_SAVE_FLAG_CONTINUE; >>> + } >>> + >>> + p = ram_ptr + offset; >>> >>> /* In doubt sent page as normal */ >>> bytes_sent = -1; >>> @@ -990,16 +996,17 @@ static inline void *host_from_stream_offset(QEMUFile >>> *f, >>> int flags) >>> { >>> static RAMBlock *block = NULL; >>> + static uint8_t *ram_ptr; >>> char id[256]; >>> uint8_t len; >>> >>> if (flags & RAM_SAVE_FLAG_CONTINUE) { >>> - if (!block) { >>> + if (!block || !ram_ptr) { >>> fprintf(stderr, "Ack, bad migration stream!\n"); >>> return NULL; >>> } >>> >>> - return memory_region_get_ram_ptr(block->mr) + offset; >>> + return ram_ptr + offset; >>> } >>> >>> len = qemu_get_byte(f); >>> @@ -1007,8 +1014,10 @@ static inline void *host_from_stream_offset(QEMUFile >>> *f, >>> id[len] = 0; >>> >>> QTAILQ_FOREACH(block, &ram_list.blocks, next) { >>> - if (!strncmp(id, block->idstr, sizeof(id))) >>> - return memory_region_get_ram_ptr(block->mr) + offset; >>> + if (!strncmp(id, block->idstr, sizeof(id))) { >>> + ram_ptr = memory_region_get_ram_ptr(block->mr); >>> + return ram_ptr + offset; >>> + } >>> } >>> >>> fprintf(stderr, "Can't find block %s!\n", id); >>>