[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 09/15] memory: prepare flatview and radix-tree for r
From: |
Liu Ping Fan |
Subject: |
[Qemu-devel] [PATCH 09/15] memory: prepare flatview and radix-tree for rcu style access |
Date: |
Wed, 8 Aug 2012 14:25:50 +0800 |
From: Liu Ping Fan <address@hidden>
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 <address@hidden>
---
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 */
+static ChunkHead physmap_reclaimer_list = { .lh_first = NULL };
+void physmap_reclaimer_enqueue(void *opaque, ReleaseHandler *release)
+{
+ reclaimer_enqueue(&physmap_reclaimer_list, opaque, release);
+}
+
+static void destroy_all_mappings(PhysMap *map);
+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
+
+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);
+*/
}
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
- Re: [Qemu-devel] [PATCH 04/15] memory: MemoryRegion topology must be stable when updating, (continued)
[Qemu-devel] [PATCH 05/15] memory: introduce life_ops to MemoryRegion, Liu Ping Fan, 2012/08/08
[Qemu-devel] [PATCH 06/15] memory: use refcnt to manage MemoryRegion, Liu Ping Fan, 2012/08/08
[Qemu-devel] [PATCH 10/15] memory: change tcg related code to using PhysMap, Liu Ping Fan, 2012/08/08
[Qemu-devel] [PATCH 09/15] memory: prepare flatview and radix-tree for rcu style access,
Liu Ping Fan <=
Re: [Qemu-devel] [PATCH 09/15] memory: prepare flatview and radix-tree for rcu style access, Blue Swirl, 2012/08/08
[Qemu-devel] [PATCH 13/15] hotplug: introduce qdev_unplug_complete() to remove device from views, Liu Ping Fan, 2012/08/08