19c17d615SPaolo Bonzini /* 29c17d615SPaolo Bonzini * DMA helper functions 39c17d615SPaolo Bonzini * 49c211ad2SPhilippe Mathieu-Daudé * Copyright (c) 2009, 2020 Red Hat 59c17d615SPaolo Bonzini * 69c17d615SPaolo Bonzini * This work is licensed under the terms of the GNU General Public License 79c17d615SPaolo Bonzini * (GNU GPL), version 2 or later. 89c17d615SPaolo Bonzini */ 99c17d615SPaolo Bonzini 109c17d615SPaolo Bonzini #ifndef DMA_H 119c17d615SPaolo Bonzini #define DMA_H 129c17d615SPaolo Bonzini 139c17d615SPaolo Bonzini #include "exec/memory.h" 14df32fd1cSPaolo Bonzini #include "exec/address-spaces.h" 159c17d615SPaolo Bonzini #include "block/block.h" 165e5a94b6SBenoît Canet #include "block/accounting.h" 179c17d615SPaolo Bonzini 189c17d615SPaolo Bonzini typedef struct ScatterGatherEntry ScatterGatherEntry; 199c17d615SPaolo Bonzini 209c17d615SPaolo Bonzini typedef enum { 219c17d615SPaolo Bonzini DMA_DIRECTION_TO_DEVICE = 0, 229c17d615SPaolo Bonzini DMA_DIRECTION_FROM_DEVICE = 1, 239c17d615SPaolo Bonzini } DMADirection; 249c17d615SPaolo Bonzini 259c17d615SPaolo Bonzini struct QEMUSGList { 269c17d615SPaolo Bonzini ScatterGatherEntry *sg; 279c17d615SPaolo Bonzini int nsg; 289c17d615SPaolo Bonzini int nalloc; 299c17d615SPaolo Bonzini size_t size; 30f487b677SPaolo Bonzini DeviceState *dev; 31df32fd1cSPaolo Bonzini AddressSpace *as; 329c17d615SPaolo Bonzini }; 339c17d615SPaolo Bonzini 349c17d615SPaolo Bonzini #ifndef CONFIG_USER_ONLY 359c17d615SPaolo Bonzini 369c17d615SPaolo Bonzini /* 379c17d615SPaolo Bonzini * When an IOMMU is present, bus addresses become distinct from 389c17d615SPaolo Bonzini * CPU/memory physical addresses and may be a different size. Because 399c17d615SPaolo Bonzini * the IOVA size depends more on the bus than on the platform, we more 409c17d615SPaolo Bonzini * or less have to treat these as 64-bit always to cover all (or at 419c17d615SPaolo Bonzini * least most) cases. 429c17d615SPaolo Bonzini */ 439c17d615SPaolo Bonzini typedef uint64_t dma_addr_t; 449c17d615SPaolo Bonzini 459c17d615SPaolo Bonzini #define DMA_ADDR_BITS 64 469c17d615SPaolo Bonzini #define DMA_ADDR_FMT "%" PRIx64 479c17d615SPaolo Bonzini 48df32fd1cSPaolo Bonzini static inline void dma_barrier(AddressSpace *as, DMADirection dir) 499c17d615SPaolo Bonzini { 509c17d615SPaolo Bonzini /* 519c17d615SPaolo Bonzini * This is called before DMA read and write operations 529c17d615SPaolo Bonzini * unless the _relaxed form is used and is responsible 539c17d615SPaolo Bonzini * for providing some sane ordering of accesses vs 549c17d615SPaolo Bonzini * concurrently running VCPUs. 559c17d615SPaolo Bonzini * 569c17d615SPaolo Bonzini * Users of map(), unmap() or lower level st/ld_* 579c17d615SPaolo Bonzini * operations are responsible for providing their own 589c17d615SPaolo Bonzini * ordering via barriers. 599c17d615SPaolo Bonzini * 609c17d615SPaolo Bonzini * This primitive implementation does a simple smp_mb() 619c17d615SPaolo Bonzini * before each operation which provides pretty much full 629c17d615SPaolo Bonzini * ordering. 639c17d615SPaolo Bonzini * 649c17d615SPaolo Bonzini * A smarter implementation can be devised if needed to 659c17d615SPaolo Bonzini * use lighter barriers based on the direction of the 669c17d615SPaolo Bonzini * transfer, the DMA context, etc... 679c17d615SPaolo Bonzini */ 689c17d615SPaolo Bonzini smp_mb(); 699c17d615SPaolo Bonzini } 709c17d615SPaolo Bonzini 719c17d615SPaolo Bonzini /* Checks that the given range of addresses is valid for DMA. This is 729c17d615SPaolo Bonzini * useful for certain cases, but usually you should just use 739c17d615SPaolo Bonzini * dma_memory_{read,write}() and check for errors */ 74df32fd1cSPaolo Bonzini static inline bool dma_memory_valid(AddressSpace *as, 759c17d615SPaolo Bonzini dma_addr_t addr, dma_addr_t len, 767ccb391cSPhilippe Mathieu-Daudé DMADirection dir, MemTxAttrs attrs) 779c17d615SPaolo Bonzini { 78df32fd1cSPaolo Bonzini return address_space_access_valid(as, addr, len, 79fddffa42SPeter Maydell dir == DMA_DIRECTION_FROM_DEVICE, 807ccb391cSPhilippe Mathieu-Daudé attrs); 819c17d615SPaolo Bonzini } 829c17d615SPaolo Bonzini 839989bcd3SPhilippe Mathieu-Daudé static inline MemTxResult dma_memory_rw_relaxed(AddressSpace *as, 849989bcd3SPhilippe Mathieu-Daudé dma_addr_t addr, 859c17d615SPaolo Bonzini void *buf, dma_addr_t len, 864afd0f2fSPhilippe Mathieu-Daudé DMADirection dir, 874afd0f2fSPhilippe Mathieu-Daudé MemTxAttrs attrs) 889c17d615SPaolo Bonzini { 894afd0f2fSPhilippe Mathieu-Daudé return address_space_rw(as, addr, attrs, 905c9eb028SPeter Maydell buf, len, dir == DMA_DIRECTION_FROM_DEVICE); 919c17d615SPaolo Bonzini } 929c17d615SPaolo Bonzini 93b1f51303SPhilippe Mathieu-Daudé static inline MemTxResult dma_memory_read_relaxed(AddressSpace *as, 94b1f51303SPhilippe Mathieu-Daudé dma_addr_t addr, 959c17d615SPaolo Bonzini void *buf, dma_addr_t len) 969c17d615SPaolo Bonzini { 974afd0f2fSPhilippe Mathieu-Daudé return dma_memory_rw_relaxed(as, addr, buf, len, 984afd0f2fSPhilippe Mathieu-Daudé DMA_DIRECTION_TO_DEVICE, 994afd0f2fSPhilippe Mathieu-Daudé MEMTXATTRS_UNSPECIFIED); 1009c17d615SPaolo Bonzini } 1019c17d615SPaolo Bonzini 10277c71d1dSPhilippe Mathieu-Daudé static inline MemTxResult dma_memory_write_relaxed(AddressSpace *as, 10377c71d1dSPhilippe Mathieu-Daudé dma_addr_t addr, 10477c71d1dSPhilippe Mathieu-Daudé const void *buf, 10577c71d1dSPhilippe Mathieu-Daudé dma_addr_t len) 1069c17d615SPaolo Bonzini { 107df32fd1cSPaolo Bonzini return dma_memory_rw_relaxed(as, addr, (void *)buf, len, 1084afd0f2fSPhilippe Mathieu-Daudé DMA_DIRECTION_FROM_DEVICE, 1094afd0f2fSPhilippe Mathieu-Daudé MEMTXATTRS_UNSPECIFIED); 1109c17d615SPaolo Bonzini } 1119c17d615SPaolo Bonzini 1129989bcd3SPhilippe Mathieu-Daudé /** 1139989bcd3SPhilippe Mathieu-Daudé * dma_memory_rw: Read from or write to an address space from DMA controller. 1149989bcd3SPhilippe Mathieu-Daudé * 1159989bcd3SPhilippe Mathieu-Daudé * Return a MemTxResult indicating whether the operation succeeded 1169989bcd3SPhilippe Mathieu-Daudé * or failed (eg unassigned memory, device rejected the transaction, 1179989bcd3SPhilippe Mathieu-Daudé * IOMMU fault). 1189989bcd3SPhilippe Mathieu-Daudé * 1199989bcd3SPhilippe Mathieu-Daudé * @as: #AddressSpace to be accessed 1209989bcd3SPhilippe Mathieu-Daudé * @addr: address within that address space 1219989bcd3SPhilippe Mathieu-Daudé * @buf: buffer with the data transferred 1229989bcd3SPhilippe Mathieu-Daudé * @len: the number of bytes to read or write 1239989bcd3SPhilippe Mathieu-Daudé * @dir: indicates the transfer direction 12423faf569SPhilippe Mathieu-Daudé * @attrs: memory transaction attributes 1259989bcd3SPhilippe Mathieu-Daudé */ 1269989bcd3SPhilippe Mathieu-Daudé static inline MemTxResult dma_memory_rw(AddressSpace *as, dma_addr_t addr, 1279c17d615SPaolo Bonzini void *buf, dma_addr_t len, 12823faf569SPhilippe Mathieu-Daudé DMADirection dir, MemTxAttrs attrs) 1299c17d615SPaolo Bonzini { 130df32fd1cSPaolo Bonzini dma_barrier(as, dir); 1319c17d615SPaolo Bonzini 13223faf569SPhilippe Mathieu-Daudé return dma_memory_rw_relaxed(as, addr, buf, len, dir, attrs); 1339c17d615SPaolo Bonzini } 1349c17d615SPaolo Bonzini 135b1f51303SPhilippe Mathieu-Daudé /** 136b1f51303SPhilippe Mathieu-Daudé * dma_memory_read: Read from an address space from DMA controller. 137b1f51303SPhilippe Mathieu-Daudé * 138b1f51303SPhilippe Mathieu-Daudé * Return a MemTxResult indicating whether the operation succeeded 139b1f51303SPhilippe Mathieu-Daudé * or failed (eg unassigned memory, device rejected the transaction, 140b1f51303SPhilippe Mathieu-Daudé * IOMMU fault). Called within RCU critical section. 141b1f51303SPhilippe Mathieu-Daudé * 142b1f51303SPhilippe Mathieu-Daudé * @as: #AddressSpace to be accessed 143b1f51303SPhilippe Mathieu-Daudé * @addr: address within that address space 144b1f51303SPhilippe Mathieu-Daudé * @buf: buffer with the data transferred 145b1f51303SPhilippe Mathieu-Daudé * @len: length of the data transferred 146ba06fe8aSPhilippe Mathieu-Daudé * @attrs: memory transaction attributes 147b1f51303SPhilippe Mathieu-Daudé */ 148b1f51303SPhilippe Mathieu-Daudé static inline MemTxResult dma_memory_read(AddressSpace *as, dma_addr_t addr, 149ba06fe8aSPhilippe Mathieu-Daudé void *buf, dma_addr_t len, 150ba06fe8aSPhilippe Mathieu-Daudé MemTxAttrs attrs) 1519c17d615SPaolo Bonzini { 15223faf569SPhilippe Mathieu-Daudé return dma_memory_rw(as, addr, buf, len, 153ba06fe8aSPhilippe Mathieu-Daudé DMA_DIRECTION_TO_DEVICE, attrs); 1549c17d615SPaolo Bonzini } 1559c17d615SPaolo Bonzini 15677c71d1dSPhilippe Mathieu-Daudé /** 15777c71d1dSPhilippe Mathieu-Daudé * address_space_write: Write to address space from DMA controller. 15877c71d1dSPhilippe Mathieu-Daudé * 15977c71d1dSPhilippe Mathieu-Daudé * Return a MemTxResult indicating whether the operation succeeded 16077c71d1dSPhilippe Mathieu-Daudé * or failed (eg unassigned memory, device rejected the transaction, 16177c71d1dSPhilippe Mathieu-Daudé * IOMMU fault). 16277c71d1dSPhilippe Mathieu-Daudé * 16377c71d1dSPhilippe Mathieu-Daudé * @as: #AddressSpace to be accessed 16477c71d1dSPhilippe Mathieu-Daudé * @addr: address within that address space 16577c71d1dSPhilippe Mathieu-Daudé * @buf: buffer with the data transferred 16677c71d1dSPhilippe Mathieu-Daudé * @len: the number of bytes to write 167ba06fe8aSPhilippe Mathieu-Daudé * @attrs: memory transaction attributes 16877c71d1dSPhilippe Mathieu-Daudé */ 16977c71d1dSPhilippe Mathieu-Daudé static inline MemTxResult dma_memory_write(AddressSpace *as, dma_addr_t addr, 170ba06fe8aSPhilippe Mathieu-Daudé const void *buf, dma_addr_t len, 171ba06fe8aSPhilippe Mathieu-Daudé MemTxAttrs attrs) 1729c17d615SPaolo Bonzini { 173df32fd1cSPaolo Bonzini return dma_memory_rw(as, addr, (void *)buf, len, 174ba06fe8aSPhilippe Mathieu-Daudé DMA_DIRECTION_FROM_DEVICE, attrs); 1759c17d615SPaolo Bonzini } 1769c17d615SPaolo Bonzini 177bb755f52SPhilippe Mathieu-Daudé /** 178bb755f52SPhilippe Mathieu-Daudé * dma_memory_set: Fill memory with a constant byte from DMA controller. 179bb755f52SPhilippe Mathieu-Daudé * 180bb755f52SPhilippe Mathieu-Daudé * Return a MemTxResult indicating whether the operation succeeded 181bb755f52SPhilippe Mathieu-Daudé * or failed (eg unassigned memory, device rejected the transaction, 182bb755f52SPhilippe Mathieu-Daudé * IOMMU fault). 183bb755f52SPhilippe Mathieu-Daudé * 184bb755f52SPhilippe Mathieu-Daudé * @as: #AddressSpace to be accessed 185bb755f52SPhilippe Mathieu-Daudé * @addr: address within that address space 186bb755f52SPhilippe Mathieu-Daudé * @c: constant byte to fill the memory 187bb755f52SPhilippe Mathieu-Daudé * @len: the number of bytes to fill with the constant byte 1887a36e42dSPhilippe Mathieu-Daudé * @attrs: memory transaction attributes 189bb755f52SPhilippe Mathieu-Daudé */ 190bb755f52SPhilippe Mathieu-Daudé MemTxResult dma_memory_set(AddressSpace *as, dma_addr_t addr, 1917a36e42dSPhilippe Mathieu-Daudé uint8_t c, dma_addr_t len, MemTxAttrs attrs); 1929c17d615SPaolo Bonzini 1939c211ad2SPhilippe Mathieu-Daudé /** 1949c211ad2SPhilippe Mathieu-Daudé * address_space_map: Map a physical memory region into a host virtual address. 1959c211ad2SPhilippe Mathieu-Daudé * 1969c211ad2SPhilippe Mathieu-Daudé * May map a subset of the requested range, given by and returned in @plen. 1979c211ad2SPhilippe Mathieu-Daudé * May return %NULL and set *@plen to zero(0), if resources needed to perform 1989c211ad2SPhilippe Mathieu-Daudé * the mapping are exhausted. 1999c211ad2SPhilippe Mathieu-Daudé * Use only for reads OR writes - not for read-modify-write operations. 2009c211ad2SPhilippe Mathieu-Daudé * 2019c211ad2SPhilippe Mathieu-Daudé * @as: #AddressSpace to be accessed 2029c211ad2SPhilippe Mathieu-Daudé * @addr: address within that address space 2039c211ad2SPhilippe Mathieu-Daudé * @len: pointer to length of buffer; updated on return 2049c211ad2SPhilippe Mathieu-Daudé * @dir: indicates the transfer direction 205a1d4b0a3SPhilippe Mathieu-Daudé * @attrs: memory attributes 2069c211ad2SPhilippe Mathieu-Daudé */ 207df32fd1cSPaolo Bonzini static inline void *dma_memory_map(AddressSpace *as, 2089c17d615SPaolo Bonzini dma_addr_t addr, dma_addr_t *len, 209a1d4b0a3SPhilippe Mathieu-Daudé DMADirection dir, MemTxAttrs attrs) 2109c17d615SPaolo Bonzini { 2119c17d615SPaolo Bonzini hwaddr xlen = *len; 2129c17d615SPaolo Bonzini void *p; 2139c17d615SPaolo Bonzini 214f26404fbSPeter Maydell p = address_space_map(as, addr, &xlen, dir == DMA_DIRECTION_FROM_DEVICE, 215a1d4b0a3SPhilippe Mathieu-Daudé attrs); 2169c17d615SPaolo Bonzini *len = xlen; 2179c17d615SPaolo Bonzini return p; 2189c17d615SPaolo Bonzini } 2199c17d615SPaolo Bonzini 2209c211ad2SPhilippe Mathieu-Daudé /** 2219c211ad2SPhilippe Mathieu-Daudé * address_space_unmap: Unmaps a memory region previously mapped 2229c211ad2SPhilippe Mathieu-Daudé * by dma_memory_map() 2239c211ad2SPhilippe Mathieu-Daudé * 2249c211ad2SPhilippe Mathieu-Daudé * Will also mark the memory as dirty if @dir == %DMA_DIRECTION_FROM_DEVICE. 2259c211ad2SPhilippe Mathieu-Daudé * @access_len gives the amount of memory that was actually read or written 2269c211ad2SPhilippe Mathieu-Daudé * by the caller. 2279c211ad2SPhilippe Mathieu-Daudé * 2289c211ad2SPhilippe Mathieu-Daudé * @as: #AddressSpace used 2299c211ad2SPhilippe Mathieu-Daudé * @buffer: host pointer as returned by address_space_map() 2309c211ad2SPhilippe Mathieu-Daudé * @len: buffer length as returned by address_space_map() 2319c211ad2SPhilippe Mathieu-Daudé * @dir: indicates the transfer direction 2329c211ad2SPhilippe Mathieu-Daudé * @access_len: amount of data actually transferred 2339c211ad2SPhilippe Mathieu-Daudé */ 234df32fd1cSPaolo Bonzini static inline void dma_memory_unmap(AddressSpace *as, 2359c17d615SPaolo Bonzini void *buffer, dma_addr_t len, 2369c17d615SPaolo Bonzini DMADirection dir, dma_addr_t access_len) 2379c17d615SPaolo Bonzini { 238df32fd1cSPaolo Bonzini address_space_unmap(as, buffer, (hwaddr)len, 2399c17d615SPaolo Bonzini dir == DMA_DIRECTION_FROM_DEVICE, access_len); 2409c17d615SPaolo Bonzini } 2419c17d615SPaolo Bonzini 2429c17d615SPaolo Bonzini #define DEFINE_LDST_DMA(_lname, _sname, _bits, _end) \ 243*cd1db8dfSPhilippe Mathieu-Daudé static inline MemTxResult ld##_lname##_##_end##_dma(AddressSpace *as, \ 24434cdea1dSPhilippe Mathieu-Daudé dma_addr_t addr, \ 245*cd1db8dfSPhilippe Mathieu-Daudé uint##_bits##_t *pval, \ 24634cdea1dSPhilippe Mathieu-Daudé MemTxAttrs attrs) \ 2479c17d615SPaolo Bonzini { \ 248*cd1db8dfSPhilippe Mathieu-Daudé MemTxResult res = dma_memory_read(as, addr, pval, (_bits) / 8, attrs); \ 249*cd1db8dfSPhilippe Mathieu-Daudé _end##_bits##_to_cpus(pval); \ 250*cd1db8dfSPhilippe Mathieu-Daudé return res; \ 2519c17d615SPaolo Bonzini } \ 25224aed6bcSPhilippe Mathieu-Daudé static inline MemTxResult st##_sname##_##_end##_dma(AddressSpace *as, \ 2539c17d615SPaolo Bonzini dma_addr_t addr, \ 2542280c27aSPhilippe Mathieu-Daudé uint##_bits##_t val, \ 2552280c27aSPhilippe Mathieu-Daudé MemTxAttrs attrs) \ 2569c17d615SPaolo Bonzini { \ 2579c17d615SPaolo Bonzini val = cpu_to_##_end##_bits(val); \ 25824aed6bcSPhilippe Mathieu-Daudé return dma_memory_write(as, addr, &val, (_bits) / 8, attrs); \ 2599c17d615SPaolo Bonzini } 2609c17d615SPaolo Bonzini 261*cd1db8dfSPhilippe Mathieu-Daudé static inline MemTxResult ldub_dma(AddressSpace *as, dma_addr_t addr, 262*cd1db8dfSPhilippe Mathieu-Daudé uint8_t *val, MemTxAttrs attrs) 2639c17d615SPaolo Bonzini { 264*cd1db8dfSPhilippe Mathieu-Daudé return dma_memory_read(as, addr, val, 1, attrs); 2659c17d615SPaolo Bonzini } 2669c17d615SPaolo Bonzini 26724aed6bcSPhilippe Mathieu-Daudé static inline MemTxResult stb_dma(AddressSpace *as, dma_addr_t addr, 2682280c27aSPhilippe Mathieu-Daudé uint8_t val, MemTxAttrs attrs) 2699c17d615SPaolo Bonzini { 27024aed6bcSPhilippe Mathieu-Daudé return dma_memory_write(as, addr, &val, 1, attrs); 2719c17d615SPaolo Bonzini } 2729c17d615SPaolo Bonzini 2739c17d615SPaolo Bonzini DEFINE_LDST_DMA(uw, w, 16, le); 2749c17d615SPaolo Bonzini DEFINE_LDST_DMA(l, l, 32, le); 2759c17d615SPaolo Bonzini DEFINE_LDST_DMA(q, q, 64, le); 2769c17d615SPaolo Bonzini DEFINE_LDST_DMA(uw, w, 16, be); 2779c17d615SPaolo Bonzini DEFINE_LDST_DMA(l, l, 32, be); 2789c17d615SPaolo Bonzini DEFINE_LDST_DMA(q, q, 64, be); 2799c17d615SPaolo Bonzini 2809c17d615SPaolo Bonzini #undef DEFINE_LDST_DMA 2819c17d615SPaolo Bonzini 2829c17d615SPaolo Bonzini struct ScatterGatherEntry { 2839c17d615SPaolo Bonzini dma_addr_t base; 2849c17d615SPaolo Bonzini dma_addr_t len; 2859c17d615SPaolo Bonzini }; 2869c17d615SPaolo Bonzini 287f487b677SPaolo Bonzini void qemu_sglist_init(QEMUSGList *qsg, DeviceState *dev, int alloc_hint, 288f487b677SPaolo Bonzini AddressSpace *as); 2899c17d615SPaolo Bonzini void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len); 2909c17d615SPaolo Bonzini void qemu_sglist_destroy(QEMUSGList *qsg); 2919c17d615SPaolo Bonzini #endif 2929c17d615SPaolo Bonzini 2938a8e63ebSPaolo Bonzini typedef BlockAIOCB *DMAIOFunc(int64_t offset, QEMUIOVector *iov, 2948a8e63ebSPaolo Bonzini BlockCompletionFunc *cb, void *cb_opaque, 2958a8e63ebSPaolo Bonzini void *opaque); 2969c17d615SPaolo Bonzini 2978a8e63ebSPaolo Bonzini BlockAIOCB *dma_blk_io(AioContext *ctx, 29899868af3SMark Cave-Ayland QEMUSGList *sg, uint64_t offset, uint32_t align, 2998a8e63ebSPaolo Bonzini DMAIOFunc *io_func, void *io_func_opaque, 3008a8e63ebSPaolo Bonzini BlockCompletionFunc *cb, void *opaque, DMADirection dir); 3014be74634SMarkus Armbruster BlockAIOCB *dma_blk_read(BlockBackend *blk, 30299868af3SMark Cave-Ayland QEMUSGList *sg, uint64_t offset, uint32_t align, 303097310b5SMarkus Armbruster BlockCompletionFunc *cb, void *opaque); 3044be74634SMarkus Armbruster BlockAIOCB *dma_blk_write(BlockBackend *blk, 30599868af3SMark Cave-Ayland QEMUSGList *sg, uint64_t offset, uint32_t align, 306097310b5SMarkus Armbruster BlockCompletionFunc *cb, void *opaque); 3071e5a3f8bSPhilippe Mathieu-Daudé uint64_t dma_buf_read(void *ptr, int32_t len, QEMUSGList *sg, MemTxAttrs attrs); 308392e48afSPhilippe Mathieu-Daudé uint64_t dma_buf_write(void *ptr, int32_t len, QEMUSGList *sg, MemTxAttrs attrs); 3099c17d615SPaolo Bonzini 3104be74634SMarkus Armbruster void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie, 3119c17d615SPaolo Bonzini QEMUSGList *sg, enum BlockAcctType type); 3129c17d615SPaolo Bonzini 313f14fb6c2SEric Auger /** 314f14fb6c2SEric Auger * dma_aligned_pow2_mask: Return the address bit mask of the largest 315f14fb6c2SEric Auger * power of 2 size less or equal than @end - @start + 1, aligned with @start, 316f14fb6c2SEric Auger * and bounded by 1 << @max_addr_bits bits. 317f14fb6c2SEric Auger * 318f14fb6c2SEric Auger * @start: range start address 319f14fb6c2SEric Auger * @end: range end address (greater than @start) 320f14fb6c2SEric Auger * @max_addr_bits: max address bits (<= 64) 321f14fb6c2SEric Auger */ 322f14fb6c2SEric Auger uint64_t dma_aligned_pow2_mask(uint64_t start, uint64_t end, 323f14fb6c2SEric Auger int max_addr_bits); 324f14fb6c2SEric Auger 3259c17d615SPaolo Bonzini #endif 326