sync with latest
[sdk/emulator/qemu.git] / dma.h
1 /*
2  * DMA helper functions
3  *
4  * Copyright (c) 2009 Red Hat
5  *
6  * This work is licensed under the terms of the GNU General Public License
7  * (GNU GPL), version 2 or later.
8  */
9
10 #ifndef DMA_H
11 #define DMA_H
12
13 #include <stdio.h>
14 #include "hw/hw.h"
15 #include "block.h"
16 #include "kvm.h"
17
18 typedef struct DMAContext DMAContext;
19 typedef struct ScatterGatherEntry ScatterGatherEntry;
20
21 typedef enum {
22     DMA_DIRECTION_TO_DEVICE = 0,
23     DMA_DIRECTION_FROM_DEVICE = 1,
24 } DMADirection;
25
26 struct QEMUSGList {
27     ScatterGatherEntry *sg;
28     int nsg;
29     int nalloc;
30     size_t size;
31     DMAContext *dma;
32 };
33
34 #if defined(TARGET_PHYS_ADDR_BITS)
35
36 /*
37  * When an IOMMU is present, bus addresses become distinct from
38  * CPU/memory physical addresses and may be a different size.  Because
39  * the IOVA size depends more on the bus than on the platform, we more
40  * or less have to treat these as 64-bit always to cover all (or at
41  * least most) cases.
42  */
43 typedef uint64_t dma_addr_t;
44
45 #define DMA_ADDR_BITS 64
46 #define DMA_ADDR_FMT "%" PRIx64
47
48 typedef int DMATranslateFunc(DMAContext *dma,
49                              dma_addr_t addr,
50                              target_phys_addr_t *paddr,
51                              target_phys_addr_t *len,
52                              DMADirection dir);
53 typedef void* DMAMapFunc(DMAContext *dma,
54                          dma_addr_t addr,
55                          dma_addr_t *len,
56                          DMADirection dir);
57 typedef void DMAUnmapFunc(DMAContext *dma,
58                           void *buffer,
59                           dma_addr_t len,
60                           DMADirection dir,
61                           dma_addr_t access_len);
62
63 struct DMAContext {
64     DMATranslateFunc *translate;
65     DMAMapFunc *map;
66     DMAUnmapFunc *unmap;
67 };
68
69 static inline void dma_barrier(DMAContext *dma, DMADirection dir)
70 {
71     /*
72      * This is called before DMA read and write operations
73      * unless the _relaxed form is used and is responsible
74      * for providing some sane ordering of accesses vs
75      * concurrently running VCPUs.
76      *
77      * Users of map(), unmap() or lower level st/ld_*
78      * operations are responsible for providing their own
79      * ordering via barriers.
80      *
81      * This primitive implementation does a simple smp_mb()
82      * before each operation which provides pretty much full
83      * ordering.
84      *
85      * A smarter implementation can be devised if needed to
86      * use lighter barriers based on the direction of the
87      * transfer, the DMA context, etc...
88      */
89     if (kvm_enabled()) {
90         smp_mb();
91     }
92 }
93
94 static inline bool dma_has_iommu(DMAContext *dma)
95 {
96     return !!dma;
97 }
98
99 /* Checks that the given range of addresses is valid for DMA.  This is
100  * useful for certain cases, but usually you should just use
101  * dma_memory_{read,write}() and check for errors */
102 bool iommu_dma_memory_valid(DMAContext *dma, dma_addr_t addr, dma_addr_t len,
103                             DMADirection dir);
104 static inline bool dma_memory_valid(DMAContext *dma,
105                                     dma_addr_t addr, dma_addr_t len,
106                                     DMADirection dir)
107 {
108     if (!dma_has_iommu(dma)) {
109         return true;
110     } else {
111         return iommu_dma_memory_valid(dma, addr, len, dir);
112     }
113 }
114
115 int iommu_dma_memory_rw(DMAContext *dma, dma_addr_t addr,
116                         void *buf, dma_addr_t len, DMADirection dir);
117 static inline int dma_memory_rw_relaxed(DMAContext *dma, dma_addr_t addr,
118                                         void *buf, dma_addr_t len,
119                                         DMADirection dir)
120 {
121     if (!dma_has_iommu(dma)) {
122         /* Fast-path for no IOMMU */
123         cpu_physical_memory_rw(addr, buf, len,
124                                dir == DMA_DIRECTION_FROM_DEVICE);
125         return 0;
126     } else {
127         return iommu_dma_memory_rw(dma, addr, buf, len, dir);
128     }
129 }
130
131 static inline int dma_memory_read_relaxed(DMAContext *dma, dma_addr_t addr,
132                                           void *buf, dma_addr_t len)
133 {
134     return dma_memory_rw_relaxed(dma, addr, buf, len, DMA_DIRECTION_TO_DEVICE);
135 }
136
137 static inline int dma_memory_write_relaxed(DMAContext *dma, dma_addr_t addr,
138                                            const void *buf, dma_addr_t len)
139 {
140     return dma_memory_rw_relaxed(dma, addr, (void *)buf, len,
141                                  DMA_DIRECTION_FROM_DEVICE);
142 }
143
144 static inline int dma_memory_rw(DMAContext *dma, dma_addr_t addr,
145                                 void *buf, dma_addr_t len,
146                                 DMADirection dir)
147 {
148     dma_barrier(dma, dir);
149
150     return dma_memory_rw_relaxed(dma, addr, buf, len, dir);
151 }
152
153 static inline int dma_memory_read(DMAContext *dma, dma_addr_t addr,
154                                   void *buf, dma_addr_t len)
155 {
156     return dma_memory_rw(dma, addr, buf, len, DMA_DIRECTION_TO_DEVICE);
157 }
158
159 static inline int dma_memory_write(DMAContext *dma, dma_addr_t addr,
160                                    const void *buf, dma_addr_t len)
161 {
162     return dma_memory_rw(dma, addr, (void *)buf, len,
163                          DMA_DIRECTION_FROM_DEVICE);
164 }
165
166 int iommu_dma_memory_set(DMAContext *dma, dma_addr_t addr, uint8_t c,
167                          dma_addr_t len);
168
169 int dma_memory_set(DMAContext *dma, dma_addr_t addr, uint8_t c, dma_addr_t len);
170
171 void *iommu_dma_memory_map(DMAContext *dma,
172                            dma_addr_t addr, dma_addr_t *len,
173                            DMADirection dir);
174 static inline void *dma_memory_map(DMAContext *dma,
175                                    dma_addr_t addr, dma_addr_t *len,
176                                    DMADirection dir)
177 {
178     if (!dma_has_iommu(dma)) {
179         target_phys_addr_t xlen = *len;
180         void *p;
181
182         p = cpu_physical_memory_map(addr, &xlen,
183                                     dir == DMA_DIRECTION_FROM_DEVICE);
184         *len = xlen;
185         return p;
186     } else {
187         return iommu_dma_memory_map(dma, addr, len, dir);
188     }
189 }
190
191 void iommu_dma_memory_unmap(DMAContext *dma,
192                             void *buffer, dma_addr_t len,
193                             DMADirection dir, dma_addr_t access_len);
194 static inline void dma_memory_unmap(DMAContext *dma,
195                                     void *buffer, dma_addr_t len,
196                                     DMADirection dir, dma_addr_t access_len)
197 {
198     if (!dma_has_iommu(dma)) {
199         cpu_physical_memory_unmap(buffer, (target_phys_addr_t)len,
200                                   dir == DMA_DIRECTION_FROM_DEVICE,
201                                   access_len);
202     } else {
203         iommu_dma_memory_unmap(dma, buffer, len, dir, access_len);
204     }
205 }
206
207 #define DEFINE_LDST_DMA(_lname, _sname, _bits, _end) \
208     static inline uint##_bits##_t ld##_lname##_##_end##_dma(DMAContext *dma, \
209                                                             dma_addr_t addr) \
210     {                                                                   \
211         uint##_bits##_t val;                                            \
212         dma_memory_read(dma, addr, &val, (_bits) / 8);                  \
213         return _end##_bits##_to_cpu(val);                               \
214     }                                                                   \
215     static inline void st##_sname##_##_end##_dma(DMAContext *dma,       \
216                                                  dma_addr_t addr,       \
217                                                  uint##_bits##_t val)   \
218     {                                                                   \
219         val = cpu_to_##_end##_bits(val);                                \
220         dma_memory_write(dma, addr, &val, (_bits) / 8);                 \
221     }
222
223 static inline uint8_t ldub_dma(DMAContext *dma, dma_addr_t addr)
224 {
225     uint8_t val;
226
227     dma_memory_read(dma, addr, &val, 1);
228     return val;
229 }
230
231 static inline void stb_dma(DMAContext *dma, dma_addr_t addr, uint8_t val)
232 {
233     dma_memory_write(dma, addr, &val, 1);
234 }
235
236 DEFINE_LDST_DMA(uw, w, 16, le);
237 DEFINE_LDST_DMA(l, l, 32, le);
238 DEFINE_LDST_DMA(q, q, 64, le);
239 DEFINE_LDST_DMA(uw, w, 16, be);
240 DEFINE_LDST_DMA(l, l, 32, be);
241 DEFINE_LDST_DMA(q, q, 64, be);
242
243 #undef DEFINE_LDST_DMA
244
245 void dma_context_init(DMAContext *dma, DMATranslateFunc translate,
246                       DMAMapFunc map, DMAUnmapFunc unmap);
247
248 struct ScatterGatherEntry {
249     dma_addr_t base;
250     dma_addr_t len;
251 };
252
253 void qemu_sglist_init(QEMUSGList *qsg, int alloc_hint, DMAContext *dma);
254 void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len);
255 void qemu_sglist_destroy(QEMUSGList *qsg);
256 #endif
257
258 typedef BlockDriverAIOCB *DMAIOFunc(BlockDriverState *bs, int64_t sector_num,
259                                  QEMUIOVector *iov, int nb_sectors,
260                                  BlockDriverCompletionFunc *cb, void *opaque);
261
262 BlockDriverAIOCB *dma_bdrv_io(BlockDriverState *bs,
263                               QEMUSGList *sg, uint64_t sector_num,
264                               DMAIOFunc *io_func, BlockDriverCompletionFunc *cb,
265                               void *opaque, DMADirection dir);
266 BlockDriverAIOCB *dma_bdrv_read(BlockDriverState *bs,
267                                 QEMUSGList *sg, uint64_t sector,
268                                 BlockDriverCompletionFunc *cb, void *opaque);
269 BlockDriverAIOCB *dma_bdrv_write(BlockDriverState *bs,
270                                  QEMUSGList *sg, uint64_t sector,
271                                  BlockDriverCompletionFunc *cb, void *opaque);
272 uint64_t dma_buf_read(uint8_t *ptr, int32_t len, QEMUSGList *sg);
273 uint64_t dma_buf_write(uint8_t *ptr, int32_t len, QEMUSGList *sg);
274
275 void dma_acct_start(BlockDriverState *bs, BlockAcctCookie *cookie,
276                     QEMUSGList *sg, enum BlockAcctType type);
277
278 #endif