On Thu, Aug 9, 2012 at 3:23 AM, Blue Swirl <blauwirbel@xxxxxxxxx> wrote: > On Wed, Aug 8, 2012 at 6:25 AM, Liu Ping Fan <qemulist@xxxxxxxxx> wrote: >> From: Liu Ping Fan <pingfank@xxxxxxxxxxxxxxxxxx> >> >> Flatview and radix view are all under the protection of pointer. >> And this make sure the change of them seem to be atomic! >> >> The mr accessed by radix-tree leaf or flatview will be reclaimed >> after the prev PhysMap not in use any longer >> >> Signed-off-by: Liu Ping Fan <pingfank@xxxxxxxxxxxxxxxxxx> >> --- >> exec.c | 303 +++++++++++++++++++++++++++++++++++++++------------------- >> hw/vhost.c | 2 +- >> hw/xen_pt.c | 2 +- >> kvm-all.c | 2 +- >> memory.c | 92 ++++++++++++++----- >> memory.h | 9 ++- >> vl.c | 1 + >> xen-all.c | 2 +- >> 8 files changed, 286 insertions(+), 127 deletions(-) >> >> diff --git a/exec.c b/exec.c >> index 01b91b0..97addb9 100644 >> --- a/exec.c >> +++ b/exec.c >> @@ -24,6 +24,7 @@ >> #include <sys/mman.h> >> #endif >> >> +#include "qemu/atomic.h" >> #include "qemu-common.h" >> #include "cpu.h" >> #include "tcg.h" >> @@ -35,6 +36,8 @@ >> #include "qemu-timer.h" >> #include "memory.h" >> #include "exec-memory.h" >> +#include "qemu-thread.h" >> +#include "qemu/reclaimer.h" >> #if defined(CONFIG_USER_ONLY) >> #include <qemu.h> >> #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) >> @@ -184,25 +187,17 @@ static void *l1_map[V_L1_SIZE]; >> >> #if !defined(CONFIG_USER_ONLY) >> >> -static MemoryRegionSection *phys_sections; >> -static unsigned phys_sections_nb, phys_sections_nb_alloc; >> static uint16_t phys_section_unassigned; >> static uint16_t phys_section_notdirty; >> static uint16_t phys_section_rom; >> static uint16_t phys_section_watch; >> >> - >> -/* Simple allocator for PhysPageEntry nodes */ >> -static PhysPageEntry (*phys_map_nodes)[L2_SIZE]; >> -static unsigned phys_map_nodes_nb, phys_map_nodes_nb_alloc; >> - >> #define PHYS_MAP_NODE_NIL (((uint16_t)~0) >> 1) >> >> -/* This is a multi-level map on the physical address space. >> - The bottom level has pointers to MemoryRegionSections. */ >> -static PhysPageEntry phys_map = { .ptr = PHYS_MAP_NODE_NIL, .is_leaf = 0 }; >> - >> +static QemuMutex cur_map_lock; >> +static PhysMap *cur_map; >> QemuMutex mem_map_lock; >> +static PhysMap *next_map; >> >> static void io_mem_init(void); >> static void memory_map_init(void); >> @@ -383,41 +378,38 @@ static inline PageDesc *page_find(tb_page_addr_t index) >> >> #if !defined(CONFIG_USER_ONLY) >> >> -static void phys_map_node_reserve(unsigned nodes) >> +static void phys_map_node_reserve(PhysMap *map, unsigned nodes) >> { >> - if (phys_map_nodes_nb + nodes > phys_map_nodes_nb_alloc) { >> + if (map->phys_map_nodes_nb + nodes > map->phys_map_nodes_nb_alloc) { >> typedef PhysPageEntry Node[L2_SIZE]; >> - phys_map_nodes_nb_alloc = MAX(phys_map_nodes_nb_alloc * 2, 16); >> - phys_map_nodes_nb_alloc = MAX(phys_map_nodes_nb_alloc, >> - phys_map_nodes_nb + nodes); >> - phys_map_nodes = g_renew(Node, phys_map_nodes, >> - phys_map_nodes_nb_alloc); >> + map->phys_map_nodes_nb_alloc = MAX(map->phys_map_nodes_nb_alloc * 2, >> + 16); >> + map->phys_map_nodes_nb_alloc = MAX(map->phys_map_nodes_nb_alloc, >> + map->phys_map_nodes_nb + nodes); >> + map->phys_map_nodes = g_renew(Node, map->phys_map_nodes, >> + map->phys_map_nodes_nb_alloc); >> } >> } >> >> -static uint16_t phys_map_node_alloc(void) >> +static uint16_t phys_map_node_alloc(PhysMap *map) >> { >> unsigned i; >> uint16_t ret; >> >> - ret = phys_map_nodes_nb++; >> + ret = map->phys_map_nodes_nb++; >> assert(ret != PHYS_MAP_NODE_NIL); >> - assert(ret != phys_map_nodes_nb_alloc); >> + assert(ret != map->phys_map_nodes_nb_alloc); >> for (i = 0; i < L2_SIZE; ++i) { >> - phys_map_nodes[ret][i].is_leaf = 0; >> - phys_map_nodes[ret][i].ptr = PHYS_MAP_NODE_NIL; >> + map->phys_map_nodes[ret][i].is_leaf = 0; >> + map->phys_map_nodes[ret][i].ptr = PHYS_MAP_NODE_NIL; >> } >> return ret; >> } >> >> -static void phys_map_nodes_reset(void) >> -{ >> - phys_map_nodes_nb = 0; >> -} >> - >> - >> -static void phys_page_set_level(PhysPageEntry *lp, target_phys_addr_t *index, >> - target_phys_addr_t *nb, uint16_t leaf, >> +static void phys_page_set_level(PhysMap *map, PhysPageEntry *lp, >> + target_phys_addr_t *index, >> + target_phys_addr_t *nb, >> + uint16_t leaf, >> int level) >> { >> PhysPageEntry *p; >> @@ -425,8 +417,8 @@ static void phys_page_set_level(PhysPageEntry *lp, target_phys_addr_t *index, >> target_phys_addr_t step = (target_phys_addr_t)1 << (level * L2_BITS); >> >> if (!lp->is_leaf && lp->ptr == PHYS_MAP_NODE_NIL) { >> - lp->ptr = phys_map_node_alloc(); >> - p = phys_map_nodes[lp->ptr]; >> + lp->ptr = phys_map_node_alloc(map); >> + p = map->phys_map_nodes[lp->ptr]; >> if (level == 0) { >> for (i = 0; i < L2_SIZE; i++) { >> p[i].is_leaf = 1; >> @@ -434,7 +426,7 @@ static void phys_page_set_level(PhysPageEntry *lp, target_phys_addr_t *index, >> } >> } >> } else { >> - p = phys_map_nodes[lp->ptr]; >> + p = map->phys_map_nodes[lp->ptr]; >> } >> lp = &p[(*index >> (level * L2_BITS)) & (L2_SIZE - 1)]; >> >> @@ -445,24 +437,27 @@ static void phys_page_set_level(PhysPageEntry *lp, target_phys_addr_t *index, >> *index += step; >> *nb -= step; >> } else { >> - phys_page_set_level(lp, index, nb, leaf, level - 1); >> + phys_page_set_level(map, lp, index, nb, leaf, level - 1); >> } >> ++lp; >> } >> } >> >> -static void phys_page_set(target_phys_addr_t index, target_phys_addr_t nb, >> - uint16_t leaf) >> +static void phys_page_set(PhysMap *map, target_phys_addr_t index, >> + target_phys_addr_t nb, >> + uint16_t leaf) >> { >> /* Wildly overreserve - it doesn't matter much. */ >> - phys_map_node_reserve(3 * P_L2_LEVELS); >> + phys_map_node_reserve(map, 3 * P_L2_LEVELS); >> >> - phys_page_set_level(&phys_map, &index, &nb, leaf, P_L2_LEVELS - 1); >> + /* update in new tree*/ >> + phys_page_set_level(map, &map->root, &index, &nb, leaf, P_L2_LEVELS - 1); >> } >> >> -MemoryRegionSection *phys_page_find(target_phys_addr_t index) >> +static MemoryRegionSection *phys_page_find_internal(PhysMap *map, >> + target_phys_addr_t index) >> { >> - PhysPageEntry lp = phys_map; >> + PhysPageEntry lp = map->root; >> PhysPageEntry *p; >> int i; >> uint16_t s_index = phys_section_unassigned; >> @@ -471,13 +466,79 @@ MemoryRegionSection *phys_page_find(target_phys_addr_t index) >> if (lp.ptr == PHYS_MAP_NODE_NIL) { >> goto not_found; >> } >> - p = phys_map_nodes[lp.ptr]; >> + p = map->phys_map_nodes[lp.ptr]; >> lp = p[(index >> (i * L2_BITS)) & (L2_SIZE - 1)]; >> } >> >> s_index = lp.ptr; >> not_found: >> - return &phys_sections[s_index]; >> + return &map->phys_sections[s_index]; >> +} >> + >> +MemoryRegionSection *phys_page_find(target_phys_addr_t index) >> +{ >> + return phys_page_find_internal(cur_map, index); >> +} >> + >> +void physmap_get(PhysMap *map) >> +{ >> + atomic_inc(&map->ref); >> +} >> + >> +/* Untill rcu read side finished, do this reclaim */ > > Until > adopted >> +static ChunkHead physmap_reclaimer_list = { .lh_first = NULL }; > > Please insert a blank line here. > adopted >> +void physmap_reclaimer_enqueue(void *opaque, ReleaseHandler *release) >> +{ >> + reclaimer_enqueue(&physmap_reclaimer_list, opaque, release); >> +} >> + >> +static void destroy_all_mappings(PhysMap *map); > > Prototypes belong to the top of the file. > adopted >> +static void phys_map_release(PhysMap *map) >> +{ >> + /* emulate for rcu reclaimer for mr */ >> + reclaimer_worker(&physmap_reclaimer_list); >> + >> + destroy_all_mappings(map); >> + g_free(map->phys_map_nodes); >> + g_free(map->phys_sections); >> + g_free(map->views[0].ranges); >> + g_free(map->views[1].ranges); >> + g_free(map); >> +} >> + >> +void physmap_put(PhysMap *map) >> +{ >> + if (atomic_dec_and_test(&map->ref)) { >> + phys_map_release(map); >> + } >> +} >> + >> +void cur_map_update(PhysMap *next) >> +{ >> + qemu_mutex_lock(&cur_map_lock); >> + physmap_put(cur_map); >> + cur_map = next; >> + smp_mb(); >> + qemu_mutex_unlock(&cur_map_lock); >> +} >> + >> +PhysMap *cur_map_get(void) >> +{ >> + PhysMap *ret; >> + >> + qemu_mutex_lock(&cur_map_lock); >> + ret = cur_map; >> + physmap_get(ret); >> + smp_mb(); >> + qemu_mutex_unlock(&cur_map_lock); >> + return ret; >> +} >> + >> +PhysMap *alloc_next_map(void) >> +{ >> + PhysMap *next = g_malloc0(sizeof(PhysMap)); >> + atomic_set(&next->ref, 1); >> + return next; >> } >> >> bool memory_region_is_unassigned(MemoryRegion *mr) >> @@ -632,6 +693,7 @@ void cpu_exec_init_all(void) >> memory_map_init(); >> io_mem_init(); >> qemu_mutex_init(&mem_map_lock); >> + qemu_mutex_init(&cur_map_lock); >> #endif >> } >> >> @@ -2161,17 +2223,18 @@ int page_unprotect(target_ulong address, uintptr_t pc, void *puc) >> >> #define SUBPAGE_IDX(addr) ((addr) & ~TARGET_PAGE_MASK) >> typedef struct subpage_t { >> + PhysMap *map; >> MemoryRegion iomem; >> target_phys_addr_t base; >> uint16_t sub_section[TARGET_PAGE_SIZE]; >> } subpage_t; >> >> -static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end, >> - uint16_t section); >> -static subpage_t *subpage_init(target_phys_addr_t base); >> -static void destroy_page_desc(uint16_t section_index) >> +static int subpage_register(PhysMap *map, subpage_t *mmio, uint32_t start, >> + uint32_t end, uint16_t section); >> +static subpage_t *subpage_init(PhysMap *map, target_phys_addr_t base); >> +static void destroy_page_desc(PhysMap *map, uint16_t section_index) >> { >> - MemoryRegionSection *section = &phys_sections[section_index]; >> + MemoryRegionSection *section = &map->phys_sections[section_index]; >> MemoryRegion *mr = section->mr; >> >> if (mr->subpage) { >> @@ -2181,7 +2244,7 @@ static void destroy_page_desc(uint16_t section_index) >> } >> } >> >> -static void destroy_l2_mapping(PhysPageEntry *lp, unsigned level) >> +static void destroy_l2_mapping(PhysMap *map, PhysPageEntry *lp, unsigned level) >> { >> unsigned i; >> PhysPageEntry *p; >> @@ -2190,38 +2253,34 @@ static void destroy_l2_mapping(PhysPageEntry *lp, unsigned level) >> return; >> } >> >> - p = phys_map_nodes[lp->ptr]; >> + p = map->phys_map_nodes[lp->ptr]; >> for (i = 0; i < L2_SIZE; ++i) { >> if (!p[i].is_leaf) { >> - destroy_l2_mapping(&p[i], level - 1); >> + destroy_l2_mapping(map, &p[i], level - 1); >> } else { >> - destroy_page_desc(p[i].ptr); >> + destroy_page_desc(map, p[i].ptr); >> } >> } >> lp->is_leaf = 0; >> lp->ptr = PHYS_MAP_NODE_NIL; >> } >> >> -static void destroy_all_mappings(void) >> +static void destroy_all_mappings(PhysMap *map) >> { >> - destroy_l2_mapping(&phys_map, P_L2_LEVELS - 1); >> - phys_map_nodes_reset(); >> -} >> + PhysPageEntry *root = &map->root; >> >> -static uint16_t phys_section_add(MemoryRegionSection *section) >> -{ >> - if (phys_sections_nb == phys_sections_nb_alloc) { >> - phys_sections_nb_alloc = MAX(phys_sections_nb_alloc * 2, 16); >> - phys_sections = g_renew(MemoryRegionSection, phys_sections, >> - phys_sections_nb_alloc); >> - } >> - phys_sections[phys_sections_nb] = *section; >> - return phys_sections_nb++; >> + destroy_l2_mapping(map, root, P_L2_LEVELS - 1); >> } >> >> -static void phys_sections_clear(void) >> +static uint16_t phys_section_add(PhysMap *map, MemoryRegionSection *section) >> { >> - phys_sections_nb = 0; >> + if (map->phys_sections_nb == map->phys_sections_nb_alloc) { >> + map->phys_sections_nb_alloc = MAX(map->phys_sections_nb_alloc * 2, 16); >> + map->phys_sections = g_renew(MemoryRegionSection, map->phys_sections, >> + map->phys_sections_nb_alloc); >> + } >> + map->phys_sections[map->phys_sections_nb] = *section; >> + return map->phys_sections_nb++; >> } >> >> /* register physical memory. >> @@ -2232,12 +2291,13 @@ static void phys_sections_clear(void) >> start_addr and region_offset are rounded down to a page boundary >> before calculating this offset. This should not be a problem unless >> the low bits of start_addr and region_offset differ. */ >> -static void register_subpage(MemoryRegionSection *section) >> +static void register_subpage(PhysMap *map, MemoryRegionSection *section) >> { >> subpage_t *subpage; >> target_phys_addr_t base = section->offset_within_address_space >> & TARGET_PAGE_MASK; >> - MemoryRegionSection *existing = phys_page_find(base >> TARGET_PAGE_BITS); >> + MemoryRegionSection *existing = phys_page_find_internal(map, >> + base >> TARGET_PAGE_BITS); >> MemoryRegionSection subsection = { >> .offset_within_address_space = base, >> .size = TARGET_PAGE_SIZE, >> @@ -2247,30 +2307,30 @@ static void register_subpage(MemoryRegionSection *section) >> assert(existing->mr->subpage || existing->mr == &io_mem_unassigned); >> >> if (!(existing->mr->subpage)) { >> - subpage = subpage_init(base); >> + subpage = subpage_init(map, base); >> subsection.mr = &subpage->iomem; >> - phys_page_set(base >> TARGET_PAGE_BITS, 1, >> - phys_section_add(&subsection)); >> + phys_page_set(map, base >> TARGET_PAGE_BITS, 1, >> + phys_section_add(map, &subsection)); >> } else { >> subpage = container_of(existing->mr, subpage_t, iomem); >> } >> start = section->offset_within_address_space & ~TARGET_PAGE_MASK; >> end = start + section->size; >> - subpage_register(subpage, start, end, phys_section_add(section)); >> + subpage_register(map, subpage, start, end, phys_section_add(map, section)); >> } >> >> >> -static void register_multipage(MemoryRegionSection *section) >> +static void register_multipage(PhysMap *map, MemoryRegionSection *section) >> { >> target_phys_addr_t start_addr = section->offset_within_address_space; >> ram_addr_t size = section->size; >> target_phys_addr_t addr; >> - uint16_t section_index = phys_section_add(section); >> + uint16_t section_index = phys_section_add(map, section); >> >> assert(size); >> >> addr = start_addr; >> - phys_page_set(addr >> TARGET_PAGE_BITS, size >> TARGET_PAGE_BITS, >> + phys_page_set(map, addr >> TARGET_PAGE_BITS, size >> TARGET_PAGE_BITS, >> section_index); >> } >> >> @@ -2278,13 +2338,14 @@ void cpu_register_physical_memory_log(MemoryRegionSection *section, >> bool readonly) >> { >> MemoryRegionSection now = *section, remain = *section; >> + PhysMap *map = next_map; >> >> if ((now.offset_within_address_space & ~TARGET_PAGE_MASK) >> || (now.size < TARGET_PAGE_SIZE)) { >> now.size = MIN(TARGET_PAGE_ALIGN(now.offset_within_address_space) >> - now.offset_within_address_space, >> now.size); >> - register_subpage(&now); >> + register_subpage(map, &now); >> remain.size -= now.size; >> remain.offset_within_address_space += now.size; >> remain.offset_within_region += now.size; >> @@ -2292,14 +2353,14 @@ void cpu_register_physical_memory_log(MemoryRegionSection *section, >> now = remain; >> now.size &= TARGET_PAGE_MASK; >> if (now.size) { >> - register_multipage(&now); >> + register_multipage(map, &now); >> remain.size -= now.size; >> remain.offset_within_address_space += now.size; >> remain.offset_within_region += now.size; >> } >> now = remain; >> if (now.size) { >> - register_subpage(&now); >> + register_subpage(map, &now); >> } >> } >> >> @@ -3001,7 +3062,7 @@ static uint64_t subpage_read(void *opaque, target_phys_addr_t addr, >> mmio, len, addr, idx); >> #endif >> >> - section = &phys_sections[mmio->sub_section[idx]]; >> + section = &mmio->map->phys_sections[mmio->sub_section[idx]]; >> addr += mmio->base; >> addr -= section->offset_within_address_space; >> addr += section->offset_within_region; >> @@ -3020,7 +3081,7 @@ static void subpage_write(void *opaque, target_phys_addr_t addr, >> __func__, mmio, len, addr, idx, value); >> #endif >> >> - section = &phys_sections[mmio->sub_section[idx]]; >> + section = &mmio->map->phys_sections[mmio->sub_section[idx]]; >> addr += mmio->base; >> addr -= section->offset_within_address_space; >> addr += section->offset_within_region; >> @@ -3065,8 +3126,8 @@ static const MemoryRegionOps subpage_ram_ops = { >> .endianness = DEVICE_NATIVE_ENDIAN, >> }; >> >> -static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end, >> - uint16_t section) >> +static int subpage_register(PhysMap *map, subpage_t *mmio, uint32_t start, >> + uint32_t end, uint16_t section) >> { >> int idx, eidx; >> >> @@ -3078,10 +3139,10 @@ static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end, >> printf("%s: %p start %08x end %08x idx %08x eidx %08x mem %ld\n", __func__, >> mmio, start, end, idx, eidx, memory); >> #endif >> - if (memory_region_is_ram(phys_sections[section].mr)) { >> - MemoryRegionSection new_section = phys_sections[section]; >> + if (memory_region_is_ram(map->phys_sections[section].mr)) { >> + MemoryRegionSection new_section = map->phys_sections[section]; >> new_section.mr = &io_mem_subpage_ram; >> - section = phys_section_add(&new_section); >> + section = phys_section_add(map, &new_section); >> } >> for (; idx <= eidx; idx++) { >> mmio->sub_section[idx] = section; >> @@ -3090,12 +3151,13 @@ static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end, >> return 0; >> } >> >> -static subpage_t *subpage_init(target_phys_addr_t base) >> +static subpage_t *subpage_init(PhysMap *map, target_phys_addr_t base) >> { >> subpage_t *mmio; >> >> mmio = g_malloc0(sizeof(subpage_t)); >> >> + mmio->map = map; >> mmio->base = base; >> memory_region_init_io(&mmio->iomem, &subpage_ops, mmio, >> "subpage", TARGET_PAGE_SIZE); >> @@ -3104,12 +3166,12 @@ static subpage_t *subpage_init(target_phys_addr_t base) >> printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__, >> mmio, base, TARGET_PAGE_SIZE, subpage_memory); >> #endif >> - subpage_register(mmio, 0, TARGET_PAGE_SIZE-1, phys_section_unassigned); >> + subpage_register(map, mmio, 0, TARGET_PAGE_SIZE-1, phys_section_unassigned); >> >> return mmio; >> } >> >> -static uint16_t dummy_section(MemoryRegion *mr) >> +static uint16_t dummy_section(PhysMap *map, MemoryRegion *mr) >> { >> MemoryRegionSection section = { >> .mr = mr, >> @@ -3118,7 +3180,7 @@ static uint16_t dummy_section(MemoryRegion *mr) >> .size = UINT64_MAX, >> }; >> >> - return phys_section_add(§ion); >> + return phys_section_add(map, §ion); >> } >> >> MemoryRegion *iotlb_to_region(target_phys_addr_t index) >> @@ -3140,15 +3202,32 @@ static void io_mem_init(void) >> "watch", UINT64_MAX); >> } >> >> -static void core_begin(MemoryListener *listener) >> +#if 0 >> +static void physmap_init(void) >> +{ >> + FlatView v = { .ranges = NULL, >> + .nr = 0, >> + .nr_allocated = 0, >> + }; >> + >> + init_map.views[0] = v; >> + init_map.views[1] = v; >> + cur_map = &init_map; >> +} >> +#endif > > Please delete. > adopted Thanks and regards, pingfan >> + >> +static void core_begin(MemoryListener *listener, PhysMap *new_map) >> { >> - destroy_all_mappings(); >> - phys_sections_clear(); >> - phys_map.ptr = PHYS_MAP_NODE_NIL; >> - phys_section_unassigned = dummy_section(&io_mem_unassigned); >> - phys_section_notdirty = dummy_section(&io_mem_notdirty); >> - phys_section_rom = dummy_section(&io_mem_rom); >> - phys_section_watch = dummy_section(&io_mem_watch); >> + >> + new_map->root.ptr = PHYS_MAP_NODE_NIL; >> + new_map->root.is_leaf = 0; >> + >> + /* In all the map, these sections have the same index */ >> + phys_section_unassigned = dummy_section(new_map, &io_mem_unassigned); >> + phys_section_notdirty = dummy_section(new_map, &io_mem_notdirty); >> + phys_section_rom = dummy_section(new_map, &io_mem_rom); >> + phys_section_watch = dummy_section(new_map, &io_mem_watch); >> + next_map = new_map; >> } >> >> static void core_commit(MemoryListener *listener) >> @@ -3161,6 +3240,16 @@ static void core_commit(MemoryListener *listener) >> for(env = first_cpu; env != NULL; env = env->next_cpu) { >> tlb_flush(env, 1); >> } >> + >> +/* move into high layer >> + qemu_mutex_lock(&cur_map_lock); >> + if (cur_map != NULL) { >> + physmap_put(cur_map); >> + } >> + cur_map = next_map; >> + smp_mb(); >> + qemu_mutex_unlock(&cur_map_lock); >> +*/ > > Also commented out code should be deleted. > >> } >> >> static void core_region_add(MemoryListener *listener, >> @@ -3217,7 +3306,7 @@ static void core_eventfd_del(MemoryListener *listener, >> { >> } >> >> -static void io_begin(MemoryListener *listener) >> +static void io_begin(MemoryListener *listener, PhysMap *next) >> { >> } >> >> @@ -3329,6 +3418,20 @@ static void memory_map_init(void) >> memory_listener_register(&io_memory_listener, system_io); >> } >> >> +void physmap_init(void) >> +{ >> + FlatView v = { .ranges = NULL, .nr = 0, .nr_allocated = 0, >> + }; >> + PhysMap *init_map = g_malloc0(sizeof(PhysMap)); >> + >> + atomic_set(&init_map->ref, 1); >> + init_map->root.ptr = PHYS_MAP_NODE_NIL; >> + init_map->root.is_leaf = 0; >> + init_map->views[0] = v; >> + init_map->views[1] = v; >> + cur_map = init_map; >> +} >> + >> MemoryRegion *get_system_memory(void) >> { >> return system_memory; >> @@ -3391,6 +3494,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, >> uint32_t val; >> target_phys_addr_t page; >> MemoryRegionSection *section; >> + PhysMap *cur = cur_map_get(); >> >> while (len > 0) { >> page = addr & TARGET_PAGE_MASK; >> @@ -3472,6 +3576,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, >> buf += l; >> addr += l; >> } >> + physmap_put(cur); >> } >> >> /* used for ROM loading : can write in RAM and ROM */ >> diff --git a/hw/vhost.c b/hw/vhost.c >> index 43664e7..df58345 100644 >> --- a/hw/vhost.c >> +++ b/hw/vhost.c >> @@ -438,7 +438,7 @@ static bool vhost_section(MemoryRegionSection *section) >> && memory_region_is_ram(section->mr); >> } >> >> -static void vhost_begin(MemoryListener *listener) >> +static void vhost_begin(MemoryListener *listener, PhysMap *next) >> { >> } >> >> diff --git a/hw/xen_pt.c b/hw/xen_pt.c >> index 3b6d186..fba8586 100644 >> --- a/hw/xen_pt.c >> +++ b/hw/xen_pt.c >> @@ -597,7 +597,7 @@ static void xen_pt_region_update(XenPCIPassthroughState *s, >> } >> } >> >> -static void xen_pt_begin(MemoryListener *l) >> +static void xen_pt_begin(MemoryListener *l, PhysMap *next) >> { >> } >> >> diff --git a/kvm-all.c b/kvm-all.c >> index f8e4328..bc42cab 100644 >> --- a/kvm-all.c >> +++ b/kvm-all.c >> @@ -693,7 +693,7 @@ static void kvm_set_phys_mem(MemoryRegionSection *section, bool add) >> } >> } >> >> -static void kvm_begin(MemoryListener *listener) >> +static void kvm_begin(MemoryListener *listener, PhysMap *next) >> { >> } >> >> diff --git a/memory.c b/memory.c >> index c7f2cfd..54cdc7f 100644 >> --- a/memory.c >> +++ b/memory.c >> @@ -20,6 +20,7 @@ >> #include "kvm.h" >> #include <assert.h> >> #include "hw/qdev.h" >> +#include "qemu-thread.h" >> >> #define WANT_EXEC_OBSOLETE >> #include "exec-obsolete.h" >> @@ -192,7 +193,7 @@ typedef struct AddressSpaceOps AddressSpaceOps; >> /* A system address space - I/O, memory, etc. */ >> struct AddressSpace { >> MemoryRegion *root; >> - FlatView current_map; >> + int view_id; >> int ioeventfd_nb; >> MemoryRegionIoeventfd *ioeventfds; >> }; >> @@ -232,11 +233,6 @@ static void flatview_insert(FlatView *view, unsigned pos, FlatRange *range) >> ++view->nr; >> } >> >> -static void flatview_destroy(FlatView *view) >> -{ >> - g_free(view->ranges); >> -} >> - >> static bool can_merge(FlatRange *r1, FlatRange *r2) >> { >> return int128_eq(addrrange_end(r1->addr), r2->addr.start) >> @@ -594,8 +590,10 @@ static void address_space_update_ioeventfds(AddressSpace *as) >> MemoryRegionIoeventfd *ioeventfds = NULL; >> AddrRange tmp; >> unsigned i; >> + PhysMap *map = cur_map_get(); >> + FlatView *view = &map->views[as->view_id]; >> >> - FOR_EACH_FLAT_RANGE(fr, &as->current_map) { >> + FOR_EACH_FLAT_RANGE(fr, view) { >> for (i = 0; i < fr->mr->ioeventfd_nb; ++i) { >> tmp = addrrange_shift(fr->mr->ioeventfds[i].addr, >> int128_sub(fr->addr.start, >> @@ -616,6 +614,7 @@ static void address_space_update_ioeventfds(AddressSpace *as) >> g_free(as->ioeventfds); >> as->ioeventfds = ioeventfds; >> as->ioeventfd_nb = ioeventfd_nb; >> + physmap_put(map); >> } >> >> static void address_space_update_topology_pass(AddressSpace *as, >> @@ -681,21 +680,23 @@ static void address_space_update_topology_pass(AddressSpace *as, >> } >> >> >> -static void address_space_update_topology(AddressSpace *as) >> +static void address_space_update_topology(AddressSpace *as, PhysMap *prev, >> + PhysMap *next) >> { >> - FlatView old_view = as->current_map; >> + FlatView old_view = prev->views[as->view_id]; >> FlatView new_view = generate_memory_topology(as->root); >> >> address_space_update_topology_pass(as, old_view, new_view, false); >> address_space_update_topology_pass(as, old_view, new_view, true); >> + next->views[as->view_id] = new_view; >> >> - as->current_map = new_view; >> - flatview_destroy(&old_view); >> address_space_update_ioeventfds(as); >> } >> >> static void memory_region_update_topology(MemoryRegion *mr) >> { >> + PhysMap *prev, *next; >> + >> if (memory_region_transaction_depth) { >> memory_region_update_pending |= !mr || mr->enabled; >> return; >> @@ -705,16 +706,20 @@ static void memory_region_update_topology(MemoryRegion *mr) >> return; >> } >> >> - MEMORY_LISTENER_CALL_GLOBAL(begin, Forward); >> + prev = cur_map_get(); >> + /* allocate PhysMap next here */ >> + next = alloc_next_map(); >> + MEMORY_LISTENER_CALL_GLOBAL(begin, Forward, next); >> >> if (address_space_memory.root) { >> - address_space_update_topology(&address_space_memory); >> + address_space_update_topology(&address_space_memory, prev, next); >> } >> if (address_space_io.root) { >> - address_space_update_topology(&address_space_io); >> + address_space_update_topology(&address_space_io, prev, next); >> } >> >> MEMORY_LISTENER_CALL_GLOBAL(commit, Forward); >> + cur_map_update(next); >> >> memory_region_update_pending = false; >> } >> @@ -1071,7 +1076,7 @@ void memory_region_put(MemoryRegion *mr) >> >> if (atomic_dec_and_test(&mr->ref)) { >> /* to fix, using call_rcu( ,release) */ >> - mr->life_ops->put(mr); >> + physmap_reclaimer_enqueue(mr, (ReleaseHandler *)mr->life_ops->put); >> } >> } >> >> @@ -1147,13 +1152,18 @@ void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr, >> void memory_region_sync_dirty_bitmap(MemoryRegion *mr) >> { >> FlatRange *fr; >> + FlatView *fview; >> + PhysMap *map; >> >> - FOR_EACH_FLAT_RANGE(fr, &address_space_memory.current_map) { >> + map = cur_map_get(); >> + fview = &map->views[address_space_memory.view_id]; >> + FOR_EACH_FLAT_RANGE(fr, fview) { >> if (fr->mr == mr) { >> MEMORY_LISTENER_UPDATE_REGION(fr, &address_space_memory, >> Forward, log_sync); >> } >> } >> + physmap_put(map); >> } >> >> void memory_region_set_readonly(MemoryRegion *mr, bool readonly) >> @@ -1201,8 +1211,12 @@ static void memory_region_update_coalesced_range(MemoryRegion *mr) >> FlatRange *fr; >> CoalescedMemoryRange *cmr; >> AddrRange tmp; >> + FlatView *fview; >> + PhysMap *map; >> >> - FOR_EACH_FLAT_RANGE(fr, &address_space_memory.current_map) { >> + map = cur_map_get(); >> + fview = &map->views[address_space_memory.view_id]; >> + FOR_EACH_FLAT_RANGE(fr, fview) { >> if (fr->mr == mr) { >> qemu_unregister_coalesced_mmio(int128_get64(fr->addr.start), >> int128_get64(fr->addr.size)); >> @@ -1219,6 +1233,7 @@ static void memory_region_update_coalesced_range(MemoryRegion *mr) >> } >> } >> } >> + physmap_put(map); >> } >> >> void memory_region_set_coalescing(MemoryRegion *mr) >> @@ -1458,29 +1473,49 @@ static int cmp_flatrange_addr(const void *addr_, const void *fr_) >> return 0; >> } >> >> -static FlatRange *address_space_lookup(AddressSpace *as, AddrRange addr) >> +static FlatRange *address_space_lookup(FlatView *view, AddrRange addr) >> { >> - return bsearch(&addr, as->current_map.ranges, as->current_map.nr, >> + return bsearch(&addr, view->ranges, view->nr, >> sizeof(FlatRange), cmp_flatrange_addr); >> } >> >> +/* dec the ref, which inc by memory_region_find*/ >> +void memory_region_section_put(MemoryRegionSection *mrs) >> +{ >> + if (mrs->mr != NULL) { >> + memory_region_put(mrs->mr); >> + } >> +} >> + >> +/* inc mr's ref. Caller need dec mr's ref */ >> MemoryRegionSection memory_region_find(MemoryRegion *address_space, >> target_phys_addr_t addr, uint64_t size) >> { >> + PhysMap *map; >> AddressSpace *as = memory_region_to_address_space(address_space); >> AddrRange range = addrrange_make(int128_make64(addr), >> int128_make64(size)); >> - FlatRange *fr = address_space_lookup(as, range); >> + FlatView *fview; >> + >> + map = cur_map_get(); >> + >> + fview = &map->views[as->view_id]; >> + FlatRange *fr = address_space_lookup(fview, range); >> MemoryRegionSection ret = { .mr = NULL, .size = 0 }; >> >> if (!fr) { >> + physmap_put(map); >> return ret; >> } >> >> - while (fr > as->current_map.ranges >> + while (fr > fview->ranges >> && addrrange_intersects(fr[-1].addr, range)) { >> --fr; >> } >> + /* To fix, the caller must in rcu, or we must inc fr->mr->ref here >> + */ >> + memory_region_get(fr->mr); >> + physmap_put(map); >> >> ret.mr = fr->mr; >> range = addrrange_intersection(range, fr->addr); >> @@ -1497,10 +1532,13 @@ void memory_global_sync_dirty_bitmap(MemoryRegion *address_space) >> { >> AddressSpace *as = memory_region_to_address_space(address_space); >> FlatRange *fr; >> + PhysMap *map = cur_map_get(); >> + FlatView *view = &map->views[as->view_id]; >> >> - FOR_EACH_FLAT_RANGE(fr, &as->current_map) { >> + FOR_EACH_FLAT_RANGE(fr, view) { >> MEMORY_LISTENER_UPDATE_REGION(fr, as, Forward, log_sync); >> } >> + physmap_put(map); >> } >> >> void memory_global_dirty_log_start(void) >> @@ -1519,6 +1557,8 @@ static void listener_add_address_space(MemoryListener *listener, >> AddressSpace *as) >> { >> FlatRange *fr; >> + PhysMap *map; >> + FlatView *view; >> >> if (listener->address_space_filter >> && listener->address_space_filter != as->root) { >> @@ -1528,7 +1568,10 @@ static void listener_add_address_space(MemoryListener *listener, >> if (global_dirty_log) { >> listener->log_global_start(listener); >> } >> - FOR_EACH_FLAT_RANGE(fr, &as->current_map) { >> + >> + map = cur_map_get(); >> + view = &map->views[as->view_id]; >> + FOR_EACH_FLAT_RANGE(fr, view) { >> MemoryRegionSection section = { >> .mr = fr->mr, >> .address_space = as->root, >> @@ -1539,6 +1582,7 @@ static void listener_add_address_space(MemoryListener *listener, >> }; >> listener->region_add(listener, §ion); >> } >> + physmap_put(map); >> } >> >> void memory_listener_register(MemoryListener *listener, MemoryRegion *filter) >> @@ -1570,12 +1614,14 @@ void memory_listener_unregister(MemoryListener *listener) >> void set_system_memory_map(MemoryRegion *mr) >> { >> address_space_memory.root = mr; >> + address_space_memory.view_id = 0; >> memory_region_update_topology(NULL); >> } >> >> void set_system_io_map(MemoryRegion *mr) >> { >> address_space_io.root = mr; >> + address_space_io.view_id = 1; >> memory_region_update_topology(NULL); >> } >> >> diff --git a/memory.h b/memory.h >> index 357edd8..18442d4 100644 >> --- a/memory.h >> +++ b/memory.h >> @@ -256,7 +256,7 @@ typedef struct MemoryListener MemoryListener; >> * Use with memory_listener_register() and memory_listener_unregister(). >> */ >> struct MemoryListener { >> - void (*begin)(MemoryListener *listener); >> + void (*begin)(MemoryListener *listener, PhysMap *next); >> void (*commit)(MemoryListener *listener); >> void (*region_add)(MemoryListener *listener, MemoryRegionSection *section); >> void (*region_del)(MemoryListener *listener, MemoryRegionSection *section); >> @@ -829,6 +829,13 @@ void mtree_info(fprintf_function mon_printf, void *f); >> >> void memory_region_get(MemoryRegion *mr); >> void memory_region_put(MemoryRegion *mr); >> +void physmap_reclaimer_enqueue(void *opaque, ReleaseHandler *release); >> +void physmap_get(PhysMap *map); >> +void physmap_put(PhysMap *map); >> +PhysMap *cur_map_get(void); >> +PhysMap *alloc_next_map(void); >> +void cur_map_update(PhysMap *next); >> +void physmap_init(void); >> #endif >> >> #endif >> diff --git a/vl.c b/vl.c >> index 1329c30..12af523 100644 >> --- a/vl.c >> +++ b/vl.c >> @@ -3346,6 +3346,7 @@ int main(int argc, char **argv, char **envp) >> if (ram_size == 0) { >> ram_size = DEFAULT_RAM_SIZE * 1024 * 1024; >> } >> + physmap_init(); >> >> configure_accelerator(); >> >> diff --git a/xen-all.c b/xen-all.c >> index 59f2323..41d82fd 100644 >> --- a/xen-all.c >> +++ b/xen-all.c >> @@ -452,7 +452,7 @@ static void xen_set_memory(struct MemoryListener *listener, >> } >> } >> >> -static void xen_begin(MemoryListener *listener) >> +static void xen_begin(MemoryListener *listener, PhysMap *next) >> { >> } >> >> -- >> 1.7.4.4 >> -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html