On Tue, May 21, 2013 at 12:57:16PM +0200, Paolo Bonzini wrote: > 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.
I don't love the name - "address_space_valid" suggests to me it tests the validity of the whole address space, not a specific range. But an obviously better name doesn't quickly occur to me. Obviously I like the functionality, since I wrote that into the DMAContext stuff specifically to support the spapr_llan driver :). > > Signed-off-by: Paolo Bonzini <pbonz...@redhat.com> > --- > dma-helpers.c | 5 +++++ > exec.c | 25 +++++++++++++++++++++++++ > include/exec/memory.h | 14 ++++++++++++++ > include/sysemu/dma.h | 3 ++- > 4 files changed, 46 insertions(+), 1 deletion(-) > > diff --git a/dma-helpers.c b/dma-helpers.c > index 272632f..2962b69 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_valid(dma->as, paddr, len, > + dir == DMA_DIRECTION_FROM_DEVICE)) { > + return false; > + } > + > len -= plen; > addr += plen; > } > diff --git a/exec.c b/exec.c > index 8d91221..8f1b507 100644 > --- a/exec.c > +++ b/exec.c > @@ -2079,6 +2079,31 @@ static void cpu_notify_map_clients(void) > } > } > > +bool address_space_valid(AddressSpace *as, hwaddr addr, int len, bool > is_write) > +{ > + AddressSpaceDispatch *d = as->dispatch; > + MemoryRegionSection *section; > + int l; > + hwaddr page; > + > + while (len > 0) { > + page = addr & TARGET_PAGE_MASK; > + l = (page + TARGET_PAGE_SIZE) - addr; > + if (l > len) { > + l = len; > + } > + section = phys_page_find(d, addr >> TARGET_PAGE_BITS); > + if (section->mr == &io_mem_unassigned || > + (is_write && section->mr->readonly)) { > + 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 6ed593c..2e5fd11 100644 > --- a/include/exec/memory.h > +++ b/include/exec/memory.h > @@ -860,6 +860,20 @@ void address_space_write(AddressSpace *as, hwaddr addr, > */ > void address_space_read(AddressSpace *as, hwaddr addr, uint8_t *buf, int > len); > > +/* address_space_valid: check for validity of 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_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 a52c93a..2e239dc 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_valid(dma->as, addr, len, > + dir == DMA_DIRECTION_FROM_DEVICE); > } else { > return iommu_dma_memory_valid(dma, addr, len, dir); > } -- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
signature.asc
Description: Digital signature