diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2013-04-11 15:40:59 +0200 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2013-05-29 16:27:16 +0200 |
commit | 51644ab70ba125cb9545702d64890743d75b444b (patch) | |
tree | 420c1b45d6556c81b04d532ca4a05202c069e341 | |
parent | c353e4cc08a2fce7c505dd0d04512ef3947adff8 (diff) |
memory: add address_space_access_valid
The old-style IOMMU lets you check whether an access is valid in a
given DMAContext. There is no equivalent for AddressSpace in the
memory API, implement it with a lookup of the dispatch tree.
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r-- | dma-helpers.c | 5 | ||||
-rw-r--r-- | exec.c | 21 | ||||
-rw-r--r-- | include/exec/memory.h | 15 | ||||
-rw-r--r-- | include/sysemu/dma.h | 3 |
4 files changed, 43 insertions, 1 deletions
diff --git a/dma-helpers.c b/dma-helpers.c index 272632f367..2e298b6ebb 100644 --- a/dma-helpers.c +++ b/dma-helpers.c @@ -298,6 +298,11 @@ bool iommu_dma_memory_valid(DMAContext *dma, dma_addr_t addr, dma_addr_t len, plen = len; } + if (!address_space_access_valid(dma->as, paddr, len, + dir == DMA_DIRECTION_FROM_DEVICE)) { + return false; + } + len -= plen; addr += plen; } @@ -2067,6 +2067,27 @@ static void cpu_notify_map_clients(void) } } +bool address_space_access_valid(AddressSpace *as, hwaddr addr, int len, bool is_write) +{ + MemoryRegionSection *section; + hwaddr l, xlat; + + while (len > 0) { + l = len; + section = address_space_translate(as, addr, &xlat, &l, is_write); + if (!memory_access_is_direct(section->mr, is_write)) { + l = memory_access_size(l, addr); + if (!memory_region_access_valid(section->mr, xlat, l, is_write)) { + return false; + } + } + + len -= l; + addr += l; + } + return true; +} + /* Map a physical memory region into a host virtual address. * May map a subset of the requested range, given by and returned in *plen. * May return NULL if resources needed to perform the mapping are exhausted. diff --git a/include/exec/memory.h b/include/exec/memory.h index 688d3f0e96..81e0e416a4 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -866,6 +866,21 @@ MemoryRegionSection *address_space_translate(AddressSpace *as, hwaddr addr, hwaddr *xlat, hwaddr *len, bool is_write); +/* address_space_access_valid: check for validity of accessing an address + * space range + * + * Check whether memory is assigned to the given address space range. + * + * For now, addr and len should be aligned to a page size. This limitation + * will be lifted in the future. + * + * @as: #AddressSpace to be accessed + * @addr: address within that address space + * @len: length of the area to be checked + * @is_write: indicates the transfer direction + */ +bool address_space_access_valid(AddressSpace *as, hwaddr addr, int len, bool is_write); + /* address_space_map: map a physical memory region into a host virtual address * * May map a subset of the requested range, given by and returned in @plen. diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h index a52c93a553..02e0dcdfeb 100644 --- a/include/sysemu/dma.h +++ b/include/sysemu/dma.h @@ -113,7 +113,8 @@ static inline bool dma_memory_valid(DMAContext *dma, DMADirection dir) { if (!dma_has_iommu(dma)) { - return true; + return address_space_access_valid(dma->as, addr, len, + dir == DMA_DIRECTION_FROM_DEVICE); } else { return iommu_dma_memory_valid(dma, addr, len, dir); } |