#include "exec-obsolete.h"
unsigned memory_region_transaction_depth = 0;
-static bool memory_region_update_pending = false;
static bool global_dirty_log = false;
static QTAILQ_HEAD(memory_listeners, MemoryListener) memory_listeners
AddrRange addr;
bool match_data;
uint64_t data;
- int fd;
+ EventNotifier *e;
};
static bool memory_region_ioeventfd_before(MemoryRegionIoeventfd a,
return false;
}
}
- if (a.fd < b.fd) {
+ if (a.e < b.e) {
return true;
- } else if (a.fd > b.fd) {
+ } else if (a.e > b.e) {
return false;
}
return false;
MemoryRegion *mr = opaque;
uint64_t tmp;
+ if (mr->flush_coalesced_mmio) {
+ qemu_flush_coalesced_mmio_buffer();
+ }
tmp = mr->ops->read(mr->opaque, addr, size);
*value |= (tmp & mask) << shift;
}
MemoryRegion *mr = opaque;
uint64_t tmp;
+ if (mr->flush_coalesced_mmio) {
+ qemu_flush_coalesced_mmio_buffer();
+ }
tmp = (*value >> shift) & mask;
mr->ops->write(mr->opaque, addr, tmp, size);
}
unsigned width,
uint64_t *data)
{
- MemoryRegion *mr = container_of(iorange, MemoryRegion, iorange);
+ MemoryRegionIORange *mrio
+ = container_of(iorange, MemoryRegionIORange, iorange);
+ MemoryRegion *mr = mrio->mr;
+ offset += mrio->offset;
if (mr->ops->old_portio) {
- const MemoryRegionPortio *mrp = find_portio(mr, offset, width, false);
+ const MemoryRegionPortio *mrp = find_portio(mr, offset - mrio->offset,
+ width, false);
*data = ((uint64_t)1 << (width * 8)) - 1;
if (mrp) {
*data = mrp->read(mr->opaque, offset);
} else if (width == 2) {
- mrp = find_portio(mr, offset, 1, false);
+ mrp = find_portio(mr, offset - mrio->offset, 1, false);
assert(mrp);
*data = mrp->read(mr->opaque, offset) |
(mrp->read(mr->opaque, offset + 1) << 8);
unsigned width,
uint64_t data)
{
- MemoryRegion *mr = container_of(iorange, MemoryRegion, iorange);
+ MemoryRegionIORange *mrio
+ = container_of(iorange, MemoryRegionIORange, iorange);
+ MemoryRegion *mr = mrio->mr;
+ offset += mrio->offset;
if (mr->ops->old_portio) {
- const MemoryRegionPortio *mrp = find_portio(mr, offset, width, true);
+ const MemoryRegionPortio *mrp = find_portio(mr, offset - mrio->offset,
+ width, true);
if (mrp) {
mrp->write(mr->opaque, offset, data);
} else if (width == 2) {
- mrp = find_portio(mr, offset, 1, false);
+ mrp = find_portio(mr, offset - mrio->offset, 1, true);
assert(mrp);
mrp->write(mr->opaque, offset, data & 0xff);
mrp->write(mr->opaque, offset + 1, data >> 8);
memory_region_write_accessor, mr);
}
+static void memory_region_iorange_destructor(IORange *iorange)
+{
+ g_free(container_of(iorange, MemoryRegionIORange, iorange));
+}
+
const IORangeOps memory_region_iorange_ops = {
.read = memory_region_iorange_read,
.write = memory_region_iorange_write,
+ .destructor = memory_region_iorange_destructor,
};
static AddressSpace address_space_io;
.size = int128_get64(fd->addr.size),
};
MEMORY_LISTENER_CALL(eventfd_del, Forward, §ion,
- fd->match_data, fd->data, fd->fd);
+ fd->match_data, fd->data, fd->e);
++iold;
} else if (inew < fds_new_nb
&& (iold == fds_old_nb
.size = int128_get64(fd->addr.size),
};
MEMORY_LISTENER_CALL(eventfd_add, Reverse, §ion,
- fd->match_data, fd->data, fd->fd);
+ fd->match_data, fd->data, fd->e);
++inew;
} else {
++iold;
address_space_update_ioeventfds(as);
}
-static void memory_region_update_topology(MemoryRegion *mr)
-{
- if (memory_region_transaction_depth) {
- memory_region_update_pending |= !mr || mr->enabled;
- return;
- }
-
- if (mr && !mr->enabled) {
- return;
- }
-
- 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);
- }
-
- MEMORY_LISTENER_CALL_GLOBAL(commit, Forward);
-
- memory_region_update_pending = false;
-}
-
void memory_region_transaction_begin(void)
{
+ qemu_flush_coalesced_mmio_buffer();
++memory_region_transaction_depth;
}
{
assert(memory_region_transaction_depth);
--memory_region_transaction_depth;
- if (!memory_region_transaction_depth && memory_region_update_pending) {
- memory_region_update_topology(NULL);
+ 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);
+ }
+
+ MEMORY_LISTENER_CALL_GLOBAL(commit, Forward);
}
}
static void memory_region_destructor_iomem(MemoryRegion *mr)
{
- cpu_unregister_io_memory(mr->ram_addr);
}
static void memory_region_destructor_rom_device(MemoryRegion *mr)
{
qemu_ram_free(mr->ram_addr & TARGET_PAGE_MASK);
- cpu_unregister_io_memory(mr->ram_addr & ~TARGET_PAGE_MASK);
}
static bool memory_region_wrong_endianness(MemoryRegion *mr)
mr->dirty_log_mask = 0;
mr->ioeventfd_nb = 0;
mr->ioeventfds = NULL;
+ mr->flush_coalesced_mmio = false;
}
static bool memory_region_access_valid(MemoryRegion *mr,
mr->opaque = opaque;
mr->terminates = true;
mr->destructor = memory_region_destructor_iomem;
- mr->ram_addr = cpu_register_io_memory(mr);
+ mr->ram_addr = ~(ram_addr_t)0;
}
void memory_region_init_ram(MemoryRegion *mr,
mr->rom_device = true;
mr->destructor = memory_region_destructor_rom_device;
mr->ram_addr = qemu_ram_alloc(size, mr);
- mr->ram_addr |= cpu_register_io_memory(mr);
}
static uint64_t invalid_read(void *opaque, target_phys_addr_t addr,
{
uint8_t mask = 1 << client;
+ memory_region_transaction_begin();
mr->dirty_log_mask = (mr->dirty_log_mask & ~mask) | (log * mask);
- memory_region_update_topology(mr);
+ memory_region_transaction_commit();
}
bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
void memory_region_set_readonly(MemoryRegion *mr, bool readonly)
{
if (mr->readonly != readonly) {
+ memory_region_transaction_begin();
mr->readonly = readonly;
- memory_region_update_topology(mr);
+ memory_region_transaction_commit();
}
}
void memory_region_rom_device_set_readable(MemoryRegion *mr, bool readable)
{
if (mr->readable != readable) {
+ memory_region_transaction_begin();
mr->readable = readable;
- memory_region_update_topology(mr);
+ memory_region_transaction_commit();
}
}
cmr->addr = addrrange_make(int128_make64(offset), int128_make64(size));
QTAILQ_INSERT_TAIL(&mr->coalesced, cmr, link);
memory_region_update_coalesced_range(mr);
+ memory_region_set_flush_coalesced(mr);
}
void memory_region_clear_coalescing(MemoryRegion *mr)
{
CoalescedMemoryRange *cmr;
+ qemu_flush_coalesced_mmio_buffer();
+ mr->flush_coalesced_mmio = false;
+
while (!QTAILQ_EMPTY(&mr->coalesced)) {
cmr = QTAILQ_FIRST(&mr->coalesced);
QTAILQ_REMOVE(&mr->coalesced, cmr, link);
memory_region_update_coalesced_range(mr);
}
+void memory_region_set_flush_coalesced(MemoryRegion *mr)
+{
+ mr->flush_coalesced_mmio = true;
+}
+
+void memory_region_clear_flush_coalesced(MemoryRegion *mr)
+{
+ qemu_flush_coalesced_mmio_buffer();
+ if (QTAILQ_EMPTY(&mr->coalesced)) {
+ mr->flush_coalesced_mmio = false;
+ }
+}
+
void memory_region_add_eventfd(MemoryRegion *mr,
target_phys_addr_t addr,
unsigned size,
bool match_data,
uint64_t data,
- int fd)
+ EventNotifier *e)
{
MemoryRegionIoeventfd mrfd = {
.addr.start = int128_make64(addr),
.addr.size = int128_make64(size),
.match_data = match_data,
.data = data,
- .fd = fd,
+ .e = e,
};
unsigned i;
+ memory_region_transaction_begin();
for (i = 0; i < mr->ioeventfd_nb; ++i) {
if (memory_region_ioeventfd_before(mrfd, mr->ioeventfds[i])) {
break;
memmove(&mr->ioeventfds[i+1], &mr->ioeventfds[i],
sizeof(*mr->ioeventfds) * (mr->ioeventfd_nb-1 - i));
mr->ioeventfds[i] = mrfd;
- memory_region_update_topology(mr);
+ memory_region_transaction_commit();
}
void memory_region_del_eventfd(MemoryRegion *mr,
unsigned size,
bool match_data,
uint64_t data,
- int fd)
+ EventNotifier *e)
{
MemoryRegionIoeventfd mrfd = {
.addr.start = int128_make64(addr),
.addr.size = int128_make64(size),
.match_data = match_data,
.data = data,
- .fd = fd,
+ .e = e,
};
unsigned i;
+ memory_region_transaction_begin();
for (i = 0; i < mr->ioeventfd_nb; ++i) {
if (memory_region_ioeventfd_equal(mrfd, mr->ioeventfds[i])) {
break;
--mr->ioeventfd_nb;
mr->ioeventfds = g_realloc(mr->ioeventfds,
sizeof(*mr->ioeventfds)*mr->ioeventfd_nb + 1);
- memory_region_update_topology(mr);
+ memory_region_transaction_commit();
}
static void memory_region_add_subregion_common(MemoryRegion *mr,
{
MemoryRegion *other;
+ memory_region_transaction_begin();
+
assert(!subregion->parent);
subregion->parent = mr;
subregion->addr = offset;
}
QTAILQ_INSERT_TAIL(&mr->subregions, subregion, subregions_link);
done:
- memory_region_update_topology(mr);
+ memory_region_transaction_commit();
}
void memory_region_del_subregion(MemoryRegion *mr,
MemoryRegion *subregion)
{
+ memory_region_transaction_begin();
assert(subregion->parent == mr);
subregion->parent = NULL;
QTAILQ_REMOVE(&mr->subregions, subregion, subregions_link);
- memory_region_update_topology(mr);
+ memory_region_transaction_commit();
}
void memory_region_set_enabled(MemoryRegion *mr, bool enabled)
if (enabled == mr->enabled) {
return;
}
+ memory_region_transaction_begin();
mr->enabled = enabled;
- memory_region_update_topology(NULL);
+ memory_region_transaction_commit();
}
void memory_region_set_address(MemoryRegion *mr, target_phys_addr_t addr)
void memory_region_set_alias_offset(MemoryRegion *mr, target_phys_addr_t offset)
{
- target_phys_addr_t old_offset = mr->alias_offset;
-
assert(mr->alias);
- mr->alias_offset = offset;
- if (offset == old_offset || !mr->parent) {
+ if (offset == mr->alias_offset) {
return;
}
- memory_region_update_topology(mr);
+ memory_region_transaction_begin();
+ mr->alias_offset = offset;
+ memory_region_transaction_commit();
}
ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr)
{
FlatRange *fr;
+ if (listener->address_space_filter
+ && listener->address_space_filter != as->root) {
+ return;
+ }
+
if (global_dirty_log) {
listener->log_global_start(listener);
}
void set_system_memory_map(MemoryRegion *mr)
{
+ memory_region_transaction_begin();
address_space_memory.root = mr;
- memory_region_update_topology(NULL);
+ memory_region_transaction_commit();
}
void set_system_io_map(MemoryRegion *mr)
{
+ memory_region_transaction_begin();
address_space_io.root = mr;
- memory_region_update_topology(NULL);
+ memory_region_transaction_commit();
}
-uint64_t io_mem_read(int io_index, target_phys_addr_t addr, unsigned size)
+uint64_t io_mem_read(MemoryRegion *mr, target_phys_addr_t addr, unsigned size)
{
- return memory_region_dispatch_read(io_mem_region[io_index], addr, size);
+ return memory_region_dispatch_read(mr, addr, size);
}
-void io_mem_write(int io_index, target_phys_addr_t addr,
+void io_mem_write(MemoryRegion *mr, target_phys_addr_t addr,
uint64_t val, unsigned size)
{
- memory_region_dispatch_write(io_mem_region[io_index], addr, val, size);
+ memory_region_dispatch_write(mr, addr, val, size);
}
typedef struct MemoryRegionList MemoryRegionList;
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);
+ }
+
+ mon_printf(f, "aliases\n");
/* print aliased regions */
QTAILQ_FOREACH(ml, &ml_head, queue) {
if (!ml->printed) {
QTAILQ_FOREACH_SAFE(ml, &ml_head, queue, ml2) {
g_free(ml);
}
-
- if (address_space_io.root &&
- !QTAILQ_EMPTY(&address_space_io.root->subregions)) {
- QTAILQ_INIT(&ml_head);
- mon_printf(f, "I/O\n");
- mtree_print_mr(mon_printf, f, address_space_io.root, 0, 0, &ml_head);
- }
}