mirror of https://github.com/xemu-project/xemu.git
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:
parent
9ad2bbc167
commit
0d673e36a7
75
memory.c
75
memory.c
|
@ -28,6 +28,9 @@ static bool global_dirty_log = false;
|
|||
static QTAILQ_HEAD(memory_listeners, MemoryListener) memory_listeners
|
||||
= QTAILQ_HEAD_INITIALIZER(memory_listeners);
|
||||
|
||||
static QTAILQ_HEAD(, AddressSpace) address_spaces
|
||||
= QTAILQ_HEAD_INITIALIZER(address_spaces);
|
||||
|
||||
typedef struct AddrRange AddrRange;
|
||||
|
||||
/*
|
||||
|
@ -449,14 +452,15 @@ static AddressSpace address_space_io;
|
|||
|
||||
static AddressSpace *memory_region_to_address_space(MemoryRegion *mr)
|
||||
{
|
||||
AddressSpace *as;
|
||||
|
||||
while (mr->parent) {
|
||||
mr = mr->parent;
|
||||
}
|
||||
if (mr == address_space_memory.root) {
|
||||
return &address_space_memory;
|
||||
}
|
||||
if (mr == address_space_io.root) {
|
||||
return &address_space_io;
|
||||
QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
|
||||
if (mr == as->root) {
|
||||
return as;
|
||||
}
|
||||
}
|
||||
abort();
|
||||
}
|
||||
|
@ -729,16 +733,15 @@ void memory_region_transaction_begin(void)
|
|||
|
||||
void memory_region_transaction_commit(void)
|
||||
{
|
||||
AddressSpace *as;
|
||||
|
||||
assert(memory_region_transaction_depth);
|
||||
--memory_region_transaction_depth;
|
||||
if (!memory_region_transaction_depth) {
|
||||
MEMORY_LISTENER_CALL_GLOBAL(begin, Forward);
|
||||
|
||||
if (address_space_memory.root) {
|
||||
address_space_update_topology(&address_space_memory);
|
||||
}
|
||||
if (address_space_io.root) {
|
||||
address_space_update_topology(&address_space_io);
|
||||
QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
|
||||
address_space_update_topology(as);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
AddressSpace *as;
|
||||
FlatRange *fr;
|
||||
|
||||
FOR_EACH_FLAT_RANGE(fr, address_space_memory.current_map) {
|
||||
if (fr->mr == mr) {
|
||||
MEMORY_LISTENER_UPDATE_REGION(fr, &address_space_memory,
|
||||
Forward, log_sync);
|
||||
QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
|
||||
FOR_EACH_FLAT_RANGE(fr, as->current_map) {
|
||||
if (fr->mr == mr) {
|
||||
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);
|
||||
}
|
||||
|
||||
static void memory_region_update_coalesced_range(MemoryRegion *mr)
|
||||
static void memory_region_update_coalesced_range_as(MemoryRegion *mr, AddressSpace *as)
|
||||
{
|
||||
FlatRange *fr;
|
||||
CoalescedMemoryRange *cmr;
|
||||
AddrRange tmp;
|
||||
|
||||
FOR_EACH_FLAT_RANGE(fr, address_space_memory.current_map) {
|
||||
FOR_EACH_FLAT_RANGE(fr, as->current_map) {
|
||||
if (fr->mr == mr) {
|
||||
qemu_unregister_coalesced_mmio(int128_get64(fr->addr.start),
|
||||
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)
|
||||
{
|
||||
memory_region_clear_coalescing(mr);
|
||||
|
@ -1450,10 +1464,6 @@ static void listener_add_address_space(MemoryListener *listener,
|
|||
{
|
||||
FlatRange *fr;
|
||||
|
||||
if (!as->root) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (listener->address_space_filter
|
||||
&& listener->address_space_filter != as->root) {
|
||||
return;
|
||||
|
@ -1478,6 +1488,7 @@ static void listener_add_address_space(MemoryListener *listener,
|
|||
void memory_listener_register(MemoryListener *listener, MemoryRegion *filter)
|
||||
{
|
||||
MemoryListener *other = NULL;
|
||||
AddressSpace *as;
|
||||
|
||||
listener->address_space_filter = filter;
|
||||
if (QTAILQ_EMPTY(&memory_listeners)
|
||||
|
@ -1492,8 +1503,10 @@ void memory_listener_register(MemoryListener *listener, MemoryRegion *filter)
|
|||
}
|
||||
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)
|
||||
|
@ -1507,17 +1520,21 @@ void address_space_init(AddressSpace *as, MemoryRegion *root)
|
|||
as->root = root;
|
||||
as->current_map = g_new(FlatView, 1);
|
||||
flatview_init(as->current_map);
|
||||
QTAILQ_INSERT_TAIL(&address_spaces, as, address_spaces_link);
|
||||
as->name = NULL;
|
||||
memory_region_transaction_commit();
|
||||
}
|
||||
|
||||
void set_system_memory_map(MemoryRegion *mr)
|
||||
{
|
||||
address_space_init(&address_space_memory, mr);
|
||||
address_space_memory.name = "memory";
|
||||
}
|
||||
|
||||
void set_system_io_map(MemoryRegion *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)
|
||||
|
@ -1637,16 +1654,16 @@ void mtree_info(fprintf_function mon_printf, void *f)
|
|||
{
|
||||
MemoryRegionListHead ml_head;
|
||||
MemoryRegionList *ml, *ml2;
|
||||
AddressSpace *as;
|
||||
|
||||
QTAILQ_INIT(&ml_head);
|
||||
|
||||
mon_printf(f, "memory\n");
|
||||
mtree_print_mr(mon_printf, f, address_space_memory.root, 0, 0, &ml_head);
|
||||
|
||||
if (address_space_io.root &&
|
||||
!QTAILQ_EMPTY(&address_space_io.root->subregions)) {
|
||||
mon_printf(f, "I/O\n");
|
||||
mtree_print_mr(mon_printf, f, address_space_io.root, 0, 0, &ml_head);
|
||||
QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
|
||||
if (!as->name) {
|
||||
continue;
|
||||
}
|
||||
mon_printf(f, "%s\n", as->name);
|
||||
mtree_print_mr(mon_printf, f, as->root, 0, 0, &ml_head);
|
||||
}
|
||||
|
||||
mon_printf(f, "aliases\n");
|
||||
|
|
2
memory.h
2
memory.h
|
@ -164,10 +164,12 @@ typedef struct AddressSpace AddressSpace;
|
|||
*/
|
||||
struct AddressSpace {
|
||||
/* All fields are private. */
|
||||
const char *name;
|
||||
MemoryRegion *root;
|
||||
struct FlatView *current_map;
|
||||
int ioeventfd_nb;
|
||||
struct MemoryRegionIoeventfd *ioeventfds;
|
||||
QTAILQ_ENTRY(AddressSpace) address_spaces_link;
|
||||
};
|
||||
|
||||
typedef struct MemoryRegionSection MemoryRegionSection;
|
||||
|
|
Loading…
Reference in New Issue