xref: /qemu/include/sysemu/dma.h (revision 5c9eb028)
19c17d615SPaolo Bonzini /*
29c17d615SPaolo Bonzini  * DMA helper functions
39c17d615SPaolo Bonzini  *
49c17d615SPaolo Bonzini  * Copyright (c) 2009 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 <stdio.h>
149c17d615SPaolo Bonzini #include "exec/memory.h"
15df32fd1cSPaolo Bonzini #include "exec/address-spaces.h"
169c17d615SPaolo Bonzini #include "hw/hw.h"
179c17d615SPaolo Bonzini #include "block/block.h"
185e5a94b6SBenoît Canet #include "block/accounting.h"
199c17d615SPaolo Bonzini #include "sysemu/kvm.h"
209c17d615SPaolo Bonzini 
219c17d615SPaolo Bonzini typedef struct ScatterGatherEntry ScatterGatherEntry;
229c17d615SPaolo Bonzini 
239c17d615SPaolo Bonzini typedef enum {
249c17d615SPaolo Bonzini     DMA_DIRECTION_TO_DEVICE = 0,
259c17d615SPaolo Bonzini     DMA_DIRECTION_FROM_DEVICE = 1,
269c17d615SPaolo Bonzini } DMADirection;
279c17d615SPaolo Bonzini 
289c17d615SPaolo Bonzini struct QEMUSGList {
299c17d615SPaolo Bonzini     ScatterGatherEntry *sg;
309c17d615SPaolo Bonzini     int nsg;
319c17d615SPaolo Bonzini     int nalloc;
329c17d615SPaolo Bonzini     size_t size;
33f487b677SPaolo Bonzini     DeviceState *dev;
34df32fd1cSPaolo Bonzini     AddressSpace *as;
359c17d615SPaolo Bonzini };
369c17d615SPaolo Bonzini 
379c17d615SPaolo Bonzini #ifndef CONFIG_USER_ONLY
389c17d615SPaolo Bonzini 
399c17d615SPaolo Bonzini /*
409c17d615SPaolo Bonzini  * When an IOMMU is present, bus addresses become distinct from
419c17d615SPaolo Bonzini  * CPU/memory physical addresses and may be a different size.  Because
429c17d615SPaolo Bonzini  * the IOVA size depends more on the bus than on the platform, we more
439c17d615SPaolo Bonzini  * or less have to treat these as 64-bit always to cover all (or at
449c17d615SPaolo Bonzini  * least most) cases.
459c17d615SPaolo Bonzini  */
469c17d615SPaolo Bonzini typedef uint64_t dma_addr_t;
479c17d615SPaolo Bonzini 
489c17d615SPaolo Bonzini #define DMA_ADDR_BITS 64
499c17d615SPaolo Bonzini #define DMA_ADDR_FMT "%" PRIx64
509c17d615SPaolo Bonzini 
51df32fd1cSPaolo Bonzini static inline void dma_barrier(AddressSpace *as, DMADirection dir)
529c17d615SPaolo Bonzini {
539c17d615SPaolo Bonzini     /*
549c17d615SPaolo Bonzini      * This is called before DMA read and write operations
559c17d615SPaolo Bonzini      * unless the _relaxed form is used and is responsible
569c17d615SPaolo Bonzini      * for providing some sane ordering of accesses vs
579c17d615SPaolo Bonzini      * concurrently running VCPUs.
589c17d615SPaolo Bonzini      *
599c17d615SPaolo Bonzini      * Users of map(), unmap() or lower level st/ld_*
609c17d615SPaolo Bonzini      * operations are responsible for providing their own
619c17d615SPaolo Bonzini      * ordering via barriers.
629c17d615SPaolo Bonzini      *
639c17d615SPaolo Bonzini      * This primitive implementation does a simple smp_mb()
649c17d615SPaolo Bonzini      * before each operation which provides pretty much full
659c17d615SPaolo Bonzini      * ordering.
669c17d615SPaolo Bonzini      *
679c17d615SPaolo Bonzini      * A smarter implementation can be devised if needed to
689c17d615SPaolo Bonzini      * use lighter barriers based on the direction of the
699c17d615SPaolo Bonzini      * transfer, the DMA context, etc...
709c17d615SPaolo Bonzini      */
719c17d615SPaolo Bonzini     if (kvm_enabled()) {
729c17d615SPaolo Bonzini         smp_mb();
739c17d615SPaolo Bonzini     }
749c17d615SPaolo Bonzini }
759c17d615SPaolo Bonzini 
769c17d615SPaolo Bonzini /* Checks that the given range of addresses is valid for DMA.  This is
779c17d615SPaolo Bonzini  * useful for certain cases, but usually you should just use
789c17d615SPaolo Bonzini  * dma_memory_{read,write}() and check for errors */
79df32fd1cSPaolo Bonzini static inline bool dma_memory_valid(AddressSpace *as,
809c17d615SPaolo Bonzini                                     dma_addr_t addr, dma_addr_t len,
819c17d615SPaolo Bonzini                                     DMADirection dir)
829c17d615SPaolo Bonzini {
83df32fd1cSPaolo Bonzini     return address_space_access_valid(as, addr, len,
8451644ab7SPaolo Bonzini                                       dir == DMA_DIRECTION_FROM_DEVICE);
859c17d615SPaolo Bonzini }
869c17d615SPaolo Bonzini 
87df32fd1cSPaolo Bonzini static inline int dma_memory_rw_relaxed(AddressSpace *as, dma_addr_t addr,
889c17d615SPaolo Bonzini                                         void *buf, dma_addr_t len,
899c17d615SPaolo Bonzini                                         DMADirection dir)
909c17d615SPaolo Bonzini {
91*5c9eb028SPeter Maydell     return (bool)address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED,
92*5c9eb028SPeter Maydell                                   buf, len, dir == DMA_DIRECTION_FROM_DEVICE);
939c17d615SPaolo Bonzini }
949c17d615SPaolo Bonzini 
95df32fd1cSPaolo Bonzini static inline int dma_memory_read_relaxed(AddressSpace *as, dma_addr_t addr,
969c17d615SPaolo Bonzini                                           void *buf, dma_addr_t len)
979c17d615SPaolo Bonzini {
98df32fd1cSPaolo Bonzini     return dma_memory_rw_relaxed(as, addr, buf, len, DMA_DIRECTION_TO_DEVICE);
999c17d615SPaolo Bonzini }
1009c17d615SPaolo Bonzini 
101df32fd1cSPaolo Bonzini static inline int dma_memory_write_relaxed(AddressSpace *as, dma_addr_t addr,
1029c17d615SPaolo Bonzini                                            const void *buf, dma_addr_t len)
1039c17d615SPaolo Bonzini {
104df32fd1cSPaolo Bonzini     return dma_memory_rw_relaxed(as, addr, (void *)buf, len,
1059c17d615SPaolo Bonzini                                  DMA_DIRECTION_FROM_DEVICE);
1069c17d615SPaolo Bonzini }
1079c17d615SPaolo Bonzini 
108df32fd1cSPaolo Bonzini static inline int dma_memory_rw(AddressSpace *as, dma_addr_t addr,
1099c17d615SPaolo Bonzini                                 void *buf, dma_addr_t len,
1109c17d615SPaolo Bonzini                                 DMADirection dir)
1119c17d615SPaolo Bonzini {
112df32fd1cSPaolo Bonzini     dma_barrier(as, dir);
1139c17d615SPaolo Bonzini 
114df32fd1cSPaolo Bonzini     return dma_memory_rw_relaxed(as, addr, buf, len, dir);
1159c17d615SPaolo Bonzini }
1169c17d615SPaolo Bonzini 
117df32fd1cSPaolo Bonzini static inline int dma_memory_read(AddressSpace *as, dma_addr_t addr,
1189c17d615SPaolo Bonzini                                   void *buf, dma_addr_t len)
1199c17d615SPaolo Bonzini {
120df32fd1cSPaolo Bonzini     return dma_memory_rw(as, addr, buf, len, DMA_DIRECTION_TO_DEVICE);
1219c17d615SPaolo Bonzini }
1229c17d615SPaolo Bonzini 
123df32fd1cSPaolo Bonzini static inline int dma_memory_write(AddressSpace *as, dma_addr_t addr,
1249c17d615SPaolo Bonzini                                    const void *buf, dma_addr_t len)
1259c17d615SPaolo Bonzini {
126df32fd1cSPaolo Bonzini     return dma_memory_rw(as, addr, (void *)buf, len,
1279c17d615SPaolo Bonzini                          DMA_DIRECTION_FROM_DEVICE);
1289c17d615SPaolo Bonzini }
1299c17d615SPaolo Bonzini 
130df32fd1cSPaolo Bonzini int dma_memory_set(AddressSpace *as, dma_addr_t addr, uint8_t c, dma_addr_t len);
1319c17d615SPaolo Bonzini 
132df32fd1cSPaolo Bonzini static inline void *dma_memory_map(AddressSpace *as,
1339c17d615SPaolo Bonzini                                    dma_addr_t addr, dma_addr_t *len,
1349c17d615SPaolo Bonzini                                    DMADirection dir)
1359c17d615SPaolo Bonzini {
1369c17d615SPaolo Bonzini     hwaddr xlen = *len;
1379c17d615SPaolo Bonzini     void *p;
1389c17d615SPaolo Bonzini 
139df32fd1cSPaolo Bonzini     p = address_space_map(as, addr, &xlen, dir == DMA_DIRECTION_FROM_DEVICE);
1409c17d615SPaolo Bonzini     *len = xlen;
1419c17d615SPaolo Bonzini     return p;
1429c17d615SPaolo Bonzini }
1439c17d615SPaolo Bonzini 
144df32fd1cSPaolo Bonzini static inline void dma_memory_unmap(AddressSpace *as,
1459c17d615SPaolo Bonzini                                     void *buffer, dma_addr_t len,
1469c17d615SPaolo Bonzini                                     DMADirection dir, dma_addr_t access_len)
1479c17d615SPaolo Bonzini {
148df32fd1cSPaolo Bonzini     address_space_unmap(as, buffer, (hwaddr)len,
1499c17d615SPaolo Bonzini                         dir == DMA_DIRECTION_FROM_DEVICE, access_len);
1509c17d615SPaolo Bonzini }
1519c17d615SPaolo Bonzini 
1529c17d615SPaolo Bonzini #define DEFINE_LDST_DMA(_lname, _sname, _bits, _end) \
153df32fd1cSPaolo Bonzini     static inline uint##_bits##_t ld##_lname##_##_end##_dma(AddressSpace *as, \
1549c17d615SPaolo Bonzini                                                             dma_addr_t addr) \
1559c17d615SPaolo Bonzini     {                                                                   \
1569c17d615SPaolo Bonzini         uint##_bits##_t val;                                            \
157df32fd1cSPaolo Bonzini         dma_memory_read(as, addr, &val, (_bits) / 8);                   \
1589c17d615SPaolo Bonzini         return _end##_bits##_to_cpu(val);                               \
1599c17d615SPaolo Bonzini     }                                                                   \
160df32fd1cSPaolo Bonzini     static inline void st##_sname##_##_end##_dma(AddressSpace *as,      \
1619c17d615SPaolo Bonzini                                                  dma_addr_t addr,       \
1629c17d615SPaolo Bonzini                                                  uint##_bits##_t val)   \
1639c17d615SPaolo Bonzini     {                                                                   \
1649c17d615SPaolo Bonzini         val = cpu_to_##_end##_bits(val);                                \
165df32fd1cSPaolo Bonzini         dma_memory_write(as, addr, &val, (_bits) / 8);                  \
1669c17d615SPaolo Bonzini     }
1679c17d615SPaolo Bonzini 
168df32fd1cSPaolo Bonzini static inline uint8_t ldub_dma(AddressSpace *as, dma_addr_t addr)
1699c17d615SPaolo Bonzini {
1709c17d615SPaolo Bonzini     uint8_t val;
1719c17d615SPaolo Bonzini 
172df32fd1cSPaolo Bonzini     dma_memory_read(as, addr, &val, 1);
1739c17d615SPaolo Bonzini     return val;
1749c17d615SPaolo Bonzini }
1759c17d615SPaolo Bonzini 
176df32fd1cSPaolo Bonzini static inline void stb_dma(AddressSpace *as, dma_addr_t addr, uint8_t val)
1779c17d615SPaolo Bonzini {
178df32fd1cSPaolo Bonzini     dma_memory_write(as, addr, &val, 1);
1799c17d615SPaolo Bonzini }
1809c17d615SPaolo Bonzini 
1819c17d615SPaolo Bonzini DEFINE_LDST_DMA(uw, w, 16, le);
1829c17d615SPaolo Bonzini DEFINE_LDST_DMA(l, l, 32, le);
1839c17d615SPaolo Bonzini DEFINE_LDST_DMA(q, q, 64, le);
1849c17d615SPaolo Bonzini DEFINE_LDST_DMA(uw, w, 16, be);
1859c17d615SPaolo Bonzini DEFINE_LDST_DMA(l, l, 32, be);
1869c17d615SPaolo Bonzini DEFINE_LDST_DMA(q, q, 64, be);
1879c17d615SPaolo Bonzini 
1889c17d615SPaolo Bonzini #undef DEFINE_LDST_DMA
1899c17d615SPaolo Bonzini 
1909c17d615SPaolo Bonzini struct ScatterGatherEntry {
1919c17d615SPaolo Bonzini     dma_addr_t base;
1929c17d615SPaolo Bonzini     dma_addr_t len;
1939c17d615SPaolo Bonzini };
1949c17d615SPaolo Bonzini 
195f487b677SPaolo Bonzini void qemu_sglist_init(QEMUSGList *qsg, DeviceState *dev, int alloc_hint,
196f487b677SPaolo Bonzini                       AddressSpace *as);
1979c17d615SPaolo Bonzini void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len);
1989c17d615SPaolo Bonzini void qemu_sglist_destroy(QEMUSGList *qsg);
1999c17d615SPaolo Bonzini #endif
2009c17d615SPaolo Bonzini 
2014be74634SMarkus Armbruster typedef BlockAIOCB *DMAIOFunc(BlockBackend *blk, int64_t sector_num,
2029c17d615SPaolo Bonzini                               QEMUIOVector *iov, int nb_sectors,
203097310b5SMarkus Armbruster                               BlockCompletionFunc *cb, void *opaque);
2049c17d615SPaolo Bonzini 
2054be74634SMarkus Armbruster BlockAIOCB *dma_blk_io(BlockBackend *blk,
2069c17d615SPaolo Bonzini                        QEMUSGList *sg, uint64_t sector_num,
207097310b5SMarkus Armbruster                        DMAIOFunc *io_func, BlockCompletionFunc *cb,
2089c17d615SPaolo Bonzini                        void *opaque, DMADirection dir);
2094be74634SMarkus Armbruster BlockAIOCB *dma_blk_read(BlockBackend *blk,
2109c17d615SPaolo Bonzini                          QEMUSGList *sg, uint64_t sector,
211097310b5SMarkus Armbruster                          BlockCompletionFunc *cb, void *opaque);
2124be74634SMarkus Armbruster BlockAIOCB *dma_blk_write(BlockBackend *blk,
2139c17d615SPaolo Bonzini                           QEMUSGList *sg, uint64_t sector,
214097310b5SMarkus Armbruster                           BlockCompletionFunc *cb, void *opaque);
2159c17d615SPaolo Bonzini uint64_t dma_buf_read(uint8_t *ptr, int32_t len, QEMUSGList *sg);
2169c17d615SPaolo Bonzini uint64_t dma_buf_write(uint8_t *ptr, int32_t len, QEMUSGList *sg);
2179c17d615SPaolo Bonzini 
2184be74634SMarkus Armbruster void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie,
2199c17d615SPaolo Bonzini                     QEMUSGList *sg, enum BlockAcctType type);
2209c17d615SPaolo Bonzini 
2219c17d615SPaolo Bonzini #endif
222