//#define DEBUG_UNASSIGNED
-#define RAM_ADDR_INVALID (~(ram_addr_t)0)
-
static unsigned memory_region_transaction_depth;
static bool memory_region_update_pending;
static bool ioeventfd_update_pending;
hwaddr offset_in_region;
AddrRange addr;
uint8_t dirty_log_mask;
+ bool romd_mode;
bool readonly;
};
return a->mr == b->mr
&& addrrange_equal(a->addr, b->addr)
&& a->offset_in_region == b->offset_in_region
+ && a->romd_mode == b->romd_mode
&& a->readonly == b->readonly;
}
r1->addr.size),
int128_make64(r2->offset_in_region))
&& r1->dirty_log_mask == r2->dirty_log_mask
+ && r1->romd_mode == r2->romd_mode
&& r1->readonly == r2->readonly;
}
fr.mr = mr;
fr.dirty_log_mask = memory_region_get_dirty_log_mask(mr);
+ fr.romd_mode = mr->romd_mode;
fr.readonly = readonly;
/* Render the region itself into any gaps left by the current view. */
mr->alias_offset = offset;
}
+void memory_region_init_rom(MemoryRegion *mr,
+ struct Object *owner,
+ const char *name,
+ uint64_t size,
+ Error **errp)
+{
+ memory_region_init(mr, owner, name, size);
+ mr->ram = true;
+ mr->readonly = true;
+ mr->terminates = true;
+ mr->destructor = memory_region_destructor_ram;
+ mr->ram_block = qemu_ram_alloc(size, mr, errp);
+ mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0;
+}
+
void memory_region_init_rom_device(MemoryRegion *mr,
Object *owner,
const MemoryRegionOps *ops,
uint64_t size,
Error **errp)
{
+ assert(ops);
memory_region_init(mr, owner, name, size);
mr->ops = ops;
mr->opaque = opaque;
void memory_region_register_iommu_notifier(MemoryRegion *mr, Notifier *n)
{
+ if (mr->iommu_ops->notify_started &&
+ QLIST_EMPTY(&mr->iommu_notify.notifiers)) {
+ mr->iommu_ops->notify_started(mr);
+ }
notifier_list_add(&mr->iommu_notify, n);
}
-void memory_region_iommu_replay(MemoryRegion *mr, Notifier *n,
- hwaddr granularity, bool is_write)
+uint64_t memory_region_iommu_get_min_page_size(MemoryRegion *mr)
+{
+ assert(memory_region_is_iommu(mr));
+ if (mr->iommu_ops && mr->iommu_ops->get_min_page_size) {
+ return mr->iommu_ops->get_min_page_size(mr);
+ }
+ return TARGET_PAGE_SIZE;
+}
+
+void memory_region_iommu_replay(MemoryRegion *mr, Notifier *n, bool is_write)
{
- hwaddr addr;
+ hwaddr addr, granularity;
IOMMUTLBEntry iotlb;
+ granularity = memory_region_iommu_get_min_page_size(mr);
+
for (addr = 0; addr < memory_region_size(mr); addr += granularity) {
iotlb = mr->iommu_ops->translate(mr, addr, is_write);
if (iotlb.perm != IOMMU_NONE) {
}
}
-void memory_region_unregister_iommu_notifier(Notifier *n)
+void memory_region_unregister_iommu_notifier(MemoryRegion *mr, Notifier *n)
{
notifier_remove(n);
+ if (mr->iommu_ops->notify_stopped &&
+ QLIST_EMPTY(&mr->iommu_notify.notifiers)) {
+ mr->iommu_ops->notify_stopped(mr);
+ }
}
void memory_region_notify_iommu(MemoryRegion *mr,
int memory_region_get_fd(MemoryRegion *mr)
{
- if (mr->alias) {
- return memory_region_get_fd(mr->alias);
+ int fd;
+
+ rcu_read_lock();
+ while (mr->alias) {
+ mr = mr->alias;
}
+ fd = mr->ram_block->fd;
+ rcu_read_unlock();
- assert(mr->ram_block);
+ return fd;
+}
- return qemu_get_ram_fd(memory_region_get_ram_addr(mr));
+void memory_region_set_fd(MemoryRegion *mr, int fd)
+{
+ rcu_read_lock();
+ while (mr->alias) {
+ mr = mr->alias;
+ }
+ mr->ram_block->fd = fd;
+ rcu_read_unlock();
}
void *memory_region_get_ram_ptr(MemoryRegion *mr)
mr = mr->alias;
}
assert(mr->ram_block);
- ptr = qemu_get_ram_ptr(mr->ram_block, memory_region_get_ram_addr(mr));
+ ptr = qemu_map_ram_ptr(mr->ram_block, offset);
rcu_read_unlock();
- return ptr + offset;
+ return ptr;
+}
+
+MemoryRegion *memory_region_from_host(void *ptr, ram_addr_t *offset)
+{
+ RAMBlock *block;
+
+ block = qemu_ram_block_from_host(ptr, false, offset);
+ if (!block) {
+ return NULL;
+ }
+
+ return block->mr;
}
ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr)