memory: maintain a list of address spaces

Instead of embedding knowledge of the memory and I/O address spaces in the
memory core, maintain a list of all address spaces.  This list will later
be extended dynamically for other bus masters.

Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
This commit is contained in:
Avi Kivity 2012-10-02 15:28:50 +02:00
parent 9ad2bbc167
commit 0d673e36a7
2 changed files with 48 additions and 29 deletions

View File

@ -28,6 +28,9 @@ static bool global_dirty_log = false;
static QTAILQ_HEAD(memory_listeners, MemoryListener) memory_listeners static QTAILQ_HEAD(memory_listeners, MemoryListener) memory_listeners
= QTAILQ_HEAD_INITIALIZER(memory_listeners); = QTAILQ_HEAD_INITIALIZER(memory_listeners);
static QTAILQ_HEAD(, AddressSpace) address_spaces
= QTAILQ_HEAD_INITIALIZER(address_spaces);
typedef struct AddrRange AddrRange; typedef struct AddrRange AddrRange;
/* /*
@ -449,14 +452,15 @@ static AddressSpace address_space_io;
static AddressSpace *memory_region_to_address_space(MemoryRegion *mr) static AddressSpace *memory_region_to_address_space(MemoryRegion *mr)
{ {
AddressSpace *as;
while (mr->parent) { while (mr->parent) {
mr = mr->parent; mr = mr->parent;
} }
if (mr == address_space_memory.root) { QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
return &address_space_memory; if (mr == as->root) {
} return as;
if (mr == address_space_io.root) { }
return &address_space_io;
} }
abort(); abort();
} }
@ -729,16 +733,15 @@ void memory_region_transaction_begin(void)
void memory_region_transaction_commit(void) void memory_region_transaction_commit(void)
{ {
AddressSpace *as;
assert(memory_region_transaction_depth); assert(memory_region_transaction_depth);
--memory_region_transaction_depth; --memory_region_transaction_depth;
if (!memory_region_transaction_depth) { if (!memory_region_transaction_depth) {
MEMORY_LISTENER_CALL_GLOBAL(begin, Forward); MEMORY_LISTENER_CALL_GLOBAL(begin, Forward);
if (address_space_memory.root) { QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
address_space_update_topology(&address_space_memory); address_space_update_topology(as);
}
if (address_space_io.root) {
address_space_update_topology(&address_space_io);
} }
MEMORY_LISTENER_CALL_GLOBAL(commit, Forward); MEMORY_LISTENER_CALL_GLOBAL(commit, Forward);
@ -1072,12 +1075,14 @@ void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr,
void memory_region_sync_dirty_bitmap(MemoryRegion *mr) void memory_region_sync_dirty_bitmap(MemoryRegion *mr)
{ {
AddressSpace *as;
FlatRange *fr; FlatRange *fr;
FOR_EACH_FLAT_RANGE(fr, address_space_memory.current_map) { QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
if (fr->mr == mr) { FOR_EACH_FLAT_RANGE(fr, as->current_map) {
MEMORY_LISTENER_UPDATE_REGION(fr, &address_space_memory, if (fr->mr == mr) {
Forward, log_sync); MEMORY_LISTENER_UPDATE_REGION(fr, as, Forward, log_sync);
}
} }
} }
} }
@ -1120,13 +1125,13 @@ void *memory_region_get_ram_ptr(MemoryRegion *mr)
return qemu_get_ram_ptr(mr->ram_addr & TARGET_PAGE_MASK); return qemu_get_ram_ptr(mr->ram_addr & TARGET_PAGE_MASK);
} }
static void memory_region_update_coalesced_range(MemoryRegion *mr) static void memory_region_update_coalesced_range_as(MemoryRegion *mr, AddressSpace *as)
{ {
FlatRange *fr; FlatRange *fr;
CoalescedMemoryRange *cmr; CoalescedMemoryRange *cmr;
AddrRange tmp; AddrRange tmp;
FOR_EACH_FLAT_RANGE(fr, address_space_memory.current_map) { FOR_EACH_FLAT_RANGE(fr, as->current_map) {
if (fr->mr == mr) { if (fr->mr == mr) {
qemu_unregister_coalesced_mmio(int128_get64(fr->addr.start), qemu_unregister_coalesced_mmio(int128_get64(fr->addr.start),
int128_get64(fr->addr.size)); int128_get64(fr->addr.size));
@ -1145,6 +1150,15 @@ static void memory_region_update_coalesced_range(MemoryRegion *mr)
} }
} }
static void memory_region_update_coalesced_range(MemoryRegion *mr)
{
AddressSpace *as;
QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
memory_region_update_coalesced_range_as(mr, as);
}
}
void memory_region_set_coalescing(MemoryRegion *mr) void memory_region_set_coalescing(MemoryRegion *mr)
{ {
memory_region_clear_coalescing(mr); memory_region_clear_coalescing(mr);
@ -1450,10 +1464,6 @@ static void listener_add_address_space(MemoryListener *listener,
{ {
FlatRange *fr; FlatRange *fr;
if (!as->root) {
return;
}
if (listener->address_space_filter if (listener->address_space_filter
&& listener->address_space_filter != as->root) { && listener->address_space_filter != as->root) {
return; return;
@ -1478,6 +1488,7 @@ static void listener_add_address_space(MemoryListener *listener,
void memory_listener_register(MemoryListener *listener, MemoryRegion *filter) void memory_listener_register(MemoryListener *listener, MemoryRegion *filter)
{ {
MemoryListener *other = NULL; MemoryListener *other = NULL;
AddressSpace *as;
listener->address_space_filter = filter; listener->address_space_filter = filter;
if (QTAILQ_EMPTY(&memory_listeners) if (QTAILQ_EMPTY(&memory_listeners)
@ -1492,8 +1503,10 @@ void memory_listener_register(MemoryListener *listener, MemoryRegion *filter)
} }
QTAILQ_INSERT_BEFORE(other, listener, link); QTAILQ_INSERT_BEFORE(other, listener, link);
} }
listener_add_address_space(listener, &address_space_memory);
listener_add_address_space(listener, &address_space_io); QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
listener_add_address_space(listener, as);
}
} }
void memory_listener_unregister(MemoryListener *listener) void memory_listener_unregister(MemoryListener *listener)
@ -1507,17 +1520,21 @@ void address_space_init(AddressSpace *as, MemoryRegion *root)
as->root = root; as->root = root;
as->current_map = g_new(FlatView, 1); as->current_map = g_new(FlatView, 1);
flatview_init(as->current_map); flatview_init(as->current_map);
QTAILQ_INSERT_TAIL(&address_spaces, as, address_spaces_link);
as->name = NULL;
memory_region_transaction_commit(); memory_region_transaction_commit();
} }
void set_system_memory_map(MemoryRegion *mr) void set_system_memory_map(MemoryRegion *mr)
{ {
address_space_init(&address_space_memory, mr); address_space_init(&address_space_memory, mr);
address_space_memory.name = "memory";
} }
void set_system_io_map(MemoryRegion *mr) void set_system_io_map(MemoryRegion *mr)
{ {
address_space_init(&address_space_io, mr); address_space_init(&address_space_io, mr);
address_space_io.name = "I/O";
} }
uint64_t io_mem_read(MemoryRegion *mr, target_phys_addr_t addr, unsigned size) uint64_t io_mem_read(MemoryRegion *mr, target_phys_addr_t addr, unsigned size)
@ -1637,16 +1654,16 @@ void mtree_info(fprintf_function mon_printf, void *f)
{ {
MemoryRegionListHead ml_head; MemoryRegionListHead ml_head;
MemoryRegionList *ml, *ml2; MemoryRegionList *ml, *ml2;
AddressSpace *as;
QTAILQ_INIT(&ml_head); QTAILQ_INIT(&ml_head);
mon_printf(f, "memory\n"); QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
mtree_print_mr(mon_printf, f, address_space_memory.root, 0, 0, &ml_head); if (!as->name) {
continue;
if (address_space_io.root && }
!QTAILQ_EMPTY(&address_space_io.root->subregions)) { mon_printf(f, "%s\n", as->name);
mon_printf(f, "I/O\n"); mtree_print_mr(mon_printf, f, as->root, 0, 0, &ml_head);
mtree_print_mr(mon_printf, f, address_space_io.root, 0, 0, &ml_head);
} }
mon_printf(f, "aliases\n"); mon_printf(f, "aliases\n");

View File

@ -164,10 +164,12 @@ typedef struct AddressSpace AddressSpace;
*/ */
struct AddressSpace { struct AddressSpace {
/* All fields are private. */ /* All fields are private. */
const char *name;
MemoryRegion *root; MemoryRegion *root;
struct FlatView *current_map; struct FlatView *current_map;
int ioeventfd_nb; int ioeventfd_nb;
struct MemoryRegionIoeventfd *ioeventfds; struct MemoryRegionIoeventfd *ioeventfds;
QTAILQ_ENTRY(AddressSpace) address_spaces_link;
}; };
typedef struct MemoryRegionSection MemoryRegionSection; typedef struct MemoryRegionSection MemoryRegionSection;