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>
This commit is contained in:
Avi Kivity 2012-10-30 13:47:46 +02:00 committed by Paolo Bonzini
parent 052e87b073
commit 3095115744
3 changed files with 111 additions and 6 deletions

35
exec.c
View file

@ -266,14 +266,45 @@ MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr,
hwaddr *xlat, hwaddr *plen,
bool is_write)
{
return address_space_translate_internal(as, addr, xlat, plen, true)->mr;
IOMMUTLBEntry iotlb;
MemoryRegionSection *section;
MemoryRegion *mr;
hwaddr len = *plen;
for (;;) {
section = address_space_translate_internal(as, addr, &addr, plen, true);
mr = section->mr;
if (!mr->iommu_ops) {
break;
}
iotlb = mr->iommu_ops->translate(mr, addr);
addr = ((iotlb.translated_addr & ~iotlb.addr_mask)
| (addr & iotlb.addr_mask));
len = MIN(len, (addr | iotlb.addr_mask) - addr + 1);
if (!(iotlb.perm & (1 << is_write))) {
mr = &io_mem_unassigned;
break;
}
as = iotlb.target_as;
}
*plen = len;
*xlat = addr;
return mr;
}
MemoryRegionSection *
address_space_translate_for_iotlb(AddressSpace *as, hwaddr addr, hwaddr *xlat,
hwaddr *plen)
{
return address_space_translate_internal(as, addr, xlat, plen, false);
MemoryRegionSection *section;
section = address_space_translate_internal(as, addr, xlat, plen, false);
assert(!section->mr->iommu_ops);
return section;
}
#endif