The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/sparc64/sparc64/iommu.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 1999, 2000 Matthew R. Green
    3  * Copyright (c) 2001-2003 Thomas Moestl
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  * 3. The name of the author may not be used to endorse or promote products
   15  *    derived from this software without specific prior written permission.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   22  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
   24  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   25  * 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  * Copyright (c) 1998 The NetBSD Foundation, Inc.
   31  * All rights reserved.
   32  *
   33  * This code is derived from software contributed to The NetBSD Foundation
   34  * by Paul Kranenburg.
   35  *
   36  * Redistribution and use in source and binary forms, with or without
   37  * modification, are permitted provided that the following conditions
   38  * are met:
   39  * 1. Redistributions of source code must retain the above copyright
   40  *    notice, this list of conditions and the following disclaimer.
   41  * 2. Redistributions in binary form must reproduce the above copyright
   42  *    notice, this list of conditions and the following disclaimer in the
   43  *    documentation and/or other materials provided with the distribution.
   44  * 3. All advertising materials mentioning features or use of this software
   45  *    must display the following acknowledgement:
   46  *        This product includes software developed by the NetBSD
   47  *        Foundation, Inc. and its contributors.
   48  * 4. Neither the name of The NetBSD Foundation nor the names of its
   49  *    contributors may be used to endorse or promote products derived
   50  *    from this software without specific prior written permission.
   51  *
   52  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   53  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   54  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   55  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   56  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   57  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   58  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   59  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   60  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   61  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   62  * POSSIBILITY OF SUCH DAMAGE.
   63  */
   64 /*-
   65  * Copyright (c) 1992, 1993
   66  *      The Regents of the University of California.  All rights reserved.
   67  *
   68  * This software was developed by the Computer Systems Engineering group
   69  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
   70  * contributed to Berkeley.
   71  *
   72  * Redistribution and use in source and binary forms, with or without
   73  * modification, are permitted provided that the following conditions
   74  * are met:
   75  * 1. Redistributions of source code must retain the above copyright
   76  *    notice, this list of conditions and the following disclaimer.
   77  * 2. Redistributions in binary form must reproduce the above copyright
   78  *    notice, this list of conditions and the following disclaimer in the
   79  *    documentation and/or other materials provided with the distribution.
   80  * 4. Neither the name of the University nor the names of its contributors
   81  *    may be used to endorse or promote products derived from this software
   82  *    without specific prior written permission.
   83  *
   84  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   85  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   86  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   87  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   88  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   89  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   90  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   91  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   92  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   93  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   94  * SUCH DAMAGE.
   95  *
   96  *      from: NetBSD: sbus.c,v 1.13 1999/05/23 07:24:02 mrg Exp
   97  *      from: @(#)sbus.c        8.1 (Berkeley) 6/11/93
   98  *      from: NetBSD: iommu.c,v 1.42 2001/08/06 22:02:58 eeh Exp
   99  */
  100 
  101 #include <sys/cdefs.h>
  102 __FBSDID("$FreeBSD$");
  103 
  104 /*
  105  * UltraSPARC IOMMU support; used by both the PCI and SBus code.
  106  *
  107  * TODO:
  108  * - Support sub-page boundaries.
  109  * - Fix alignment handling for small allocations (the possible page offset
  110  *   of malloc()ed memory is not handled at all). Revise interaction of
  111  *   alignment with the load_mbuf and load_uio functions.
  112  * - Handle lowaddr and highaddr in some way, and try to work out a way
  113  *   for filter callbacks to work. Currently, only lowaddr is honored
  114  *   in that no addresses above it are considered at all.
  115  * - Implement BUS_DMA_ALLOCNOW in bus_dma_tag_create as far as possible.
  116  * - Check the possible return values and callback error arguments;
  117  *   the callback currently gets called in error conditions where it should
  118  *   not be.
  119  * - When running out of DVMA space, return EINPROGRESS in the non-
  120  *   BUS_DMA_NOWAIT case and delay the callback until sufficient space
  121  *   becomes available.
  122  * - Use the streaming cache unless BUS_DMA_COHERENT is specified; do not
  123  *   flush the streaming cache when coherent mappings are synced.
  124  */
  125 
  126 #include "opt_iommu.h"
  127 
  128 #include <sys/param.h>
  129 #include <sys/kernel.h>
  130 #include <sys/lock.h>
  131 #include <sys/malloc.h>
  132 #include <sys/mbuf.h>
  133 #include <sys/mutex.h>
  134 #include <sys/proc.h>
  135 #include <sys/systm.h>
  136 #include <sys/uio.h>
  137 
  138 #include <vm/vm.h>
  139 #include <vm/pmap.h>
  140 #include <vm/vm_map.h>
  141 
  142 #include <machine/bus.h>
  143 #include <machine/bus_private.h>
  144 #include <machine/iommureg.h>
  145 #include <machine/pmap.h>
  146 #include <machine/resource.h>
  147 
  148 #include <sys/rman.h>
  149 
  150 #include <machine/iommuvar.h>
  151 
  152 /*
  153  * Tuning constants.
  154  */
  155 #define IOMMU_MAX_PRE           (32 * 1024)
  156 #define IOMMU_MAX_PRE_SEG       3
  157 
  158 /* Threshold for using the streaming buffer. */
  159 #define IOMMU_STREAM_THRESH     128
  160 
  161 MALLOC_DEFINE(M_IOMMU, "dvmamem", "IOMMU DVMA Buffers");
  162 
  163 static  int iommu_strbuf_flush_sync(struct iommu_state *);
  164 #ifdef IOMMU_DIAG
  165 static  void iommu_diag(struct iommu_state *, vm_offset_t va);
  166 #endif
  167 
  168 /*
  169  * Helpers
  170  */
  171 #define IOMMU_READ8(is, reg, off)                                       \
  172         bus_space_read_8((is)->is_bustag, (is)->is_bushandle,           \
  173             (is)->reg + (off))
  174 #define IOMMU_WRITE8(is, reg, off, v)                                   \
  175         bus_space_write_8((is)->is_bustag, (is)->is_bushandle,          \
  176             (is)->reg + (off), (v))
  177 
  178 #define IOMMU_HAS_SB(is)                                                \
  179         ((is)->is_sb[0] != 0 || (is)->is_sb[1] != 0)
  180 
  181 /*
  182  * Always overallocate one page; this is needed to handle alignment of the
  183  * buffer, so it makes sense using a lazy allocation scheme.
  184  */
  185 #define IOMMU_SIZE_ROUNDUP(sz)                                          \
  186         (round_io_page(sz) + IO_PAGE_SIZE)
  187 
  188 #define IOMMU_SET_TTE(is, va, tte)                                      \
  189         ((is)->is_tsb[IOTSBSLOT(va)] = (tte))
  190 #define IOMMU_GET_TTE(is, va)                                           \
  191         (is)->is_tsb[IOTSBSLOT(va)]
  192 
  193 /* Resource helpers */
  194 #define IOMMU_RES_START(res)                                            \
  195         ((bus_addr_t)rman_get_start(res) << IO_PAGE_SHIFT)
  196 #define IOMMU_RES_END(res)                                              \
  197         ((bus_addr_t)(rman_get_end(res) + 1) << IO_PAGE_SHIFT)
  198 #define IOMMU_RES_SIZE(res)                                             \
  199         ((bus_size_t)rman_get_size(res) << IO_PAGE_SHIFT)
  200 
  201 /* Helpers for struct bus_dmamap_res */
  202 #define BDR_START(r)    IOMMU_RES_START((r)->dr_res)
  203 #define BDR_END(r)      IOMMU_RES_END((r)->dr_res)
  204 #define BDR_SIZE(r)     IOMMU_RES_SIZE((r)->dr_res)
  205 
  206 /* Locking macros */
  207 #define IS_LOCK(is)     mtx_lock(&is->is_mtx)
  208 #define IS_LOCK_ASSERT(is)      mtx_assert(&is->is_mtx, MA_OWNED)
  209 #define IS_UNLOCK(is)   mtx_unlock(&is->is_mtx)
  210 
  211 /* Flush a page from the TLB. No locking required, since this is atomic. */
  212 static __inline void
  213 iommu_tlb_flush(struct iommu_state *is, bus_addr_t va)
  214 {
  215 
  216         IOMMU_WRITE8(is, is_iommu, IMR_FLUSH, va);
  217 }
  218 
  219 /*
  220  * Flush a page from the streaming buffer. No locking required, since this is
  221  * atomic.
  222  */
  223 static __inline void
  224 iommu_strbuf_flushpg(struct iommu_state *is, bus_addr_t va)
  225 {
  226         int i;
  227 
  228         for (i = 0; i < 2; i++)
  229                 if (is->is_sb[i] != 0)
  230                         IOMMU_WRITE8(is, is_sb[i], ISR_PGFLUSH, va);
  231 }
  232 
  233 /*
  234  * Flush an address from the streaming buffer(s); this is an asynchronous
  235  * operation. To make sure that it has completed, iommu_strbuf_sync() needs
  236  * to be called. No locking required.
  237  */
  238 static __inline void
  239 iommu_strbuf_flush(struct iommu_state *is, bus_addr_t va)
  240 {
  241 
  242         iommu_strbuf_flushpg(is, va);
  243 }
  244 
  245 /* Synchronize all outstanding flush operations. */
  246 static __inline void
  247 iommu_strbuf_sync(struct iommu_state *is)
  248 {
  249 
  250         IS_LOCK_ASSERT(is);
  251         iommu_strbuf_flush_sync(is);
  252 }
  253 
  254 /* LRU queue handling for lazy resource allocation. */
  255 static __inline void
  256 iommu_map_insq(struct iommu_state *is, bus_dmamap_t map)
  257 {
  258 
  259         IS_LOCK_ASSERT(is);
  260         if (!SLIST_EMPTY(&map->dm_reslist)) {
  261                 if (map->dm_onq)
  262                         TAILQ_REMOVE(&is->is_maplruq, map, dm_maplruq);
  263                 TAILQ_INSERT_TAIL(&is->is_maplruq, map, dm_maplruq);
  264                 map->dm_onq = 1;
  265         }
  266 }
  267 
  268 static __inline void
  269 iommu_map_remq(struct iommu_state *is, bus_dmamap_t map)
  270 {
  271 
  272         IS_LOCK_ASSERT(is);
  273         if (map->dm_onq)
  274                 TAILQ_REMOVE(&is->is_maplruq, map, dm_maplruq);
  275         map->dm_onq = 0;
  276 }
  277 
  278 /*
  279  * initialise the UltraSPARC IOMMU (PCI or SBus):
  280  *      - allocate and setup the iotsb.
  281  *      - enable the IOMMU
  282  *      - initialise the streaming buffers (if they exist)
  283  *      - create a private DVMA map.
  284  */
  285 void
  286 iommu_init(char *name, struct iommu_state *is, int tsbsize, u_int32_t iovabase,
  287     int resvpg)
  288 {
  289         vm_size_t size;
  290         vm_offset_t offs;
  291         u_int64_t end;
  292         int i;
  293 
  294         /*
  295          * Setup the iommu.
  296          *
  297          * The sun4u iommu is part of the PCI or SBus controller so we
  298          * will deal with it here..
  299          *
  300          * The IOMMU address space always ends at 0xffffe000, but the starting
  301          * address depends on the size of the map.  The map size is 1024 * 2 ^
  302          * is->is_tsbsize entries, where each entry is 8 bytes.  The start of
  303          * the map can be calculated by (0xffffe000 << (8 + is->is_tsbsize)).
  304          */
  305         is->is_cr = (tsbsize << IOMMUCR_TSBSZ_SHIFT) | IOMMUCR_EN;
  306         is->is_tsbsize = tsbsize;
  307         is->is_dvmabase = iovabase;
  308         if (iovabase == -1)
  309                 is->is_dvmabase = IOTSB_VSTART(is->is_tsbsize);
  310 
  311         size = IOTSB_BASESZ << is->is_tsbsize;
  312         printf("%s: DVMA map: %#lx to %#lx\n", name,
  313             is->is_dvmabase, is->is_dvmabase +
  314             (size << (IO_PAGE_SHIFT - IOTTE_SHIFT)) - 1);
  315 
  316         /*
  317          * Set up resource mamangement.
  318          */
  319         mtx_init(&is->is_mtx, "iommu", NULL, MTX_DEF);
  320         end = is->is_dvmabase + (size << (IO_PAGE_SHIFT - IOTTE_SHIFT));
  321         is->is_dvma_rman.rm_type = RMAN_ARRAY;
  322         is->is_dvma_rman.rm_descr = "DVMA Memory";
  323         if (rman_init(&is->is_dvma_rman) != 0 ||
  324             rman_manage_region(&is->is_dvma_rman,
  325             (is->is_dvmabase >> IO_PAGE_SHIFT) + resvpg,
  326             (end >> IO_PAGE_SHIFT) - 1) != 0)
  327                 panic("%s: could not initialize DVMA rman", __func__);
  328         TAILQ_INIT(&is->is_maplruq);
  329 
  330         /*
  331          * Allocate memory for I/O page tables.  They need to be
  332          * physically contiguous.
  333          */
  334         is->is_tsb = contigmalloc(size, M_DEVBUF, M_NOWAIT, 0, ~0UL,
  335             PAGE_SIZE, 0);
  336         if (is->is_tsb == 0)
  337                 panic("%s: contigmalloc failed", __func__);
  338         is->is_ptsb = pmap_kextract((vm_offset_t)is->is_tsb);
  339         bzero(is->is_tsb, size);
  340 
  341         /*
  342          * Initialize streaming buffer, if it is there.
  343          */
  344         if (IOMMU_HAS_SB(is)) {
  345                 /*
  346                  * Find two 64-byte blocks in is_flush that are aligned on
  347                  * a 64-byte boundary for flushing.
  348                  */
  349                 offs = roundup2((vm_offset_t)is->is_flush,
  350                     STRBUF_FLUSHSYNC_NBYTES);
  351                 for (i = 0; i < 2; i++, offs += STRBUF_FLUSHSYNC_NBYTES) {
  352                         is->is_flushva[i] = (int64_t *)offs;
  353                         is->is_flushpa[i] = pmap_kextract(offs);
  354                 }
  355         }
  356 
  357         /*
  358          * Now actually start up the IOMMU.
  359          */
  360         iommu_reset(is);
  361 }
  362 
  363 /*
  364  * Streaming buffers don't exist on the UltraSPARC IIi; we should have
  365  * detected that already and disabled them.  If not, we will notice that
  366  * they aren't there when the STRBUF_EN bit does not remain.
  367  */
  368 void
  369 iommu_reset(struct iommu_state *is)
  370 {
  371         int i;
  372 
  373         IOMMU_WRITE8(is, is_iommu, IMR_TSB, is->is_ptsb);
  374         /* Enable IOMMU in diagnostic mode */
  375         IOMMU_WRITE8(is, is_iommu, IMR_CTL, is->is_cr | IOMMUCR_DE);
  376 
  377         for (i = 0; i < 2; i++) {
  378                 if (is->is_sb[i] != 0) {
  379                         /* Enable diagnostics mode? */
  380                         IOMMU_WRITE8(is, is_sb[i], ISR_CTL, STRBUF_EN);
  381 
  382                         /* No streaming buffers? Disable them */
  383                         if (IOMMU_READ8(is, is_sb[i], ISR_CTL) == 0)
  384                                 is->is_sb[i] = 0;
  385                 }
  386         }
  387 }
  388 
  389 /*
  390  * Enter a mapping into the TSB. No locking required, since each TSB slot is
  391  * uniquely assigned to a single map.
  392  */
  393 static void
  394 iommu_enter(struct iommu_state *is, vm_offset_t va, vm_paddr_t pa,
  395     int stream, int flags)
  396 {
  397         int64_t tte;
  398 
  399         KASSERT(va >= is->is_dvmabase,
  400             ("iommu_enter: va %#lx not in DVMA space", va));
  401         KASSERT(pa <= is->is_pmaxaddr,
  402             ("iommu_enter: XXX: physical address too large (%#lx)", pa));
  403 
  404         tte = MAKEIOTTE(pa, !(flags & BUS_DMA_NOWRITE),
  405             !(flags & BUS_DMA_NOCACHE), stream);
  406 
  407         IOMMU_SET_TTE(is, va, tte);
  408         iommu_tlb_flush(is, va);
  409 #ifdef IOMMU_DIAG
  410         IS_LOCK(is);
  411         iommu_diag(is, va);
  412         IS_UNLOCK(is);
  413 #endif
  414 }
  415 
  416 /*
  417  * Remove mappings created by iommu_enter. Flush the streaming buffer, but do
  418  * not synchronize it. Returns whether a streaming buffer flush was performed.
  419  */
  420 static int
  421 iommu_remove(struct iommu_state *is, vm_offset_t va, vm_size_t len)
  422 {
  423         int streamed = 0;
  424 
  425 #ifdef IOMMU_DIAG
  426         iommu_diag(is, va);
  427 #endif
  428 
  429         KASSERT(va >= is->is_dvmabase,
  430             ("iommu_remove: va 0x%lx not in DVMA space", (u_long)va));
  431         KASSERT(va + len >= va,
  432             ("iommu_remove: va 0x%lx + len 0x%lx wraps", (long)va, (long)len));
  433 
  434         va = trunc_io_page(va);
  435         while (len > 0) {
  436                 if ((IOMMU_GET_TTE(is, va) & IOTTE_STREAM) != 0) {
  437                         streamed = 1;
  438                         iommu_strbuf_flush(is, va);
  439                 }
  440                 len -= ulmin(len, IO_PAGE_SIZE);
  441                 IOMMU_SET_TTE(is, va, 0);
  442                 iommu_tlb_flush(is, va);
  443                 va += IO_PAGE_SIZE;
  444         }
  445         return (streamed);
  446 }
  447 
  448 /* Decode an IOMMU fault for host bridge error handlers. */
  449 void
  450 iommu_decode_fault(struct iommu_state *is, vm_offset_t phys)
  451 {
  452         bus_addr_t va;
  453         long idx;
  454 
  455         idx = phys - is->is_ptsb;
  456         if (phys < is->is_ptsb ||
  457             idx > (PAGE_SIZE << is->is_tsbsize))
  458                 return;
  459         va = is->is_dvmabase +
  460             (((bus_addr_t)idx >> IOTTE_SHIFT) << IO_PAGE_SHIFT);
  461         printf("IOMMU fault virtual address %#lx\n", (u_long)va);
  462 }
  463 
  464 /*
  465  * A barrier operation which makes sure that all previous streaming buffer
  466  * flushes complete before it returns.
  467  */
  468 static int
  469 iommu_strbuf_flush_sync(struct iommu_state *is)
  470 {
  471         struct timeval cur, end;
  472         int i;
  473 
  474         IS_LOCK_ASSERT(is);
  475         if (!IOMMU_HAS_SB(is))
  476                 return (0);
  477 
  478         /*
  479          * Streaming buffer flushes:
  480          *
  481          *   1 Tell strbuf to flush by storing va to strbuf_pgflush.  If
  482          *     we're not on a cache line boundary (64-bits):
  483          *   2 Store 0 in flag
  484          *   3 Store pointer to flag in flushsync
  485          *   4 wait till flushsync becomes 0x1
  486          *
  487          * If it takes more than .5 sec, something
  488          * went wrong.
  489          */
  490         *is->is_flushva[0] = 1;
  491         *is->is_flushva[1] = 1;
  492         membar(StoreStore);
  493         for (i = 0; i < 2; i++) {
  494                 if (is->is_sb[i] != 0) {
  495                         *is->is_flushva[i] = 0;
  496                         IOMMU_WRITE8(is, is_sb[i], ISR_FLUSHSYNC,
  497                             is->is_flushpa[i]);
  498                 }
  499         }
  500 
  501         microuptime(&cur);
  502         end.tv_sec = 0;
  503         /*
  504          * 0.5s is the recommended timeout from the U2S manual. The actual
  505          * time required should be smaller by at least a factor of 1000.
  506          * We have no choice but to busy-wait.
  507          */
  508         end.tv_usec = 500000;
  509         timevaladd(&end, &cur);
  510 
  511         while ((!*is->is_flushva[0] || !*is->is_flushva[1]) &&
  512             timevalcmp(&cur, &end, <=))
  513                 microuptime(&cur);
  514 
  515         if (!*is->is_flushva[0] || !*is->is_flushva[1]) {
  516                 panic("%s: flush timeout %ld, %ld at %#lx", __func__,
  517                     *is->is_flushva[0], *is->is_flushva[1], is->is_flushpa[0]);
  518         }
  519 
  520         return (1);
  521 }
  522 
  523 /* Determine whether we may enable streaming on a mapping. */
  524 static __inline int
  525 iommu_use_streaming(struct iommu_state *is, bus_dmamap_t map, bus_size_t size)
  526 {
  527 
  528         /*
  529          * This cannot be enabled yet, as many driver are still missing
  530          * bus_dmamap_sync() calls. As soon as there is a BUS_DMA_STREAMING
  531          * flag, this should be reenabled conditionally on it.
  532          */
  533 #ifdef notyet
  534         return (size >= IOMMU_STREAM_THRESH && IOMMU_HAS_SB(is) &&
  535             (map->dm_flags & DMF_COHERENT) == 0);
  536 #else
  537         return (0);
  538 #endif
  539 }
  540 
  541 /*
  542  * Allocate DVMA virtual memory for a map. The map may not be on a queue, so
  543  * that it can be freely modified.
  544  */
  545 static int
  546 iommu_dvma_valloc(bus_dma_tag_t t, struct iommu_state *is, bus_dmamap_t map,
  547     bus_size_t size)
  548 {
  549         struct resource *res;
  550         struct bus_dmamap_res *bdr;
  551         bus_size_t align, sgsize;
  552 
  553         KASSERT(!map->dm_onq, ("iommu_dvma_valloc: map on queue!"));
  554         if ((bdr = malloc(sizeof(*bdr), M_IOMMU, M_NOWAIT)) == NULL)
  555                 return (EAGAIN);
  556         /*
  557          * If a boundary is specified, a map cannot be larger than it; however
  558          * we do not clip currently, as that does not play well with the lazy
  559          * allocation code.
  560          * Alignment to a page boundary is always enforced.
  561          */
  562         align = (t->dt_alignment + IO_PAGE_MASK) >> IO_PAGE_SHIFT;
  563         sgsize = round_io_page(size) >> IO_PAGE_SHIFT;
  564         if (t->dt_boundary > 0 && t->dt_boundary < IO_PAGE_SIZE)
  565                 panic("%s: illegal boundary specified", __func__);
  566         res = rman_reserve_resource_bound(&is->is_dvma_rman, 0L,
  567             t->dt_lowaddr >> IO_PAGE_SHIFT, sgsize,
  568             t->dt_boundary >> IO_PAGE_SHIFT,
  569             RF_ACTIVE | rman_make_alignment_flags(align), NULL);
  570         if (res == NULL) {
  571                 free(bdr, M_IOMMU);
  572                 return (ENOMEM);
  573         }
  574 
  575         bdr->dr_res = res;
  576         bdr->dr_used = 0;
  577         SLIST_INSERT_HEAD(&map->dm_reslist, bdr, dr_link);
  578         return (0);
  579 }
  580 
  581 /* Unload the map and mark all resources as unused, but do not free them. */
  582 static void
  583 iommu_dvmamap_vunload(struct iommu_state *is, bus_dmamap_t map)
  584 {
  585         struct bus_dmamap_res *r;
  586         int streamed = 0;
  587 
  588         IS_LOCK_ASSERT(is);     /* for iommu_strbuf_sync() below. */
  589         SLIST_FOREACH(r, &map->dm_reslist, dr_link) {
  590                 streamed |= iommu_remove(is, BDR_START(r), r->dr_used);
  591                 r->dr_used = 0;
  592         }
  593         if (streamed)
  594                 iommu_strbuf_sync(is);
  595 }
  596 
  597 /* Free a DVMA virtual memory resource. */
  598 static __inline void
  599 iommu_dvma_vfree_res(bus_dmamap_t map, struct bus_dmamap_res *r)
  600 {
  601 
  602         KASSERT(r->dr_used == 0, ("iommu_dvma_vfree_res: resource busy!"));
  603         if (r->dr_res != NULL && rman_release_resource(r->dr_res) != 0)
  604                 printf("warning: DVMA space lost\n");
  605         SLIST_REMOVE(&map->dm_reslist, r, bus_dmamap_res, dr_link);
  606         free(r, M_IOMMU);
  607 }
  608 
  609 /* Free all DVMA virtual memory for a map. */
  610 static void
  611 iommu_dvma_vfree(struct iommu_state *is, bus_dmamap_t map)
  612 {
  613 
  614         IS_LOCK(is);
  615         iommu_map_remq(is, map);
  616         iommu_dvmamap_vunload(is, map);
  617         IS_UNLOCK(is);
  618         while (!SLIST_EMPTY(&map->dm_reslist))
  619                 iommu_dvma_vfree_res(map, SLIST_FIRST(&map->dm_reslist));
  620 }
  621 
  622 /* Prune a map, freeing all unused DVMA resources. */
  623 static bus_size_t
  624 iommu_dvma_vprune(struct iommu_state *is, bus_dmamap_t map)
  625 {
  626         struct bus_dmamap_res *r, *n;
  627         bus_size_t freed = 0;
  628 
  629         IS_LOCK_ASSERT(is);
  630         for (r = SLIST_FIRST(&map->dm_reslist); r != NULL; r = n) {
  631                 n = SLIST_NEXT(r, dr_link);
  632                 if (r->dr_used == 0) {
  633                         freed += BDR_SIZE(r);
  634                         iommu_dvma_vfree_res(map, r);
  635                 }
  636         }
  637         if (SLIST_EMPTY(&map->dm_reslist))
  638                 iommu_map_remq(is, map);
  639         return (freed);
  640 }
  641 
  642 /*
  643  * Try to find a suitably-sized (and if requested, -aligned) slab of DVMA
  644  * memory with IO page offset voffs.
  645  */
  646 static bus_addr_t
  647 iommu_dvma_vfindseg(bus_dmamap_t map, vm_offset_t voffs, bus_size_t size,
  648     bus_addr_t amask)
  649 {
  650         struct bus_dmamap_res *r;
  651         bus_addr_t dvmaddr, dvmend;
  652 
  653         KASSERT(!map->dm_onq, ("iommu_dvma_vfindseg: map on queue!"));
  654         SLIST_FOREACH(r, &map->dm_reslist, dr_link) {
  655                 dvmaddr = round_io_page(BDR_START(r) + r->dr_used);
  656                 /* Alignment can only work with voffs == 0. */
  657                 dvmaddr = (dvmaddr + amask) & ~amask;
  658                 dvmaddr += voffs;
  659                 dvmend = dvmaddr + size;
  660                 if (dvmend <= BDR_END(r)) {
  661                         r->dr_used = dvmend - BDR_START(r);
  662                         return (dvmaddr);
  663                 }
  664         }
  665         return (0);
  666 }
  667 
  668 /*
  669  * Try to find or allocate a slab of DVMA space; see above.
  670  */
  671 static int
  672 iommu_dvma_vallocseg(bus_dma_tag_t dt, struct iommu_state *is, bus_dmamap_t map,
  673     vm_offset_t voffs, bus_size_t size, bus_addr_t amask, bus_addr_t *addr)
  674 {
  675         bus_dmamap_t tm, last;
  676         bus_addr_t dvmaddr, freed;
  677         int error, complete = 0;
  678 
  679         dvmaddr = iommu_dvma_vfindseg(map, voffs, size, amask);
  680 
  681         /* Need to allocate. */
  682         if (dvmaddr == 0) {
  683                 while ((error = iommu_dvma_valloc(dt, is, map,
  684                         voffs + size)) == ENOMEM && !complete) {
  685                         /*
  686                          * Free the allocated DVMA of a few maps until
  687                          * the required size is reached. This is an
  688                          * approximation to not have to call the allocation
  689                          * function too often; most likely one free run
  690                          * will not suffice if not one map was large enough
  691                          * itself due to fragmentation.
  692                          */
  693                         IS_LOCK(is);
  694                         freed = 0;
  695                         last = TAILQ_LAST(&is->is_maplruq, iommu_maplruq_head);
  696                         do {
  697                                 tm = TAILQ_FIRST(&is->is_maplruq);
  698                                 complete = tm == last;
  699                                 if (tm == NULL)
  700                                         break;
  701                                 freed += iommu_dvma_vprune(is, tm);
  702                                 /* Move to the end. */
  703                                 iommu_map_insq(is, tm);
  704                         } while (freed < size && !complete);
  705                         IS_UNLOCK(is);
  706                 }
  707                 if (error != 0)
  708                         return (error);
  709                 dvmaddr = iommu_dvma_vfindseg(map, voffs, size, amask);
  710                 KASSERT(dvmaddr != 0,
  711                     ("iommu_dvma_vallocseg: allocation failed unexpectedly!"));
  712         }
  713         *addr = dvmaddr;
  714         return (0);
  715 }
  716 
  717 static int
  718 iommu_dvmamem_alloc(bus_dma_tag_t dt, void **vaddr, int flags,
  719     bus_dmamap_t *mapp)
  720 {
  721         struct iommu_state *is = dt->dt_cookie;
  722         int error, mflags;
  723 
  724         /*
  725          * XXX: This will break for 32 bit transfers on machines with more
  726          * than is->is_pmaxaddr memory.
  727          */
  728         if ((error = sparc64_dma_alloc_map(dt, mapp)) != 0)
  729                 return (error);
  730 
  731         if ((flags & BUS_DMA_NOWAIT) != 0)
  732                 mflags = M_NOWAIT;
  733         else
  734                 mflags = M_WAITOK;
  735         if ((flags & BUS_DMA_ZERO) != 0)
  736                 mflags |= M_ZERO;
  737 
  738         if ((*vaddr = malloc(dt->dt_maxsize, M_IOMMU, mflags)) == NULL) {
  739                 error = ENOMEM;
  740                 sparc64_dma_free_map(dt, *mapp);
  741                 return (error);
  742         }
  743         if ((flags & BUS_DMA_COHERENT) != 0)
  744                 (*mapp)->dm_flags |= DMF_COHERENT;
  745         /*
  746          * Try to preallocate DVMA space. If this fails, it is retried at load
  747          * time.
  748          */
  749         iommu_dvma_valloc(dt, is, *mapp, IOMMU_SIZE_ROUNDUP(dt->dt_maxsize));
  750         IS_LOCK(is);
  751         iommu_map_insq(is, *mapp);
  752         IS_UNLOCK(is);
  753         return (0);
  754 }
  755 
  756 static void
  757 iommu_dvmamem_free(bus_dma_tag_t dt, void *vaddr, bus_dmamap_t map)
  758 {
  759         struct iommu_state *is = dt->dt_cookie;
  760 
  761         iommu_dvma_vfree(is, map);
  762         sparc64_dma_free_map(dt, map);
  763         free(vaddr, M_IOMMU);
  764 }
  765 
  766 static int
  767 iommu_dvmamap_create(bus_dma_tag_t dt, int flags, bus_dmamap_t *mapp)
  768 {
  769         struct iommu_state *is = dt->dt_cookie;
  770         bus_size_t totsz, presz, currsz;
  771         int error, i, maxpre;
  772 
  773         if ((error = sparc64_dma_alloc_map(dt, mapp)) != 0)
  774                 return (error);
  775         if ((flags & BUS_DMA_COHERENT) != 0)
  776                 (*mapp)->dm_flags |= DMF_COHERENT;
  777         /*
  778          * Preallocate DVMA space; if this fails now, it is retried at load
  779          * time. Through bus_dmamap_load_mbuf() and bus_dmamap_load_uio(), it
  780          * is possible to have multiple discontiguous segments in a single map,
  781          * which is handled by allocating additional resources, instead of
  782          * increasing the size, to avoid fragmentation.
  783          * Clamp preallocation to IOMMU_MAX_PRE. In some situations we can
  784          * handle more; that case is handled by reallocating at map load time.
  785          */
  786         totsz = ulmin(IOMMU_SIZE_ROUNDUP(dt->dt_maxsize), IOMMU_MAX_PRE);
  787         error = iommu_dvma_valloc(dt, is, *mapp, totsz);
  788         if (error != 0)
  789                 return (0);
  790         /*
  791          * Try to be smart about preallocating some additional segments if
  792          * needed.
  793          */
  794         maxpre = imin(dt->dt_nsegments, IOMMU_MAX_PRE_SEG);
  795         presz = dt->dt_maxsize / maxpre;
  796         KASSERT(presz != 0, ("iommu_dvmamap_create: bogus preallocation size "
  797             ", nsegments = %d, maxpre = %d, maxsize = %lu", dt->dt_nsegments,
  798             maxpre, dt->dt_maxsize));
  799         for (i = 1; i < maxpre && totsz < IOMMU_MAX_PRE; i++) {
  800                 currsz = round_io_page(ulmin(presz, IOMMU_MAX_PRE - totsz));
  801                 error = iommu_dvma_valloc(dt, is, *mapp, currsz);
  802                 if (error != 0)
  803                         break;
  804                 totsz += currsz;
  805         }
  806         IS_LOCK(is);
  807         iommu_map_insq(is, *mapp);
  808         IS_UNLOCK(is);
  809         return (0);
  810 }
  811 
  812 static int
  813 iommu_dvmamap_destroy(bus_dma_tag_t dt, bus_dmamap_t map)
  814 {
  815         struct iommu_state *is = dt->dt_cookie;
  816 
  817         iommu_dvma_vfree(is, map);
  818         sparc64_dma_free_map(dt, map);
  819         return (0);
  820 }
  821 
  822 /*
  823  * IOMMU DVMA operations, common to PCI and SBus.
  824  */
  825 static int
  826 iommu_dvmamap_load_buffer(bus_dma_tag_t dt, struct iommu_state *is,
  827     bus_dmamap_t map, void *buf, bus_size_t buflen, struct thread *td,
  828     int flags, bus_dma_segment_t *segs, int *segp, int align)
  829 {
  830         bus_addr_t amask, dvmaddr;
  831         bus_size_t sgsize, esize;
  832         vm_offset_t vaddr, voffs;
  833         vm_paddr_t curaddr;
  834         int error, sgcnt, firstpg, stream;
  835         pmap_t pmap = NULL;
  836 
  837         KASSERT(buflen != 0, ("iommu_dvmamap_load_buffer: buflen == 0!"));
  838         if (buflen > dt->dt_maxsize)
  839                 return (EINVAL);
  840 
  841         if (td != NULL)
  842                 pmap = vmspace_pmap(td->td_proc->p_vmspace);
  843 
  844         vaddr = (vm_offset_t)buf;
  845         voffs = vaddr & IO_PAGE_MASK;
  846         amask = align ? dt->dt_alignment - 1 : 0;
  847 
  848         /* Try to find a slab that is large enough. */
  849         error = iommu_dvma_vallocseg(dt, is, map, voffs, buflen, amask,
  850             &dvmaddr);
  851         if (error != 0)
  852                 return (error);
  853 
  854         sgcnt = *segp;
  855         firstpg = 1;
  856         stream = iommu_use_streaming(is, map, buflen);
  857         for (; buflen > 0; ) {
  858                 /*
  859                  * Get the physical address for this page.
  860                  */
  861                 if (pmap != NULL)
  862                         curaddr = pmap_extract(pmap, vaddr);
  863                 else
  864                         curaddr = pmap_kextract(vaddr);
  865 
  866                 /*
  867                  * Compute the segment size, and adjust counts.
  868                  */
  869                 sgsize = IO_PAGE_SIZE - ((u_long)vaddr & IO_PAGE_MASK);
  870                 if (buflen < sgsize)
  871                         sgsize = buflen;
  872 
  873                 buflen -= sgsize;
  874                 vaddr += sgsize;
  875 
  876                 iommu_enter(is, trunc_io_page(dvmaddr), trunc_io_page(curaddr),
  877                     stream, flags);
  878 
  879                 /*
  880                  * Chop the chunk up into segments of at most maxsegsz, but try
  881                  * to fill each segment as well as possible.
  882                  */
  883                 if (!firstpg) {
  884                         esize = ulmin(sgsize,
  885                             dt->dt_maxsegsz - segs[sgcnt].ds_len);
  886                         segs[sgcnt].ds_len += esize;
  887                         sgsize -= esize;
  888                         dvmaddr += esize;
  889                 }
  890                 while (sgsize > 0) {
  891                         sgcnt++;
  892                         if (sgcnt >= dt->dt_nsegments)
  893                                 return (EFBIG);
  894                         /*
  895                          * No extra alignment here - the common practice in the
  896                          * busdma code seems to be that only the first segment
  897                          * needs to satisfy the alignment constraints (and that
  898                          * only for bus_dmamem_alloc()ed maps). It is assumed
  899                          * that such tags have maxsegsize >= maxsize.
  900                          */
  901                         esize = ulmin(sgsize, dt->dt_maxsegsz);
  902                         segs[sgcnt].ds_addr = dvmaddr;
  903                         segs[sgcnt].ds_len = esize;
  904                         sgsize -= esize;
  905                         dvmaddr += esize;
  906                 }
  907 
  908                 firstpg = 0;
  909         }
  910         *segp = sgcnt;
  911         return (0);
  912 }
  913 
  914 static int
  915 iommu_dvmamap_load(bus_dma_tag_t dt, bus_dmamap_t map, void *buf,
  916     bus_size_t buflen, bus_dmamap_callback_t *cb, void *cba,
  917     int flags)
  918 {
  919         struct iommu_state *is = dt->dt_cookie;
  920         int error, seg = -1;
  921 
  922         if ((map->dm_flags & DMF_LOADED) != 0) {
  923 #ifdef DIAGNOSTIC
  924                 printf("%s: map still in use\n", __func__);
  925 #endif
  926                 bus_dmamap_unload(dt, map);
  927         }
  928 
  929         /*
  930          * Make sure that the map is not on a queue so that the resource list
  931          * may be safely accessed and modified without needing the lock to
  932          * cover the whole operation.
  933          */
  934         IS_LOCK(is);
  935         iommu_map_remq(is, map);
  936         IS_UNLOCK(is);
  937 
  938         error = iommu_dvmamap_load_buffer(dt, is, map, buf, buflen, NULL,
  939             flags, dt->dt_segments, &seg, 1);
  940 
  941         IS_LOCK(is);
  942         iommu_map_insq(is, map);
  943         if (error != 0) {
  944                 iommu_dvmamap_vunload(is, map);
  945                 IS_UNLOCK(is);
  946                 (*cb)(cba, dt->dt_segments, 0, error);
  947         } else {
  948                 IS_UNLOCK(is);
  949                 map->dm_flags |= DMF_LOADED;
  950                 (*cb)(cba, dt->dt_segments, seg + 1, 0);
  951         }
  952 
  953         return (error);
  954 }
  955 
  956 static int
  957 iommu_dvmamap_load_mbuf(bus_dma_tag_t dt, bus_dmamap_t map, struct mbuf *m0,
  958     bus_dmamap_callback2_t *cb, void *cba, int flags)
  959 {
  960         struct iommu_state *is = dt->dt_cookie;
  961         struct mbuf *m;
  962         int error = 0, first = 1, nsegs = -1;
  963 
  964         M_ASSERTPKTHDR(m0);
  965 
  966         if ((map->dm_flags & DMF_LOADED) != 0) {
  967 #ifdef DIAGNOSTIC
  968                 printf("%s: map still in use\n", __func__);
  969 #endif
  970                 bus_dmamap_unload(dt, map);
  971         }
  972 
  973         IS_LOCK(is);
  974         iommu_map_remq(is, map);
  975         IS_UNLOCK(is);
  976 
  977         if (m0->m_pkthdr.len <= dt->dt_maxsize) {
  978                 for (m = m0; m != NULL && error == 0; m = m->m_next) {
  979                         if (m->m_len == 0)
  980                                 continue;
  981                         error = iommu_dvmamap_load_buffer(dt, is, map,
  982                             m->m_data, m->m_len, NULL, flags, dt->dt_segments,
  983                             &nsegs, first);
  984                         first = 0;
  985                 }
  986         } else
  987                 error = EINVAL;
  988 
  989         IS_LOCK(is);
  990         iommu_map_insq(is, map);
  991         if (error != 0) {
  992                 iommu_dvmamap_vunload(is, map);
  993                 IS_UNLOCK(is);
  994                 /* force "no valid mappings" in callback */
  995                 (*cb)(cba, dt->dt_segments, 0, 0, error);
  996         } else {
  997                 IS_UNLOCK(is);
  998                 map->dm_flags |= DMF_LOADED;
  999                 (*cb)(cba, dt->dt_segments, nsegs + 1, m0->m_pkthdr.len, 0);
 1000         }
 1001         return (error);
 1002 }
 1003 
 1004 static int
 1005 iommu_dvmamap_load_mbuf_sg(bus_dma_tag_t dt, bus_dmamap_t map, struct mbuf *m0,
 1006     bus_dma_segment_t *segs, int *nsegs, int flags)
 1007 {
 1008         struct iommu_state *is = dt->dt_cookie;
 1009         struct mbuf *m;
 1010         int error = 0, first = 1;
 1011 
 1012         M_ASSERTPKTHDR(m0);
 1013 
 1014         *nsegs = -1;
 1015         if ((map->dm_flags & DMF_LOADED) != 0) {
 1016 #ifdef DIAGNOSTIC
 1017                 printf("%s: map still in use\n", __func__);
 1018 #endif
 1019                 bus_dmamap_unload(dt, map);
 1020         }
 1021 
 1022         IS_LOCK(is);
 1023         iommu_map_remq(is, map);
 1024         IS_UNLOCK(is);
 1025 
 1026         if (m0->m_pkthdr.len <= dt->dt_maxsize) {
 1027                 for (m = m0; m != NULL && error == 0; m = m->m_next) {
 1028                         if (m->m_len == 0)
 1029                                 continue;
 1030                         error = iommu_dvmamap_load_buffer(dt, is, map,
 1031                             m->m_data, m->m_len, NULL, flags, segs,
 1032                             nsegs, first);
 1033                         first = 0;
 1034                 }
 1035         } else
 1036                 error = EINVAL;
 1037 
 1038         IS_LOCK(is);
 1039         iommu_map_insq(is, map);
 1040         if (error != 0) {
 1041                 iommu_dvmamap_vunload(is, map);
 1042         } else {
 1043                 map->dm_flags |= DMF_LOADED;
 1044                 ++*nsegs;
 1045         }
 1046         IS_UNLOCK(is);
 1047         return (error);
 1048 }
 1049 
 1050 static int
 1051 iommu_dvmamap_load_uio(bus_dma_tag_t dt, bus_dmamap_t map, struct uio *uio,
 1052     bus_dmamap_callback2_t *cb,  void *cba, int flags)
 1053 {
 1054         struct iommu_state *is = dt->dt_cookie;
 1055         struct iovec *iov;
 1056         struct thread *td = NULL;
 1057         bus_size_t minlen, resid;
 1058         int nsegs = -1, error = 0, first = 1, i;
 1059 
 1060         if ((map->dm_flags & DMF_LOADED) != 0) {
 1061 #ifdef DIAGNOSTIC
 1062                 printf("%s: map still in use\n", __func__);
 1063 #endif
 1064                 bus_dmamap_unload(dt, map);
 1065         }
 1066 
 1067         IS_LOCK(is);
 1068         iommu_map_remq(is, map);
 1069         IS_UNLOCK(is);
 1070 
 1071         resid = uio->uio_resid;
 1072         iov = uio->uio_iov;
 1073 
 1074         if (uio->uio_segflg == UIO_USERSPACE) {
 1075                 td = uio->uio_td;
 1076                 KASSERT(td != NULL,
 1077                     ("%s: USERSPACE but no proc", __func__));
 1078         }
 1079 
 1080         for (i = 0; i < uio->uio_iovcnt && resid != 0 && error == 0; i++) {
 1081                 /*
 1082                  * Now at the first iovec to load.  Load each iovec
 1083                  * until we have exhausted the residual count.
 1084                  */
 1085                 minlen = resid < iov[i].iov_len ? resid : iov[i].iov_len;
 1086                 if (minlen == 0)
 1087                         continue;
 1088 
 1089                 error = iommu_dvmamap_load_buffer(dt, is, map,
 1090                     iov[i].iov_base, minlen, td, flags, dt->dt_segments,
 1091                     &nsegs, first);
 1092                 first = 0;
 1093 
 1094                 resid -= minlen;
 1095         }
 1096 
 1097         IS_LOCK(is);
 1098         iommu_map_insq(is, map);
 1099         if (error) {
 1100                 iommu_dvmamap_vunload(is, map);
 1101                 IS_UNLOCK(is);
 1102                 /* force "no valid mappings" in callback */
 1103                 (*cb)(cba, dt->dt_segments, 0, 0, error);
 1104         } else {
 1105                 IS_UNLOCK(is);
 1106                 map->dm_flags |= DMF_LOADED;
 1107                 (*cb)(cba, dt->dt_segments, nsegs + 1, uio->uio_resid, 0);
 1108         }
 1109         return (error);
 1110 }
 1111 
 1112 static void
 1113 iommu_dvmamap_unload(bus_dma_tag_t dt, bus_dmamap_t map)
 1114 {
 1115         struct iommu_state *is = dt->dt_cookie;
 1116 
 1117         if ((map->dm_flags & DMF_LOADED) == 0)
 1118                 return;
 1119         IS_LOCK(is);
 1120         iommu_dvmamap_vunload(is, map);
 1121         iommu_map_insq(is, map);
 1122         IS_UNLOCK(is);
 1123         map->dm_flags &= ~DMF_LOADED;
 1124 }
 1125 
 1126 static void
 1127 iommu_dvmamap_sync(bus_dma_tag_t dt, bus_dmamap_t map, bus_dmasync_op_t op)
 1128 {
 1129         struct iommu_state *is = dt->dt_cookie;
 1130         struct bus_dmamap_res *r;
 1131         vm_offset_t va;
 1132         vm_size_t len;
 1133         int streamed = 0;
 1134 
 1135         if ((map->dm_flags & DMF_LOADED) == 0)
 1136                 return;
 1137         /* XXX This is probably bogus. */
 1138         if ((op & BUS_DMASYNC_PREREAD) != 0)
 1139                 membar(Sync);
 1140         if (IOMMU_HAS_SB(is) &&
 1141             ((op & BUS_DMASYNC_POSTREAD) != 0 ||
 1142             (op & BUS_DMASYNC_PREWRITE) != 0)) {
 1143                 IS_LOCK(is);
 1144                 SLIST_FOREACH(r, &map->dm_reslist, dr_link) {
 1145                         va = (vm_offset_t)BDR_START(r);
 1146                         len = r->dr_used;
 1147                         /* if we have a streaming buffer, flush it here first */
 1148                         while (len > 0) {
 1149                                 if ((IOMMU_GET_TTE(is, va) & IOTTE_STREAM) != 0) {
 1150                                         streamed = 1;
 1151                                         iommu_strbuf_flush(is, va);
 1152                                 }
 1153                                 len -= ulmin(len, IO_PAGE_SIZE);
 1154                                 va += IO_PAGE_SIZE;
 1155                         }
 1156                 }
 1157                 if (streamed)
 1158                         iommu_strbuf_sync(is);
 1159                 IS_UNLOCK(is);
 1160         }
 1161         if ((op & BUS_DMASYNC_PREWRITE) != 0)
 1162                 membar(Sync);
 1163 }
 1164 
 1165 #ifdef IOMMU_DIAG
 1166 
 1167 /*
 1168  * Perform an IOMMU diagnostic access and print the tag belonging to va.
 1169  */
 1170 static void
 1171 iommu_diag(struct iommu_state *is, vm_offset_t va)
 1172 {
 1173         int i;
 1174         u_int64_t tag, data;
 1175 
 1176         IS_LOCK_ASSERT(is);
 1177         IOMMU_WRITE8(is, is_dva, 0, trunc_io_page(va));
 1178         membar(StoreStore | StoreLoad);
 1179         printf("%s: tte entry %#lx", __func__, IOMMU_GET_TTE(is, va));
 1180         if (is->is_dtcmp != 0) {
 1181                 printf(", tag compare register is %#lx\n",
 1182                     IOMMU_READ8(is, is_dtcmp, 0));
 1183         } else
 1184                 printf("\n");
 1185         for (i = 0; i < 16; i++) {
 1186                 tag = IOMMU_READ8(is, is_dtag, i * 8);
 1187                 data = IOMMU_READ8(is, is_ddram, i * 8);
 1188                 printf("%s: tag %d: %#lx, vpn %#lx, err %lx; "
 1189                     "data %#lx, pa %#lx, v %d, c %d\n", __func__, i,
 1190                     tag, (tag & IOMMU_DTAG_VPNMASK) << IOMMU_DTAG_VPNSHIFT,
 1191                     (tag & IOMMU_DTAG_ERRMASK) >> IOMMU_DTAG_ERRSHIFT, data,
 1192                     (data & IOMMU_DDATA_PGMASK) << IOMMU_DDATA_PGSHIFT,
 1193                     (data & IOMMU_DDATA_V) != 0, (data & IOMMU_DDATA_C) != 0);
 1194         }
 1195 }
 1196 
 1197 #endif /* IOMMU_DIAG */
 1198 
 1199 struct bus_dma_methods iommu_dma_methods = {
 1200         iommu_dvmamap_create,
 1201         iommu_dvmamap_destroy,
 1202         iommu_dvmamap_load,
 1203         iommu_dvmamap_load_mbuf,
 1204         iommu_dvmamap_load_mbuf_sg,
 1205         iommu_dvmamap_load_uio,
 1206         iommu_dvmamap_unload,
 1207         iommu_dvmamap_sync,
 1208         iommu_dvmamem_alloc,
 1209         iommu_dvmamem_free,
 1210 };

Cache object: 05fa078bbfe8d0fb9c99fbc733e8cbbb


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.