|
|
0a122b |
From a2c4efbb5b968a80eb552757308c2fb2f28157c6 Mon Sep 17 00:00:00 2001
|
|
|
0a122b |
From: Marcel Apfelbaum <marcel.a@redhat.com>
|
|
|
0a122b |
Date: Sun, 19 Jan 2014 13:07:36 +0100
|
|
|
0a122b |
Subject: [PATCH 11/11] exec: separate sections and nodes per address space
|
|
|
0a122b |
|
|
|
0a122b |
RH-Author: Marcel Apfelbaum <marcel.a@redhat.com>
|
|
|
0a122b |
Message-id: <1390136856-7024-3-git-send-email-marcel.a@redhat.com>
|
|
|
0a122b |
Patchwork-id: 56811
|
|
|
0a122b |
O-Subject: [RHEL-7 qemu-kvm PATCH v2 2/2] exec: separate sections and nodes per address space
|
|
|
0a122b |
Bugzilla: 1003535
|
|
|
0a122b |
RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
|
|
|
0a122b |
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
0a122b |
RH-Acked-by: Markus Armbruster <armbru@redhat.com>
|
|
|
0a122b |
|
|
|
0a122b |
Every address space has its own nodes and sections, but
|
|
|
0a122b |
it uses the same global arrays of nodes/section.
|
|
|
0a122b |
|
|
|
0a122b |
This limits the number of devices that can be attached
|
|
|
0a122b |
to the guest to 20-30 devices. It happens because:
|
|
|
0a122b |
- The sections array is limited to 2^12 entries.
|
|
|
0a122b |
- The main memory has at least 100 sections.
|
|
|
0a122b |
- Each device address space is actually an alias to
|
|
|
0a122b |
main memory, multiplying its number of nodes/sections.
|
|
|
0a122b |
|
|
|
0a122b |
Remove the limitation by using separate arrays of
|
|
|
0a122b |
nodes and sections for each address space.
|
|
|
0a122b |
|
|
|
0a122b |
Closest upstream commit: 53cb28cbfea038f8ad50132dc8a684e638c7d48b
|
|
|
0a122b |
Signed-off-by: Marcel Apfelbaum <marcel.a@redhat.com>
|
|
|
0a122b |
---
|
|
|
0a122b |
v1 -> v2:
|
|
|
0a122b |
- The series confilcted with Juan's series:
|
|
|
0a122b |
- [RHEL7 qemu-kvm PATCH 00/40] bitmap optmization
|
|
|
0a122b |
- Conflicts solved:
|
|
|
0a122b |
- AddressSpaceDispatch was moved to exec.c
|
|
|
0a122b |
- PhysPageEntry was moved to exec.c
|
|
|
0a122b |
- Moved also PhysPageMap to exec.c
|
|
|
0a122b |
|
|
|
0a122b |
exec.c | 166 ++++++++++++++++++++++++++++++++++-------------------------------
|
|
|
0a122b |
1 file changed, 86 insertions(+), 80 deletions(-)
|
|
|
0a122b |
|
|
|
0a122b |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
0a122b |
---
|
|
|
0a122b |
exec.c | 166 +++++++++++++++++++++++++++++++++-------------------------------
|
|
|
0a122b |
1 files changed, 86 insertions(+), 80 deletions(-)
|
|
|
0a122b |
|
|
|
0a122b |
diff --git a/exec.c b/exec.c
|
|
|
0a122b |
index 01c74cd..ce9310c 100644
|
|
|
0a122b |
--- a/exec.c
|
|
|
0a122b |
+++ b/exec.c
|
|
|
0a122b |
@@ -91,25 +91,32 @@ struct PhysPageEntry {
|
|
|
0a122b |
uint16_t ptr : 15;
|
|
|
0a122b |
};
|
|
|
0a122b |
|
|
|
0a122b |
+typedef PhysPageEntry Node[L2_SIZE];
|
|
|
0a122b |
+
|
|
|
0a122b |
+typedef struct PhysPageMap {
|
|
|
0a122b |
+ unsigned sections_nb;
|
|
|
0a122b |
+ unsigned sections_nb_alloc;
|
|
|
0a122b |
+ unsigned nodes_nb;
|
|
|
0a122b |
+ unsigned nodes_nb_alloc;
|
|
|
0a122b |
+ Node *nodes;
|
|
|
0a122b |
+ MemoryRegionSection *sections;
|
|
|
0a122b |
+} PhysPageMap;
|
|
|
0a122b |
+
|
|
|
0a122b |
struct AddressSpaceDispatch {
|
|
|
0a122b |
/* This is a multi-level map on the physical address space.
|
|
|
0a122b |
* The bottom level has pointers to MemoryRegionSections.
|
|
|
0a122b |
*/
|
|
|
0a122b |
PhysPageEntry phys_map;
|
|
|
0a122b |
+ PhysPageMap map;
|
|
|
0a122b |
MemoryListener listener;
|
|
|
0a122b |
+ AddressSpace *as;
|
|
|
0a122b |
};
|
|
|
0a122b |
|
|
|
0a122b |
-static MemoryRegionSection *phys_sections;
|
|
|
0a122b |
-static unsigned phys_sections_nb, phys_sections_nb_alloc;
|
|
|
0a122b |
#define PHYS_SECTION_UNASSIGNED 0
|
|
|
0a122b |
#define PHYS_SECTION_NOTDIRTY 1
|
|
|
0a122b |
#define PHYS_SECTION_ROM 2
|
|
|
0a122b |
#define PHYS_SECTION_WATCH 3
|
|
|
0a122b |
|
|
|
0a122b |
-/* Simple allocator for PhysPageEntry nodes */
|
|
|
0a122b |
-static PhysPageEntry (*phys_map_nodes)[L2_SIZE];
|
|
|
0a122b |
-static unsigned phys_map_nodes_nb, phys_map_nodes_nb_alloc;
|
|
|
0a122b |
-
|
|
|
0a122b |
#define PHYS_MAP_NODE_NIL (((uint16_t)~0) >> 1)
|
|
|
0a122b |
|
|
|
0a122b |
static void io_mem_init(void);
|
|
|
0a122b |
@@ -121,41 +128,38 @@ static MemoryRegion io_mem_watch;
|
|
|
0a122b |
|
|
|
0a122b |
#if !defined(CONFIG_USER_ONLY)
|
|
|
0a122b |
|
|
|
0a122b |
-static void phys_map_node_reserve(unsigned nodes)
|
|
|
0a122b |
+static void phys_map_node_reserve(PhysPageMap *map, unsigned nodes)
|
|
|
0a122b |
{
|
|
|
0a122b |
- if (phys_map_nodes_nb + nodes > phys_map_nodes_nb_alloc) {
|
|
|
0a122b |
- typedef PhysPageEntry Node[L2_SIZE];
|
|
|
0a122b |
- phys_map_nodes_nb_alloc = MAX(phys_map_nodes_nb_alloc * 2, 16);
|
|
|
0a122b |
- phys_map_nodes_nb_alloc = MAX(phys_map_nodes_nb_alloc,
|
|
|
0a122b |
- phys_map_nodes_nb + nodes);
|
|
|
0a122b |
- phys_map_nodes = g_renew(Node, phys_map_nodes,
|
|
|
0a122b |
- phys_map_nodes_nb_alloc);
|
|
|
0a122b |
+ if (map->nodes_nb + nodes > map->nodes_nb_alloc) {
|
|
|
0a122b |
+ map->nodes_nb_alloc = MAX(map->nodes_nb_alloc * 2, 16);
|
|
|
0a122b |
+ map->nodes_nb_alloc = MAX(map->nodes_nb_alloc, map->nodes_nb + nodes);
|
|
|
0a122b |
+ map->nodes = g_renew(Node, map->nodes, map->nodes_nb_alloc);
|
|
|
0a122b |
}
|
|
|
0a122b |
}
|
|
|
0a122b |
|
|
|
0a122b |
-static uint16_t phys_map_node_alloc(void)
|
|
|
0a122b |
+static uint16_t phys_map_node_alloc(PhysPageMap *map)
|
|
|
0a122b |
{
|
|
|
0a122b |
unsigned i;
|
|
|
0a122b |
uint16_t ret;
|
|
|
0a122b |
|
|
|
0a122b |
- ret = phys_map_nodes_nb++;
|
|
|
0a122b |
+ ret = map->nodes_nb++;
|
|
|
0a122b |
assert(ret != PHYS_MAP_NODE_NIL);
|
|
|
0a122b |
- assert(ret != phys_map_nodes_nb_alloc);
|
|
|
0a122b |
+ assert(ret != map->nodes_nb_alloc);
|
|
|
0a122b |
for (i = 0; i < L2_SIZE; ++i) {
|
|
|
0a122b |
- phys_map_nodes[ret][i].is_leaf = 0;
|
|
|
0a122b |
- phys_map_nodes[ret][i].ptr = PHYS_MAP_NODE_NIL;
|
|
|
0a122b |
+ map->nodes[ret][i].is_leaf = 0;
|
|
|
0a122b |
+ map->nodes[ret][i].ptr = PHYS_MAP_NODE_NIL;
|
|
|
0a122b |
}
|
|
|
0a122b |
return ret;
|
|
|
0a122b |
}
|
|
|
0a122b |
|
|
|
0a122b |
-static void phys_map_nodes_reset(void)
|
|
|
0a122b |
+static void phys_map_nodes_reset(PhysPageMap *map)
|
|
|
0a122b |
{
|
|
|
0a122b |
- phys_map_nodes_nb = 0;
|
|
|
0a122b |
+ map->nodes_nb = 0;
|
|
|
0a122b |
}
|
|
|
0a122b |
|
|
|
0a122b |
|
|
|
0a122b |
-static void phys_page_set_level(PhysPageEntry *lp, hwaddr *index,
|
|
|
0a122b |
- hwaddr *nb, uint16_t leaf,
|
|
|
0a122b |
+static void phys_page_set_level(PhysPageMap *map, PhysPageEntry *lp,
|
|
|
0a122b |
+ hwaddr *index, hwaddr *nb, uint16_t leaf,
|
|
|
0a122b |
int level)
|
|
|
0a122b |
{
|
|
|
0a122b |
PhysPageEntry *p;
|
|
|
0a122b |
@@ -163,8 +167,8 @@ static void phys_page_set_level(PhysPageEntry *lp, hwaddr *index,
|
|
|
0a122b |
hwaddr step = (hwaddr)1 << (level * L2_BITS);
|
|
|
0a122b |
|
|
|
0a122b |
if (!lp->is_leaf && lp->ptr == PHYS_MAP_NODE_NIL) {
|
|
|
0a122b |
- lp->ptr = phys_map_node_alloc();
|
|
|
0a122b |
- p = phys_map_nodes[lp->ptr];
|
|
|
0a122b |
+ lp->ptr = phys_map_node_alloc(map);
|
|
|
0a122b |
+ p = map->nodes[lp->ptr];
|
|
|
0a122b |
if (level == 0) {
|
|
|
0a122b |
for (i = 0; i < L2_SIZE; i++) {
|
|
|
0a122b |
p[i].is_leaf = 1;
|
|
|
0a122b |
@@ -172,7 +176,7 @@ static void phys_page_set_level(PhysPageEntry *lp, hwaddr *index,
|
|
|
0a122b |
}
|
|
|
0a122b |
}
|
|
|
0a122b |
} else {
|
|
|
0a122b |
- p = phys_map_nodes[lp->ptr];
|
|
|
0a122b |
+ p = map->nodes[lp->ptr];
|
|
|
0a122b |
}
|
|
|
0a122b |
lp = &p[(*index >> (level * L2_BITS)) & (L2_SIZE - 1)];
|
|
|
0a122b |
|
|
|
0a122b |
@@ -183,7 +187,7 @@ static void phys_page_set_level(PhysPageEntry *lp, hwaddr *index,
|
|
|
0a122b |
*index += step;
|
|
|
0a122b |
*nb -= step;
|
|
|
0a122b |
} else {
|
|
|
0a122b |
- phys_page_set_level(lp, index, nb, leaf, level - 1);
|
|
|
0a122b |
+ phys_page_set_level(map, lp, index, nb, leaf, level - 1);
|
|
|
0a122b |
}
|
|
|
0a122b |
++lp;
|
|
|
0a122b |
}
|
|
|
0a122b |
@@ -194,9 +198,10 @@ static void phys_page_set(AddressSpaceDispatch *d,
|
|
|
0a122b |
uint16_t leaf)
|
|
|
0a122b |
{
|
|
|
0a122b |
/* Wildly overreserve - it doesn't matter much. */
|
|
|
0a122b |
- phys_map_node_reserve(3 * P_L2_LEVELS);
|
|
|
0a122b |
+ phys_map_node_reserve(&d->map, 3 * P_L2_LEVELS);
|
|
|
0a122b |
|
|
|
0a122b |
- phys_page_set_level(&d->phys_map, &index, &nb, leaf, P_L2_LEVELS - 1);
|
|
|
0a122b |
+ phys_page_set_level(&d->map, &d->phys_map, &index,
|
|
|
0a122b |
+ &nb, leaf, P_L2_LEVELS - 1);
|
|
|
0a122b |
}
|
|
|
0a122b |
|
|
|
0a122b |
MemoryRegionSection *phys_page_find(AddressSpaceDispatch *d, hwaddr index)
|
|
|
0a122b |
@@ -210,13 +215,13 @@ MemoryRegionSection *phys_page_find(AddressSpaceDispatch *d, hwaddr index)
|
|
|
0a122b |
if (lp.ptr == PHYS_MAP_NODE_NIL) {
|
|
|
0a122b |
goto not_found;
|
|
|
0a122b |
}
|
|
|
0a122b |
- p = phys_map_nodes[lp.ptr];
|
|
|
0a122b |
+ p = d->map.nodes[lp.ptr];
|
|
|
0a122b |
lp = p[(index >> (i * L2_BITS)) & (L2_SIZE - 1)];
|
|
|
0a122b |
}
|
|
|
0a122b |
|
|
|
0a122b |
s_index = lp.ptr;
|
|
|
0a122b |
not_found:
|
|
|
0a122b |
- return &phys_sections[s_index];
|
|
|
0a122b |
+ return &d->map.sections[s_index];
|
|
|
0a122b |
}
|
|
|
0a122b |
|
|
|
0a122b |
bool memory_region_is_unassigned(MemoryRegion *mr)
|
|
|
0a122b |
@@ -657,7 +662,7 @@ hwaddr memory_region_section_get_iotlb(CPUArchState *env,
|
|
|
0a122b |
and avoid full address decoding in every device.
|
|
|
0a122b |
We can't use the high bits of pd for this because
|
|
|
0a122b |
IO_MEM_ROMD uses these as a ram address. */
|
|
|
0a122b |
- iotlb = section - phys_sections;
|
|
|
0a122b |
+ iotlb = section - address_space_memory.dispatch->map.sections;
|
|
|
0a122b |
iotlb += memory_region_section_addr(section, paddr);
|
|
|
0a122b |
}
|
|
|
0a122b |
|
|
|
0a122b |
@@ -683,13 +688,14 @@ hwaddr memory_region_section_get_iotlb(CPUArchState *env,
|
|
|
0a122b |
#define SUBPAGE_IDX(addr) ((addr) & ~TARGET_PAGE_MASK)
|
|
|
0a122b |
typedef struct subpage_t {
|
|
|
0a122b |
MemoryRegion iomem;
|
|
|
0a122b |
+ AddressSpace *as;
|
|
|
0a122b |
hwaddr base;
|
|
|
0a122b |
uint16_t sub_section[TARGET_PAGE_SIZE];
|
|
|
0a122b |
} subpage_t;
|
|
|
0a122b |
|
|
|
0a122b |
static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
|
|
|
0a122b |
uint16_t section);
|
|
|
0a122b |
-static subpage_t *subpage_init(hwaddr base);
|
|
|
0a122b |
+static subpage_t *subpage_init(AddressSpace *as, hwaddr base);
|
|
|
0a122b |
|
|
|
0a122b |
static void *(*phys_mem_alloc)(size_t size) = qemu_anon_ram_alloc;
|
|
|
0a122b |
|
|
|
0a122b |
@@ -703,9 +709,9 @@ void phys_mem_set_alloc(void *(*alloc)(size_t))
|
|
|
0a122b |
phys_mem_alloc = alloc;
|
|
|
0a122b |
}
|
|
|
0a122b |
|
|
|
0a122b |
-static void destroy_page_desc(uint16_t section_index)
|
|
|
0a122b |
+static void destroy_page_desc(PhysPageMap *map, uint16_t section_index)
|
|
|
0a122b |
{
|
|
|
0a122b |
- MemoryRegionSection *section = &phys_sections[section_index];
|
|
|
0a122b |
+ MemoryRegionSection *section = &map->sections[section_index];
|
|
|
0a122b |
MemoryRegion *mr = section->mr;
|
|
|
0a122b |
|
|
|
0a122b |
if (mr->subpage) {
|
|
|
0a122b |
@@ -715,7 +721,8 @@ static void destroy_page_desc(uint16_t section_index)
|
|
|
0a122b |
}
|
|
|
0a122b |
}
|
|
|
0a122b |
|
|
|
0a122b |
-static void destroy_l2_mapping(PhysPageEntry *lp, unsigned level)
|
|
|
0a122b |
+static void destroy_l2_mapping(PhysPageMap *map, PhysPageEntry *lp,
|
|
|
0a122b |
+ unsigned level)
|
|
|
0a122b |
{
|
|
|
0a122b |
unsigned i;
|
|
|
0a122b |
PhysPageEntry *p;
|
|
|
0a122b |
@@ -724,12 +731,12 @@ static void destroy_l2_mapping(PhysPageEntry *lp, unsigned level)
|
|
|
0a122b |
return;
|
|
|
0a122b |
}
|
|
|
0a122b |
|
|
|
0a122b |
- p = phys_map_nodes[lp->ptr];
|
|
|
0a122b |
+ p = map->nodes[lp->ptr];
|
|
|
0a122b |
for (i = 0; i < L2_SIZE; ++i) {
|
|
|
0a122b |
if (!p[i].is_leaf) {
|
|
|
0a122b |
- destroy_l2_mapping(&p[i], level - 1);
|
|
|
0a122b |
+ destroy_l2_mapping(map, &p[i], level - 1);
|
|
|
0a122b |
} else {
|
|
|
0a122b |
- destroy_page_desc(p[i].ptr);
|
|
|
0a122b |
+ destroy_page_desc(map, p[i].ptr);
|
|
|
0a122b |
}
|
|
|
0a122b |
}
|
|
|
0a122b |
lp->is_leaf = 0;
|
|
|
0a122b |
@@ -738,24 +745,25 @@ static void destroy_l2_mapping(PhysPageEntry *lp, unsigned level)
|
|
|
0a122b |
|
|
|
0a122b |
static void destroy_all_mappings(AddressSpaceDispatch *d)
|
|
|
0a122b |
{
|
|
|
0a122b |
- destroy_l2_mapping(&d->phys_map, P_L2_LEVELS - 1);
|
|
|
0a122b |
- phys_map_nodes_reset();
|
|
|
0a122b |
+ destroy_l2_mapping(&d->map, &d->phys_map, P_L2_LEVELS - 1);
|
|
|
0a122b |
+ phys_map_nodes_reset(&d->map);
|
|
|
0a122b |
}
|
|
|
0a122b |
|
|
|
0a122b |
-static uint16_t phys_section_add(MemoryRegionSection *section)
|
|
|
0a122b |
+static uint16_t phys_section_add(PhysPageMap *map,
|
|
|
0a122b |
+ MemoryRegionSection *section)
|
|
|
0a122b |
{
|
|
|
0a122b |
- if (phys_sections_nb == phys_sections_nb_alloc) {
|
|
|
0a122b |
- phys_sections_nb_alloc = MAX(phys_sections_nb_alloc * 2, 16);
|
|
|
0a122b |
- phys_sections = g_renew(MemoryRegionSection, phys_sections,
|
|
|
0a122b |
- phys_sections_nb_alloc);
|
|
|
0a122b |
+ if (map->sections_nb == map->sections_nb_alloc) {
|
|
|
0a122b |
+ map->sections_nb_alloc = MAX(map->sections_nb_alloc * 2, 16);
|
|
|
0a122b |
+ map->sections = g_renew(MemoryRegionSection, map->sections,
|
|
|
0a122b |
+ map->sections_nb_alloc);
|
|
|
0a122b |
}
|
|
|
0a122b |
- phys_sections[phys_sections_nb] = *section;
|
|
|
0a122b |
- return phys_sections_nb++;
|
|
|
0a122b |
+ map->sections[map->sections_nb] = *section;
|
|
|
0a122b |
+ return map->sections_nb++;
|
|
|
0a122b |
}
|
|
|
0a122b |
|
|
|
0a122b |
-static void phys_sections_clear(void)
|
|
|
0a122b |
+static void phys_sections_clear(PhysPageMap *map)
|
|
|
0a122b |
{
|
|
|
0a122b |
- phys_sections_nb = 0;
|
|
|
0a122b |
+ map->sections_nb = 0;
|
|
|
0a122b |
}
|
|
|
0a122b |
|
|
|
0a122b |
static void register_subpage(AddressSpaceDispatch *d, MemoryRegionSection *section)
|
|
|
0a122b |
@@ -773,16 +781,16 @@ static void register_subpage(AddressSpaceDispatch *d, MemoryRegionSection *secti
|
|
|
0a122b |
assert(existing->mr->subpage || existing->mr == &io_mem_unassigned);
|
|
|
0a122b |
|
|
|
0a122b |
if (!(existing->mr->subpage)) {
|
|
|
0a122b |
- subpage = subpage_init(base);
|
|
|
0a122b |
+ subpage = subpage_init(d->as, base);
|
|
|
0a122b |
subsection.mr = &subpage->iomem;
|
|
|
0a122b |
phys_page_set(d, base >> TARGET_PAGE_BITS, 1,
|
|
|
0a122b |
- phys_section_add(&subsection));
|
|
|
0a122b |
+ phys_section_add(&d->map, &subsection));
|
|
|
0a122b |
} else {
|
|
|
0a122b |
subpage = container_of(existing->mr, subpage_t, iomem);
|
|
|
0a122b |
}
|
|
|
0a122b |
start = section->offset_within_address_space & ~TARGET_PAGE_MASK;
|
|
|
0a122b |
end = start + section->size - 1;
|
|
|
0a122b |
- subpage_register(subpage, start, end, phys_section_add(section));
|
|
|
0a122b |
+ subpage_register(subpage, start, end, phys_section_add(&d->map, section));
|
|
|
0a122b |
}
|
|
|
0a122b |
|
|
|
0a122b |
|
|
|
0a122b |
@@ -791,7 +799,7 @@ static void register_multipage(AddressSpaceDispatch *d, MemoryRegionSection *sec
|
|
|
0a122b |
hwaddr start_addr = section->offset_within_address_space;
|
|
|
0a122b |
ram_addr_t size = section->size;
|
|
|
0a122b |
hwaddr addr;
|
|
|
0a122b |
- uint16_t section_index = phys_section_add(section);
|
|
|
0a122b |
+ uint16_t section_index = phys_section_add(&d->map, section);
|
|
|
0a122b |
|
|
|
0a122b |
assert(size);
|
|
|
0a122b |
|
|
|
0a122b |
@@ -1619,7 +1627,7 @@ static uint64_t subpage_read(void *opaque, hwaddr addr,
|
|
|
0a122b |
mmio, len, addr, idx);
|
|
|
0a122b |
#endif
|
|
|
0a122b |
|
|
|
0a122b |
- section = &phys_sections[mmio->sub_section[idx]];
|
|
|
0a122b |
+ section = &mmio->as->dispatch->map.sections[mmio->sub_section[idx]];
|
|
|
0a122b |
addr += mmio->base;
|
|
|
0a122b |
addr -= section->offset_within_address_space;
|
|
|
0a122b |
addr += section->offset_within_region;
|
|
|
0a122b |
@@ -1638,7 +1646,7 @@ static void subpage_write(void *opaque, hwaddr addr,
|
|
|
0a122b |
__func__, mmio, len, addr, idx, value);
|
|
|
0a122b |
#endif
|
|
|
0a122b |
|
|
|
0a122b |
- section = &phys_sections[mmio->sub_section[idx]];
|
|
|
0a122b |
+ section = &mmio->as->dispatch->map.sections[mmio->sub_section[idx]];
|
|
|
0a122b |
addr += mmio->base;
|
|
|
0a122b |
addr -= section->offset_within_address_space;
|
|
|
0a122b |
addr += section->offset_within_region;
|
|
|
0a122b |
@@ -1696,10 +1704,10 @@ static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
|
|
|
0a122b |
printf("%s: %p start %08x end %08x idx %08x eidx %08x mem %ld\n", __func__,
|
|
|
0a122b |
mmio, start, end, idx, eidx, memory);
|
|
|
0a122b |
#endif
|
|
|
0a122b |
- if (memory_region_is_ram(phys_sections[section].mr)) {
|
|
|
0a122b |
- MemoryRegionSection new_section = phys_sections[section];
|
|
|
0a122b |
+ if (memory_region_is_ram(mmio->as->dispatch->map.sections[section].mr)) {
|
|
|
0a122b |
+ MemoryRegionSection new_section = mmio->as->dispatch->map.sections[section];
|
|
|
0a122b |
new_section.mr = &io_mem_subpage_ram;
|
|
|
0a122b |
- section = phys_section_add(&new_section);
|
|
|
0a122b |
+ section = phys_section_add(&mmio->as->dispatch->map, &new_section);
|
|
|
0a122b |
}
|
|
|
0a122b |
for (; idx <= eidx; idx++) {
|
|
|
0a122b |
mmio->sub_section[idx] = section;
|
|
|
0a122b |
@@ -1708,12 +1716,13 @@ static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
|
|
|
0a122b |
return 0;
|
|
|
0a122b |
}
|
|
|
0a122b |
|
|
|
0a122b |
-static subpage_t *subpage_init(hwaddr base)
|
|
|
0a122b |
+static subpage_t *subpage_init(AddressSpace *as, hwaddr base)
|
|
|
0a122b |
{
|
|
|
0a122b |
subpage_t *mmio;
|
|
|
0a122b |
|
|
|
0a122b |
mmio = g_malloc0(sizeof(subpage_t));
|
|
|
0a122b |
|
|
|
0a122b |
+ mmio->as = as;
|
|
|
0a122b |
mmio->base = base;
|
|
|
0a122b |
memory_region_init_io(&mmio->iomem, &subpage_ops, mmio,
|
|
|
0a122b |
"subpage", TARGET_PAGE_SIZE);
|
|
|
0a122b |
@@ -1727,7 +1736,7 @@ static subpage_t *subpage_init(hwaddr base)
|
|
|
0a122b |
return mmio;
|
|
|
0a122b |
}
|
|
|
0a122b |
|
|
|
0a122b |
-static uint16_t dummy_section(MemoryRegion *mr)
|
|
|
0a122b |
+static uint16_t dummy_section(PhysPageMap *map, MemoryRegion *mr)
|
|
|
0a122b |
{
|
|
|
0a122b |
MemoryRegionSection section = {
|
|
|
0a122b |
.mr = mr,
|
|
|
0a122b |
@@ -1736,12 +1745,13 @@ static uint16_t dummy_section(MemoryRegion *mr)
|
|
|
0a122b |
.size = UINT64_MAX,
|
|
|
0a122b |
};
|
|
|
0a122b |
|
|
|
0a122b |
- return phys_section_add(§ion);
|
|
|
0a122b |
+ return phys_section_add(map, §ion);
|
|
|
0a122b |
}
|
|
|
0a122b |
|
|
|
0a122b |
MemoryRegion *iotlb_to_region(hwaddr index)
|
|
|
0a122b |
{
|
|
|
0a122b |
- return phys_sections[index & ~TARGET_PAGE_MASK].mr;
|
|
|
0a122b |
+ return address_space_memory.dispatch->map.sections[
|
|
|
0a122b |
+ index & ~TARGET_PAGE_MASK].mr;
|
|
|
0a122b |
}
|
|
|
0a122b |
|
|
|
0a122b |
static void io_mem_init(void)
|
|
|
0a122b |
@@ -1761,23 +1771,19 @@ static void io_mem_init(void)
|
|
|
0a122b |
static void mem_begin(MemoryListener *listener)
|
|
|
0a122b |
{
|
|
|
0a122b |
AddressSpaceDispatch *d = container_of(listener, AddressSpaceDispatch, listener);
|
|
|
0a122b |
+ uint16_t n;
|
|
|
0a122b |
|
|
|
0a122b |
destroy_all_mappings(d);
|
|
|
0a122b |
d->phys_map.ptr = PHYS_MAP_NODE_NIL;
|
|
|
0a122b |
-}
|
|
|
0a122b |
-
|
|
|
0a122b |
-static void core_begin(MemoryListener *listener)
|
|
|
0a122b |
-{
|
|
|
0a122b |
- uint16_t n;
|
|
|
0a122b |
|
|
|
0a122b |
- phys_sections_clear();
|
|
|
0a122b |
- n = dummy_section(&io_mem_unassigned);
|
|
|
0a122b |
+ phys_sections_clear(&d->map);
|
|
|
0a122b |
+ n = dummy_section(&d->map, &io_mem_unassigned);
|
|
|
0a122b |
assert(n == PHYS_SECTION_UNASSIGNED);
|
|
|
0a122b |
- n = dummy_section(&io_mem_notdirty);
|
|
|
0a122b |
+ n = dummy_section(&d->map, &io_mem_notdirty);
|
|
|
0a122b |
assert(n == PHYS_SECTION_NOTDIRTY);
|
|
|
0a122b |
- n = dummy_section(&io_mem_rom);
|
|
|
0a122b |
+ n = dummy_section(&d->map, &io_mem_rom);
|
|
|
0a122b |
assert(n == PHYS_SECTION_ROM);
|
|
|
0a122b |
- n = dummy_section(&io_mem_watch);
|
|
|
0a122b |
+ n = dummy_section(&d->map, &io_mem_watch);
|
|
|
0a122b |
assert(n == PHYS_SECTION_WATCH);
|
|
|
0a122b |
}
|
|
|
0a122b |
|
|
|
0a122b |
@@ -1822,7 +1828,6 @@ static void io_region_del(MemoryListener *listener,
|
|
|
0a122b |
}
|
|
|
0a122b |
|
|
|
0a122b |
static MemoryListener core_memory_listener = {
|
|
|
0a122b |
- .begin = core_begin,
|
|
|
0a122b |
.log_global_start = core_log_global_start,
|
|
|
0a122b |
.log_global_stop = core_log_global_stop,
|
|
|
0a122b |
.priority = 1,
|
|
|
0a122b |
@@ -1840,7 +1845,7 @@ static MemoryListener tcg_memory_listener = {
|
|
|
0a122b |
|
|
|
0a122b |
void address_space_init_dispatch(AddressSpace *as)
|
|
|
0a122b |
{
|
|
|
0a122b |
- AddressSpaceDispatch *d = g_new(AddressSpaceDispatch, 1);
|
|
|
0a122b |
+ AddressSpaceDispatch *d = g_new0(AddressSpaceDispatch, 1);
|
|
|
0a122b |
|
|
|
0a122b |
d->phys_map = (PhysPageEntry) { .ptr = PHYS_MAP_NODE_NIL, .is_leaf = 0 };
|
|
|
0a122b |
d->listener = (MemoryListener) {
|
|
|
0a122b |
@@ -1849,6 +1854,7 @@ void address_space_init_dispatch(AddressSpace *as)
|
|
|
0a122b |
.region_nop = mem_add,
|
|
|
0a122b |
.priority = 0,
|
|
|
0a122b |
};
|
|
|
0a122b |
+ d->as = as;
|
|
|
0a122b |
as->dispatch = d;
|
|
|
0a122b |
memory_listener_register(&d->listener, as);
|
|
|
0a122b |
}
|
|
|
0a122b |
@@ -1858,7 +1864,7 @@ void address_space_destroy_dispatch(AddressSpace *as)
|
|
|
0a122b |
AddressSpaceDispatch *d = as->dispatch;
|
|
|
0a122b |
|
|
|
0a122b |
memory_listener_unregister(&d->listener);
|
|
|
0a122b |
- destroy_l2_mapping(&d->phys_map, P_L2_LEVELS - 1);
|
|
|
0a122b |
+ destroy_l2_mapping(&d->map, &d->phys_map, P_L2_LEVELS - 1);
|
|
|
0a122b |
g_free(d);
|
|
|
0a122b |
as->dispatch = NULL;
|
|
|
0a122b |
}
|
|
|
0a122b |
@@ -2446,7 +2452,7 @@ void stl_phys_notdirty(hwaddr addr, uint32_t val)
|
|
|
0a122b |
if (!memory_region_is_ram(section->mr) || section->readonly) {
|
|
|
0a122b |
addr = memory_region_section_addr(section, addr);
|
|
|
0a122b |
if (memory_region_is_ram(section->mr)) {
|
|
|
0a122b |
- section = &phys_sections[PHYS_SECTION_ROM];
|
|
|
0a122b |
+ section = &address_space_memory.dispatch->map.sections[PHYS_SECTION_ROM];
|
|
|
0a122b |
}
|
|
|
0a122b |
io_mem_write(section->mr, addr, val, 4);
|
|
|
0a122b |
} else {
|
|
|
0a122b |
@@ -2479,7 +2485,7 @@ void stq_phys_notdirty(hwaddr addr, uint64_t val)
|
|
|
0a122b |
if (!memory_region_is_ram(section->mr) || section->readonly) {
|
|
|
0a122b |
addr = memory_region_section_addr(section, addr);
|
|
|
0a122b |
if (memory_region_is_ram(section->mr)) {
|
|
|
0a122b |
- section = &phys_sections[PHYS_SECTION_ROM];
|
|
|
0a122b |
+ section = &address_space_memory.dispatch->map.sections[PHYS_SECTION_ROM];
|
|
|
0a122b |
}
|
|
|
0a122b |
#ifdef TARGET_WORDS_BIGENDIAN
|
|
|
0a122b |
io_mem_write(section->mr, addr, val >> 32, 4);
|
|
|
0a122b |
@@ -2508,7 +2514,7 @@ static inline void stl_phys_internal(hwaddr addr, uint32_t val,
|
|
|
0a122b |
if (!memory_region_is_ram(section->mr) || section->readonly) {
|
|
|
0a122b |
addr = memory_region_section_addr(section, addr);
|
|
|
0a122b |
if (memory_region_is_ram(section->mr)) {
|
|
|
0a122b |
- section = &phys_sections[PHYS_SECTION_ROM];
|
|
|
0a122b |
+ section = &address_space_memory.dispatch->map.sections[PHYS_SECTION_ROM];
|
|
|
0a122b |
}
|
|
|
0a122b |
#if defined(TARGET_WORDS_BIGENDIAN)
|
|
|
0a122b |
if (endian == DEVICE_LITTLE_ENDIAN) {
|
|
|
0a122b |
@@ -2575,7 +2581,7 @@ static inline void stw_phys_internal(hwaddr addr, uint32_t val,
|
|
|
0a122b |
if (!memory_region_is_ram(section->mr) || section->readonly) {
|
|
|
0a122b |
addr = memory_region_section_addr(section, addr);
|
|
|
0a122b |
if (memory_region_is_ram(section->mr)) {
|
|
|
0a122b |
- section = &phys_sections[PHYS_SECTION_ROM];
|
|
|
0a122b |
+ section = &address_space_memory.dispatch->map.sections[PHYS_SECTION_ROM];
|
|
|
0a122b |
}
|
|
|
0a122b |
#if defined(TARGET_WORDS_BIGENDIAN)
|
|
|
0a122b |
if (endian == DEVICE_LITTLE_ENDIAN) {
|
|
|
0a122b |
--
|
|
|
0a122b |
1.7.1
|
|
|
0a122b |
|