]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/x86/iommu/busdma_dmar.c
MFV r262617: ncurses 5.9.
[FreeBSD/FreeBSD.git] / sys / x86 / iommu / busdma_dmar.c
1 /*-
2  * Copyright (c) 2013 The FreeBSD Foundation
3  * All rights reserved.
4  *
5  * This software was developed by Konstantin Belousov <kib@FreeBSD.org>
6  * under sponsorship from the FreeBSD Foundation.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/malloc.h>
36 #include <sys/bus.h>
37 #include <sys/conf.h>
38 #include <sys/interrupt.h>
39 #include <sys/kernel.h>
40 #include <sys/ktr.h>
41 #include <sys/lock.h>
42 #include <sys/proc.h>
43 #include <sys/memdesc.h>
44 #include <sys/mutex.h>
45 #include <sys/sysctl.h>
46 #include <sys/rman.h>
47 #include <sys/taskqueue.h>
48 #include <sys/tree.h>
49 #include <sys/uio.h>
50 #include <dev/pci/pcivar.h>
51 #include <vm/vm.h>
52 #include <vm/vm_extern.h>
53 #include <vm/vm_kern.h>
54 #include <vm/vm_object.h>
55 #include <vm/vm_page.h>
56 #include <vm/vm_map.h>
57 #include <machine/atomic.h>
58 #include <machine/bus.h>
59 #include <machine/md_var.h>
60 #include <machine/specialreg.h>
61 #include <x86/include/busdma_impl.h>
62 #include <x86/iommu/intel_reg.h>
63 #include <x86/iommu/busdma_dmar.h>
64 #include <x86/iommu/intel_dmar.h>
65
66 /*
67  * busdma_dmar.c, the implementation of the busdma(9) interface using
68  * DMAR units from Intel VT-d.
69  */
70
71 static bool
72 dmar_bus_dma_is_dev_disabled(device_t dev)
73 {
74         char str[128], *env;
75         int domain, bus, slot, func;
76
77         domain = pci_get_domain(dev);
78         bus = pci_get_bus(dev);
79         slot = pci_get_slot(dev);
80         func = pci_get_function(dev);
81         snprintf(str, sizeof(str), "hw.busdma.pci%d.%d.%d.%d.bounce",
82             domain, bus, slot, func);
83         env = getenv(str);
84         if (env == NULL)
85                 return (false);
86         freeenv(env);
87         return (true);
88 }
89
90 struct dmar_ctx *
91 dmar_instantiate_ctx(struct dmar_unit *dmar, device_t dev, bool rmrr)
92 {
93         struct dmar_ctx *ctx;
94         bool disabled;
95
96         /*
97          * If the user requested the IOMMU disabled for the device, we
98          * cannot disable the DMAR, due to possibility of other
99          * devices on the same DMAR still requiring translation.
100          * Instead provide the identity mapping for the device
101          * context.
102          */
103         disabled = dmar_bus_dma_is_dev_disabled(dev);
104         ctx = dmar_get_ctx(dmar, dev, disabled, rmrr);
105         if (ctx == NULL)
106                 return (NULL);
107         ctx->ctx_tag.owner = dev;
108         if (disabled) {
109                 /*
110                  * Keep the first reference on context, release the
111                  * later refs.
112                  */
113                 DMAR_LOCK(dmar);
114                 if ((ctx->flags & DMAR_CTX_DISABLED) == 0) {
115                         ctx->flags |= DMAR_CTX_DISABLED;
116                         DMAR_UNLOCK(dmar);
117                 } else {
118                         dmar_free_ctx_locked(dmar, ctx);
119                 }
120                 ctx = NULL;
121         }
122         return (ctx);
123 }
124
125 bus_dma_tag_t
126 dmar_get_dma_tag(device_t dev, device_t child)
127 {
128         struct dmar_unit *dmar;
129         struct dmar_ctx *ctx;
130         bus_dma_tag_t res;
131
132         dmar = dmar_find(child);
133         /* Not in scope of any DMAR ? */
134         if (dmar == NULL)
135                 return (NULL);
136         dmar_quirks_pre_use(dmar);
137         dmar_instantiate_rmrr_ctxs(dmar);
138
139         ctx = dmar_instantiate_ctx(dmar, child, false);
140         res = ctx == NULL ? NULL : (bus_dma_tag_t)&ctx->ctx_tag;
141         return (res);
142 }
143
144 static MALLOC_DEFINE(M_DMAR_DMAMAP, "dmar_dmamap", "Intel DMAR DMA Map");
145
146 static void dmar_bus_schedule_dmamap(struct dmar_unit *unit,
147     struct bus_dmamap_dmar *map);
148
149 static int
150 dmar_bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment,
151     bus_addr_t boundary, bus_addr_t lowaddr, bus_addr_t highaddr,
152     bus_dma_filter_t *filter, void *filterarg, bus_size_t maxsize,
153     int nsegments, bus_size_t maxsegsz, int flags, bus_dma_lock_t *lockfunc,
154     void *lockfuncarg, bus_dma_tag_t *dmat)
155 {
156         struct bus_dma_tag_dmar *newtag, *oldtag;
157         int error;
158
159         *dmat = NULL;
160         error = common_bus_dma_tag_create(parent != NULL ?
161             &((struct bus_dma_tag_dmar *)parent)->common : NULL, alignment,
162             boundary, lowaddr, highaddr, filter, filterarg, maxsize,
163             nsegments, maxsegsz, flags, lockfunc, lockfuncarg,
164             sizeof(struct bus_dma_tag_dmar), (void **)&newtag);
165         if (error != 0)
166                 goto out;
167
168         oldtag = (struct bus_dma_tag_dmar *)parent;
169         newtag->common.impl = &bus_dma_dmar_impl;
170         newtag->ctx = oldtag->ctx;
171         newtag->owner = oldtag->owner;
172
173         *dmat = (bus_dma_tag_t)newtag;
174 out:
175         CTR4(KTR_BUSDMA, "%s returned tag %p tag flags 0x%x error %d",
176             __func__, newtag, (newtag != NULL ? newtag->common.flags : 0),
177             error);
178         return (error);
179 }
180
181 static int
182 dmar_bus_dma_tag_destroy(bus_dma_tag_t dmat1)
183 {
184         struct bus_dma_tag_dmar *dmat, *dmat_copy, *parent;
185         int error;
186
187         error = 0;
188         dmat_copy = dmat = (struct bus_dma_tag_dmar *)dmat1;
189
190         if (dmat != NULL) {
191                 if (dmat->map_count != 0) {
192                         error = EBUSY;
193                         goto out;
194                 }
195                 while (dmat != NULL) {
196                         parent = (struct bus_dma_tag_dmar *)dmat->common.parent;
197                         if (atomic_fetchadd_int(&dmat->common.ref_count, -1) ==
198                             1) {
199                                 if (dmat == &dmat->ctx->ctx_tag)
200                                         dmar_free_ctx(dmat->ctx);
201                                 free(dmat->segments, M_DMAR_DMAMAP);
202                                 free(dmat, M_DEVBUF);
203                                 dmat = parent;
204                         } else
205                                 dmat = NULL;
206                 }
207         }
208 out:
209         CTR3(KTR_BUSDMA, "%s tag %p error %d", __func__, dmat_copy, error);
210         return (error);
211 }
212
213 static int
214 dmar_bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp)
215 {
216         struct bus_dma_tag_dmar *tag;
217         struct bus_dmamap_dmar *map;
218
219         tag = (struct bus_dma_tag_dmar *)dmat;
220         map = malloc(sizeof(*map), M_DMAR_DMAMAP, M_NOWAIT | M_ZERO);
221         if (map == NULL) {
222                 *mapp = NULL;
223                 return (ENOMEM);
224         }
225         if (tag->segments == NULL) {
226                 tag->segments = malloc(sizeof(bus_dma_segment_t) *
227                     tag->common.nsegments, M_DMAR_DMAMAP, M_NOWAIT);
228                 if (tag->segments == NULL) {
229                         free(map, M_DMAR_DMAMAP);
230                         *mapp = NULL;
231                         return (ENOMEM);
232                 }
233         }
234         TAILQ_INIT(&map->map_entries);
235         map->tag = tag;
236         map->locked = true;
237         map->cansleep = false;
238         tag->map_count++;
239         *mapp = (bus_dmamap_t)map;
240         
241         return (0);
242 }
243
244 static int
245 dmar_bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map1)
246 {
247         struct bus_dma_tag_dmar *tag;
248         struct bus_dmamap_dmar *map;
249
250         tag = (struct bus_dma_tag_dmar *)dmat;
251         map = (struct bus_dmamap_dmar *)map1;
252         if (map != NULL) {
253                 DMAR_CTX_LOCK(tag->ctx);
254                 if (!TAILQ_EMPTY(&map->map_entries)) {
255                         DMAR_CTX_UNLOCK(tag->ctx);
256                         return (EBUSY);
257                 }
258                 DMAR_CTX_UNLOCK(tag->ctx);
259                 free(map, M_DMAR_DMAMAP);
260         }
261         tag->map_count--;
262         return (0);
263 }
264
265
266 static int
267 dmar_bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,
268     bus_dmamap_t *mapp)
269 {
270         struct bus_dma_tag_dmar *tag;
271         struct bus_dmamap_dmar *map;
272         int error, mflags;
273         vm_memattr_t attr;
274
275         error = dmar_bus_dmamap_create(dmat, flags, mapp);
276         if (error != 0)
277                 return (error);
278
279         mflags = (flags & BUS_DMA_NOWAIT) != 0 ? M_NOWAIT : M_WAITOK;
280         mflags |= (flags & BUS_DMA_ZERO) != 0 ? M_ZERO : 0;
281         attr = (flags & BUS_DMA_NOCACHE) != 0 ? VM_MEMATTR_UNCACHEABLE :
282             VM_MEMATTR_DEFAULT;
283         
284         tag = (struct bus_dma_tag_dmar *)dmat;
285         map = (struct bus_dmamap_dmar *)*mapp;
286
287         if (tag->common.maxsize < PAGE_SIZE &&
288             tag->common.alignment <= tag->common.maxsize &&
289             attr == VM_MEMATTR_DEFAULT) {
290                 *vaddr = malloc(tag->common.maxsize, M_DEVBUF, mflags);
291                 map->flags |= BUS_DMAMAP_DMAR_MALLOC;
292         } else {
293                 *vaddr = (void *)kmem_alloc_attr(kernel_arena,
294                     tag->common.maxsize, mflags, 0ul, BUS_SPACE_MAXADDR,
295                     attr);
296                 map->flags |= BUS_DMAMAP_DMAR_KMEM_ALLOC;
297         }
298         if (*vaddr == NULL) {
299                 dmar_bus_dmamap_destroy(dmat, *mapp);
300                 *mapp = NULL;
301                 return (ENOMEM);
302         }
303         return (0);
304 }
305
306 static void
307 dmar_bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map1)
308 {
309         struct bus_dma_tag_dmar *tag;
310         struct bus_dmamap_dmar *map;
311
312         tag = (struct bus_dma_tag_dmar *)dmat;
313         map = (struct bus_dmamap_dmar *)map1;
314
315         if ((map->flags & BUS_DMAMAP_DMAR_MALLOC) != 0) {
316                 free(vaddr, M_DEVBUF);
317                 map->flags &= ~BUS_DMAMAP_DMAR_MALLOC;
318         } else {
319                 KASSERT((map->flags & BUS_DMAMAP_DMAR_KMEM_ALLOC) != 0,
320                     ("dmar_bus_dmamem_free for non alloced map %p", map));
321                 kmem_free(kernel_arena, (vm_offset_t)vaddr, tag->common.maxsize);
322                 map->flags &= ~BUS_DMAMAP_DMAR_KMEM_ALLOC;
323         }
324
325         dmar_bus_dmamap_destroy(dmat, map1);
326 }
327
328 static int
329 dmar_bus_dmamap_load_something1(struct bus_dma_tag_dmar *tag,
330     struct bus_dmamap_dmar *map, vm_page_t *ma, int offset, bus_size_t buflen,
331     int flags, bus_dma_segment_t *segs, int *segp,
332     struct dmar_map_entries_tailq *unroll_list)
333 {
334         struct dmar_ctx *ctx;
335         struct dmar_map_entry *entry;
336         dmar_gaddr_t size;
337         bus_size_t buflen1;
338         int error, idx, gas_flags, seg;
339
340         if (segs == NULL)
341                 segs = tag->segments;
342         ctx = tag->ctx;
343         seg = *segp;
344         error = 0;
345         idx = 0;
346         while (buflen > 0) {
347                 seg++;
348                 if (seg >= tag->common.nsegments) {
349                         error = EFBIG;
350                         break;
351                 }
352                 buflen1 = buflen > tag->common.maxsegsz ?
353                     tag->common.maxsegsz : buflen;
354                 buflen -= buflen1;
355                 size = round_page(offset + buflen1);
356
357                 /*
358                  * (Too) optimistically allow split if there are more
359                  * then one segments left.
360                  */
361                 gas_flags = map->cansleep ? DMAR_GM_CANWAIT : 0;
362                 if (seg + 1 < tag->common.nsegments)
363                         gas_flags |= DMAR_GM_CANSPLIT;
364
365                 error = dmar_gas_map(ctx, &tag->common, size,
366                     DMAR_MAP_ENTRY_READ | DMAR_MAP_ENTRY_WRITE,
367                     gas_flags, ma + idx, &entry);
368                 if (error != 0)
369                         break;
370                 if ((gas_flags & DMAR_GM_CANSPLIT) != 0) {
371                         KASSERT(size >= entry->end - entry->start,
372                             ("split increased entry size %jx %jx %jx",
373                             (uintmax_t)size, (uintmax_t)entry->start,
374                             (uintmax_t)entry->end));
375                         size = entry->end - entry->start;
376                         if (buflen1 > size)
377                                 buflen1 = size;
378                 } else {
379                         KASSERT(entry->end - entry->start == size,
380                             ("no split allowed %jx %jx %jx",
381                             (uintmax_t)size, (uintmax_t)entry->start,
382                             (uintmax_t)entry->end));
383                 }
384
385                 KASSERT(((entry->start + offset) & (tag->common.alignment - 1))
386                     == 0,
387                     ("alignment failed: ctx %p start 0x%jx offset %x "
388                     "align 0x%jx", ctx, (uintmax_t)entry->start, offset,
389                     (uintmax_t)tag->common.alignment));
390                 KASSERT(entry->end <= tag->common.lowaddr ||
391                     entry->start >= tag->common.highaddr,
392                     ("entry placement failed: ctx %p start 0x%jx end 0x%jx "
393                     "lowaddr 0x%jx highaddr 0x%jx", ctx,
394                     (uintmax_t)entry->start, (uintmax_t)entry->end,
395                     (uintmax_t)tag->common.lowaddr,
396                     (uintmax_t)tag->common.highaddr));
397                 KASSERT(dmar_test_boundary(entry->start, entry->end -
398                     entry->start, tag->common.boundary),
399                     ("boundary failed: ctx %p start 0x%jx end 0x%jx "
400                     "boundary 0x%jx", ctx, (uintmax_t)entry->start,
401                     (uintmax_t)entry->end, (uintmax_t)tag->common.boundary));
402                 KASSERT(buflen1 <= tag->common.maxsegsz,
403                     ("segment too large: ctx %p start 0x%jx end 0x%jx "
404                     "maxsegsz 0x%jx", ctx, (uintmax_t)entry->start,
405                     (uintmax_t)entry->end, (uintmax_t)tag->common.maxsegsz));
406
407                 DMAR_CTX_LOCK(ctx);
408                 TAILQ_INSERT_TAIL(&map->map_entries, entry, dmamap_link);
409                 entry->flags |= DMAR_MAP_ENTRY_MAP;
410                 DMAR_CTX_UNLOCK(ctx);
411                 TAILQ_INSERT_TAIL(unroll_list, entry, unroll_link);
412
413                 segs[seg].ds_addr = entry->start + offset;
414                 segs[seg].ds_len = buflen1;
415
416                 idx += OFF_TO_IDX(trunc_page(offset + buflen1));
417                 offset += buflen1;
418                 offset &= DMAR_PAGE_MASK;
419         }
420         if (error == 0)
421                 *segp = seg;
422         return (error);
423 }
424
425 static int
426 dmar_bus_dmamap_load_something(struct bus_dma_tag_dmar *tag,
427     struct bus_dmamap_dmar *map, vm_page_t *ma, int offset, bus_size_t buflen,
428     int flags, bus_dma_segment_t *segs, int *segp)
429 {
430         struct dmar_ctx *ctx;
431         struct dmar_map_entry *entry, *entry1;
432         struct dmar_map_entries_tailq unroll_list;
433         int error;
434
435         ctx = tag->ctx;
436         atomic_add_long(&ctx->loads, 1);
437
438         TAILQ_INIT(&unroll_list);
439         error = dmar_bus_dmamap_load_something1(tag, map, ma, offset,
440             buflen, flags, segs, segp, &unroll_list);
441         if (error != 0) {
442                 /*
443                  * The busdma interface does not allow us to report
444                  * partial buffer load, so unfortunately we have to
445                  * revert all work done.
446                  */
447                 DMAR_CTX_LOCK(ctx);
448                 TAILQ_FOREACH_SAFE(entry, &unroll_list, unroll_link,
449                     entry1) {
450                         /*
451                          * No entries other than what we have created
452                          * during the failed run might have been
453                          * inserted there in between, since we own ctx
454                          * pglock.
455                          */
456                         TAILQ_REMOVE(&map->map_entries, entry, dmamap_link);
457                         TAILQ_REMOVE(&unroll_list, entry, unroll_link);
458                         TAILQ_INSERT_TAIL(&ctx->unload_entries, entry,
459                             dmamap_link);
460                 }
461                 DMAR_CTX_UNLOCK(ctx);
462                 taskqueue_enqueue(ctx->dmar->delayed_taskqueue,
463                     &ctx->unload_task);
464         }
465
466         if (error == ENOMEM && (flags & BUS_DMA_NOWAIT) == 0 &&
467             !map->cansleep)
468                 error = EINPROGRESS;
469         if (error == EINPROGRESS)
470                 dmar_bus_schedule_dmamap(ctx->dmar, map);
471         return (error);
472 }
473
474 static int
475 dmar_bus_dmamap_load_ma(bus_dma_tag_t dmat, bus_dmamap_t map1,
476     struct vm_page **ma, bus_size_t tlen, int ma_offs, int flags,
477     bus_dma_segment_t *segs, int *segp)
478 {
479         struct bus_dma_tag_dmar *tag;
480         struct bus_dmamap_dmar *map;
481
482         tag = (struct bus_dma_tag_dmar *)dmat;
483         map = (struct bus_dmamap_dmar *)map1;
484         return (dmar_bus_dmamap_load_something(tag, map, ma, ma_offs, tlen,
485             flags, segs, segp));
486 }
487
488 static int
489 dmar_bus_dmamap_load_phys(bus_dma_tag_t dmat, bus_dmamap_t map1,
490     vm_paddr_t buf, bus_size_t buflen, int flags, bus_dma_segment_t *segs,
491     int *segp)
492 {
493         struct bus_dma_tag_dmar *tag;
494         struct bus_dmamap_dmar *map;
495         vm_page_t *ma;
496         vm_paddr_t pstart, pend;
497         int error, i, ma_cnt, offset;
498
499         tag = (struct bus_dma_tag_dmar *)dmat;
500         map = (struct bus_dmamap_dmar *)map1;
501         pstart = trunc_page(buf);
502         pend = round_page(buf + buflen);
503         offset = buf & PAGE_MASK;
504         ma_cnt = OFF_TO_IDX(pend - pstart);
505         ma = malloc(sizeof(vm_page_t) * ma_cnt, M_DEVBUF, map->cansleep ?
506             M_WAITOK : M_NOWAIT);
507         if (ma == NULL)
508                 return (ENOMEM);
509         for (i = 0; i < ma_cnt; i++)
510                 ma[i] = PHYS_TO_VM_PAGE(pstart + i * PAGE_SIZE);
511         error = dmar_bus_dmamap_load_something(tag, map, ma, offset, buflen,
512             flags, segs, segp);
513         free(ma, M_DEVBUF);
514         return (error);
515 }
516
517 static int
518 dmar_bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dmamap_t map1, void *buf,
519     bus_size_t buflen, pmap_t pmap, int flags, bus_dma_segment_t *segs,
520     int *segp)
521 {
522         struct bus_dma_tag_dmar *tag;
523         struct bus_dmamap_dmar *map;
524         vm_page_t *ma, fma;
525         vm_paddr_t pstart, pend, paddr;
526         int error, i, ma_cnt, offset;
527
528         tag = (struct bus_dma_tag_dmar *)dmat;
529         map = (struct bus_dmamap_dmar *)map1;
530         pstart = trunc_page((vm_offset_t)buf);
531         pend = round_page((vm_offset_t)buf + buflen);
532         offset = (vm_offset_t)buf & PAGE_MASK;
533         ma_cnt = OFF_TO_IDX(pend - pstart);
534         ma = malloc(sizeof(vm_page_t) * ma_cnt, M_DEVBUF, map->cansleep ?
535             M_WAITOK : M_NOWAIT);
536         if (ma == NULL)
537                 return (ENOMEM);
538         if (dumping) {
539                 /*
540                  * If dumping, do not attempt to call
541                  * PHYS_TO_VM_PAGE() at all.  It may return non-NULL
542                  * but the vm_page returned might be not initialized,
543                  * e.g. for the kernel itself.
544                  */
545                 KASSERT(pmap == kernel_pmap, ("non-kernel address write"));
546                 fma = malloc(sizeof(struct vm_page) * ma_cnt, M_DEVBUF,
547                     M_ZERO | (map->cansleep ? M_WAITOK : M_NOWAIT));
548                 if (fma == NULL) {
549                         free(ma, M_DEVBUF);
550                         return (ENOMEM);
551                 }
552                 for (i = 0; i < ma_cnt; i++, pstart += PAGE_SIZE) {
553                         paddr = pmap_kextract(pstart);
554                         vm_page_initfake(&fma[i], paddr, VM_MEMATTR_DEFAULT);
555                         ma[i] = &fma[i];
556                 }
557         } else {
558                 fma = NULL;
559                 for (i = 0; i < ma_cnt; i++, pstart += PAGE_SIZE) {
560                         if (pmap == kernel_pmap)
561                                 paddr = pmap_kextract(pstart);
562                         else
563                                 paddr = pmap_extract(pmap, pstart);
564                         ma[i] = PHYS_TO_VM_PAGE(paddr);
565                         KASSERT(VM_PAGE_TO_PHYS(ma[i]) == paddr,
566                             ("PHYS_TO_VM_PAGE failed %jx %jx m %p",
567                             (uintmax_t)paddr, (uintmax_t)VM_PAGE_TO_PHYS(ma[i]),
568                             ma[i]));
569                 }
570         }
571         error = dmar_bus_dmamap_load_something(tag, map, ma, offset, buflen,
572             flags, segs, segp);
573         free(ma, M_DEVBUF);
574         free(fma, M_DEVBUF);
575         return (error);
576 }
577
578 static void
579 dmar_bus_dmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map1,
580     struct memdesc *mem, bus_dmamap_callback_t *callback, void *callback_arg)
581 {
582         struct bus_dmamap_dmar *map;
583
584         if (map1 == NULL)
585                 return;
586         map = (struct bus_dmamap_dmar *)map1;
587         map->mem = *mem;
588         map->tag = (struct bus_dma_tag_dmar *)dmat;
589         map->callback = callback;
590         map->callback_arg = callback_arg;
591 }
592
593 static bus_dma_segment_t *
594 dmar_bus_dmamap_complete(bus_dma_tag_t dmat, bus_dmamap_t map1,
595     bus_dma_segment_t *segs, int nsegs, int error)
596 {
597         struct bus_dma_tag_dmar *tag;
598         struct bus_dmamap_dmar *map;
599
600         tag = (struct bus_dma_tag_dmar *)dmat;
601         map = (struct bus_dmamap_dmar *)map1;
602
603         if (!map->locked) {
604                 KASSERT(map->cansleep,
605                     ("map not locked and not sleepable context %p", map));
606
607                 /*
608                  * We are called from the delayed context.  Relock the
609                  * driver.
610                  */
611                 (tag->common.lockfunc)(tag->common.lockfuncarg, BUS_DMA_LOCK);
612                 map->locked = true;
613         }
614
615         if (segs == NULL)
616                 segs = tag->segments;
617         return (segs);
618 }
619
620 /*
621  * The limitations of busdma KPI forces the dmar to perform the actual
622  * unload, consisting of the unmapping of the map entries page tables,
623  * from the delayed context on i386, since page table page mapping
624  * might require a sleep to be successfull.  The unfortunate
625  * consequence is that the DMA requests can be served some time after
626  * the bus_dmamap_unload() call returned.
627  *
628  * On amd64, we assume that sf allocation cannot fail.
629  */
630 static void
631 dmar_bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map1)
632 {
633         struct bus_dma_tag_dmar *tag;
634         struct bus_dmamap_dmar *map;
635         struct dmar_ctx *ctx;
636 #if defined(__amd64__)
637         struct dmar_map_entries_tailq entries;
638 #endif
639
640         tag = (struct bus_dma_tag_dmar *)dmat;
641         map = (struct bus_dmamap_dmar *)map1;
642         ctx = tag->ctx;
643         atomic_add_long(&ctx->unloads, 1);
644
645 #if defined(__i386__)
646         DMAR_CTX_LOCK(ctx);
647         TAILQ_CONCAT(&ctx->unload_entries, &map->map_entries, dmamap_link);
648         DMAR_CTX_UNLOCK(ctx);
649         taskqueue_enqueue(ctx->dmar->delayed_taskqueue, &ctx->unload_task);
650 #else /* defined(__amd64__) */
651         TAILQ_INIT(&entries);
652         DMAR_CTX_LOCK(ctx);
653         TAILQ_CONCAT(&entries, &map->map_entries, dmamap_link);
654         DMAR_CTX_UNLOCK(ctx);
655         THREAD_NO_SLEEPING();
656         dmar_ctx_unload(ctx, &entries, false);
657         THREAD_SLEEPING_OK();
658         KASSERT(TAILQ_EMPTY(&entries), ("lazy dmar_ctx_unload %p", ctx));
659 #endif
660 }
661
662 static void
663 dmar_bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map,
664     bus_dmasync_op_t op)
665 {
666 }
667
668 struct bus_dma_impl bus_dma_dmar_impl = {
669         .tag_create = dmar_bus_dma_tag_create,
670         .tag_destroy = dmar_bus_dma_tag_destroy,
671         .map_create = dmar_bus_dmamap_create,
672         .map_destroy = dmar_bus_dmamap_destroy,
673         .mem_alloc = dmar_bus_dmamem_alloc,
674         .mem_free = dmar_bus_dmamem_free,
675         .load_phys = dmar_bus_dmamap_load_phys,
676         .load_buffer = dmar_bus_dmamap_load_buffer,
677         .load_ma = dmar_bus_dmamap_load_ma,
678         .map_waitok = dmar_bus_dmamap_waitok,
679         .map_complete = dmar_bus_dmamap_complete,
680         .map_unload = dmar_bus_dmamap_unload,
681         .map_sync = dmar_bus_dmamap_sync
682 };
683
684 static void
685 dmar_bus_task_dmamap(void *arg, int pending)
686 {
687         struct bus_dma_tag_dmar *tag;
688         struct bus_dmamap_dmar *map;
689         struct dmar_unit *unit;
690         struct dmar_ctx *ctx;
691
692         unit = arg;
693         DMAR_LOCK(unit);
694         while ((map = TAILQ_FIRST(&unit->delayed_maps)) != NULL) {
695                 TAILQ_REMOVE(&unit->delayed_maps, map, delay_link);
696                 DMAR_UNLOCK(unit);
697                 tag = map->tag;
698                 ctx = map->tag->ctx;
699                 map->cansleep = true;
700                 map->locked = false;
701                 bus_dmamap_load_mem((bus_dma_tag_t)tag, (bus_dmamap_t)map,
702                     &map->mem, map->callback, map->callback_arg,
703                     BUS_DMA_WAITOK);
704                 map->cansleep = false;
705                 if (map->locked) {
706                         (tag->common.lockfunc)(tag->common.lockfuncarg,
707                             BUS_DMA_UNLOCK);
708                 } else
709                         map->locked = true;
710                 map->cansleep = false;
711                 DMAR_LOCK(unit);
712         }
713         DMAR_UNLOCK(unit);
714 }
715
716 static void
717 dmar_bus_schedule_dmamap(struct dmar_unit *unit, struct bus_dmamap_dmar *map)
718 {
719         struct dmar_ctx *ctx;
720
721         ctx = map->tag->ctx;
722         map->locked = false;
723         DMAR_LOCK(unit);
724         TAILQ_INSERT_TAIL(&unit->delayed_maps, map, delay_link);
725         DMAR_UNLOCK(unit);
726         taskqueue_enqueue(unit->delayed_taskqueue, &unit->dmamap_load_task);
727 }
728
729 int
730 dmar_init_busdma(struct dmar_unit *unit)
731 {
732
733         TAILQ_INIT(&unit->delayed_maps);
734         TASK_INIT(&unit->dmamap_load_task, 0, dmar_bus_task_dmamap, unit);
735         unit->delayed_taskqueue = taskqueue_create("dmar", M_WAITOK,
736             taskqueue_thread_enqueue, &unit->delayed_taskqueue);
737         taskqueue_start_threads(&unit->delayed_taskqueue, 1, PI_DISK,
738             "dmar%d busdma taskq", unit->unit);
739         return (0);
740 }
741
742 void
743 dmar_fini_busdma(struct dmar_unit *unit)
744 {
745
746         if (unit->delayed_taskqueue == NULL)
747                 return;
748
749         taskqueue_drain(unit->delayed_taskqueue, &unit->dmamap_load_task);
750         taskqueue_free(unit->delayed_taskqueue);
751         unit->delayed_taskqueue = NULL;
752 }