unsigned access_size;
unsigned i;
MemTxResult r = MEMTX_OK;
+ bool reentrancy_guard_applied = false;
if (!access_size_min) {
access_size_min = 1;
access_size_max = 4;
}
+ /* Do not allow more than one simultaneous access to a device's IO Regions */
+ if (mr->dev && !mr->disable_reentrancy_guard &&
+ !mr->ram_device && !mr->ram && !mr->rom_device && !mr->readonly) {
+ if (mr->dev->mem_reentrancy_guard.engaged_in_io) {
+ warn_report_once("Blocked re-entrant IO on MemoryRegion: "
+ "%s at addr: 0x%" HWADDR_PRIX,
+ memory_region_name(mr), addr);
+ return MEMTX_ACCESS_ERROR;
+ }
+ mr->dev->mem_reentrancy_guard.engaged_in_io = true;
+ reentrancy_guard_applied = true;
+ }
+
/* FIXME: support unaligned access? */
access_size = MAX(MIN(size, access_size_max), access_size_min);
access_mask = MAKE_64BIT_MASK(0, access_size * 8);
access_mask, attrs);
}
}
+ if (mr->dev && reentrancy_guard_applied) {
+ mr->dev->mem_reentrancy_guard.engaged_in_io = false;
+ }
return r;
}
}
mr->name = g_strdup(name);
mr->owner = owner;
+ mr->dev = (DeviceState *) object_dynamic_cast(mr->owner, TYPE_DEVICE);
mr->ram_block = NULL;
if (name) {
unsigned size)
{
#ifdef DEBUG_UNASSIGNED
- printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
+ printf("Unassigned mem read " HWADDR_FMT_plx "\n", addr);
#endif
return 0;
}
uint64_t val, unsigned size)
{
#ifdef DEBUG_UNASSIGNED
- printf("Unassigned mem write " TARGET_FMT_plx " = 0x%"PRIx64"\n", addr, val);
+ printf("Unassigned mem write " HWADDR_FMT_plx " = 0x%"PRIx64"\n", addr, val);
#endif
}
uint64_t align,
uint32_t ram_flags,
const char *path,
- bool readonly,
+ ram_addr_t offset,
Error **errp)
{
Error *err = NULL;
memory_region_init(mr, owner, name, size);
mr->ram = true;
- mr->readonly = readonly;
+ mr->readonly = !!(ram_flags & RAM_READONLY);
mr->terminates = true;
mr->destructor = memory_region_destructor_ram;
mr->align = align;
mr->ram_block = qemu_ram_alloc_from_file(size, mr, ram_flags, path,
- readonly, &err);
+ offset, &err);
if (err) {
mr->size = int128_zero();
object_unparent(OBJECT(mr));
Error *err = NULL;
memory_region_init(mr, owner, name, size);
mr->ram = true;
+ mr->readonly = !!(ram_flags & RAM_READONLY);
mr->terminates = true;
mr->destructor = memory_region_destructor_ram;
mr->ram_block = qemu_ram_alloc_from_fd(size, mr, ram_flags, fd, offset,
- false, &err);
+ &err);
if (err) {
mr->size = int128_zero();
object_unparent(OBJECT(mr));
}
}
+void memory_region_unmap_iommu_notifier_range(IOMMUNotifier *notifier)
+{
+ IOMMUTLBEvent event;
+
+ event.type = IOMMU_NOTIFIER_UNMAP;
+ event.entry.target_as = &address_space_memory;
+ event.entry.iova = notifier->start;
+ event.entry.perm = IOMMU_NONE;
+ event.entry.addr_mask = notifier->end - notifier->start;
+
+ memory_region_notify_iommu_one(notifier, &event);
+}
+
void memory_region_notify_iommu(IOMMUMemoryRegion *iommu_mr,
int iommu_idx,
IOMMUTLBEvent event)
* If memory region `mr' is NULL, do global sync. Otherwise, sync
* dirty bitmap for the specified memory region.
*/
-static void memory_region_sync_dirty_bitmap(MemoryRegion *mr)
+static void memory_region_sync_dirty_bitmap(MemoryRegion *mr, bool last_stage)
{
MemoryListener *listener;
AddressSpace *as;
* is to do a global sync, because we are not capable to
* sync in a finer granularity.
*/
- listener->log_sync_global(listener);
+ listener->log_sync_global(listener, last_stage);
trace_memory_region_sync_dirty(mr ? mr->name : "(all)", listener->name, 1);
}
}
{
DirtyBitmapSnapshot *snapshot;
assert(mr->ram_block);
- memory_region_sync_dirty_bitmap(mr);
+ memory_region_sync_dirty_bitmap(mr, false);
snapshot = cpu_physical_memory_snapshot_and_clear_dirty(mr, addr, size, client);
memory_global_after_dirty_log_sync();
return snapshot;
int memory_region_get_fd(MemoryRegion *mr)
{
- int fd;
-
RCU_READ_LOCK_GUARD();
while (mr->alias) {
mr = mr->alias;
}
- fd = mr->ram_block->fd;
-
- return fd;
+ return mr->ram_block->fd;
}
void *memory_region_get_ram_ptr(MemoryRegion *mr)
{
- void *ptr;
uint64_t offset = 0;
RCU_READ_LOCK_GUARD();
mr = mr->alias;
}
assert(mr->ram_block);
- ptr = qemu_map_ram_ptr(mr->ram_block, offset);
-
- return ptr;
+ return qemu_map_ram_ptr(mr->ram_block, offset);
}
MemoryRegion *memory_region_from_host(void *ptr, ram_addr_t *offset)
return mr && mr != container;
}
-void memory_global_dirty_log_sync(void)
+void memory_global_dirty_log_sync(bool last_stage)
{
- memory_region_sync_dirty_bitmap(NULL);
+ memory_region_sync_dirty_bitmap(NULL, last_stage);
}
void memory_global_after_dirty_log_sync(void)
for (i = 0; i < level; i++) {
qemu_printf(MTREE_INDENT);
}
- qemu_printf(TARGET_FMT_plx "-" TARGET_FMT_plx
- " (prio %d, %s%s): alias %s @%s " TARGET_FMT_plx
- "-" TARGET_FMT_plx "%s",
+ qemu_printf(HWADDR_FMT_plx "-" HWADDR_FMT_plx
+ " (prio %d, %s%s): alias %s @%s " HWADDR_FMT_plx
+ "-" HWADDR_FMT_plx "%s",
cur_start, cur_end,
mr->priority,
mr->nonvolatile ? "nv-" : "",
for (i = 0; i < level; i++) {
qemu_printf(MTREE_INDENT);
}
- qemu_printf(TARGET_FMT_plx "-" TARGET_FMT_plx
+ qemu_printf(HWADDR_FMT_plx "-" HWADDR_FMT_plx
" (prio %d, %s%s): %s%s",
cur_start, cur_end,
mr->priority,
while (n--) {
mr = range->mr;
if (range->offset_in_region) {
- qemu_printf(MTREE_INDENT TARGET_FMT_plx "-" TARGET_FMT_plx
- " (prio %d, %s%s): %s @" TARGET_FMT_plx,
+ qemu_printf(MTREE_INDENT HWADDR_FMT_plx "-" HWADDR_FMT_plx
+ " (prio %d, %s%s): %s @" HWADDR_FMT_plx,
int128_get64(range->addr.start),
int128_get64(range->addr.start)
+ MR_SIZE(range->addr.size),
memory_region_name(mr),
range->offset_in_region);
} else {
- qemu_printf(MTREE_INDENT TARGET_FMT_plx "-" TARGET_FMT_plx
+ qemu_printf(MTREE_INDENT HWADDR_FMT_plx "-" HWADDR_FMT_plx
" (prio %d, %s%s): %s",
int128_get64(range->addr.start),
int128_get64(range->addr.start)