diff options
author | Avi Kivity <avi.kivity@gmail.com> | 2012-10-30 13:47:46 +0200 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2013-06-20 16:32:47 +0200 |
commit | 30951157441aed950ad8ca326500b4986d431c7a (patch) | |
tree | a5b3ba2434175eb5e87b533d4791038d33ac73a0 /memory.c | |
parent | 052e87b073cb70afcd767d32f45af2794a5a65de (diff) |
memory: iommu support
Add a new memory region type that translates addresses it is given,
then forwards them to a target address space. This is similar to
an alias, except that the mapping is more flexible than a linear
translation and trucation, and also less efficient since the
translation happens at runtime.
The implementation uses an AddressSpace mapping the target region to
avoid hierarchical dispatch all the way to the resolved region; only
iommu regions are looked up dynamically.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Avi Kivity <avi.kivity@gmail.com>
[Modified to put translation in address_space_translate; assume
IOMMUs are not reachable from TCG. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'memory.c')
-rw-r--r-- | memory.c | 16 |
1 files changed, 16 insertions, 0 deletions
@@ -824,6 +824,7 @@ void memory_region_init(MemoryRegion *mr, { mr->ops = &unassigned_mem_ops; mr->opaque = NULL; + mr->iommu_ops = NULL; mr->parent = NULL; mr->size = int128_make64(size); if (size == UINT64_MAX) { @@ -1063,6 +1064,16 @@ void memory_region_init_rom_device(MemoryRegion *mr, mr->ram_addr = qemu_ram_alloc(size, mr); } +void memory_region_init_iommu(MemoryRegion *mr, + const MemoryRegionIOMMUOps *ops, + const char *name, + uint64_t size) +{ + memory_region_init(mr, name, size); + mr->iommu_ops = ops, + mr->terminates = true; /* then re-forwards */ +} + void memory_region_init_reservation(MemoryRegion *mr, const char *name, uint64_t size) @@ -1108,6 +1119,11 @@ bool memory_region_is_rom(MemoryRegion *mr) return mr->ram && mr->readonly; } +bool memory_region_is_iommu(MemoryRegion *mr) +{ + return mr->iommu_ops; +} + void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client) { uint8_t mask = 1 << client; |