1 1.29 thorpej /* $NetBSD: sgmap_common.c,v 1.29 2021/07/18 05:12:27 thorpej Exp $ */ 2 1.2 thorpej 3 1.2 thorpej /*- 4 1.18 thorpej * Copyright (c) 1997, 1998, 2001 The NetBSD Foundation, Inc. 5 1.2 thorpej * All rights reserved. 6 1.2 thorpej * 7 1.2 thorpej * This code is derived from software contributed to The NetBSD Foundation 8 1.2 thorpej * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 1.2 thorpej * NASA Ames Research Center. 10 1.2 thorpej * 11 1.2 thorpej * Redistribution and use in source and binary forms, with or without 12 1.2 thorpej * modification, are permitted provided that the following conditions 13 1.2 thorpej * are met: 14 1.2 thorpej * 1. Redistributions of source code must retain the above copyright 15 1.2 thorpej * notice, this list of conditions and the following disclaimer. 16 1.2 thorpej * 2. Redistributions in binary form must reproduce the above copyright 17 1.2 thorpej * notice, this list of conditions and the following disclaimer in the 18 1.2 thorpej * documentation and/or other materials provided with the distribution. 19 1.2 thorpej * 20 1.2 thorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 1.2 thorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 1.2 thorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 1.2 thorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 1.2 thorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 1.2 thorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 1.2 thorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 1.2 thorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 1.2 thorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 1.2 thorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 1.2 thorpej * POSSIBILITY OF SUCH DAMAGE. 31 1.2 thorpej */ 32 1.2 thorpej 33 1.2 thorpej #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 34 1.2 thorpej 35 1.29 thorpej __KERNEL_RCSID(0, "$NetBSD: sgmap_common.c,v 1.29 2021/07/18 05:12:27 thorpej Exp $"); 36 1.2 thorpej 37 1.2 thorpej #include <sys/param.h> 38 1.2 thorpej #include <sys/systm.h> 39 1.2 thorpej #include <sys/kernel.h> 40 1.2 thorpej #include <sys/proc.h> 41 1.2 thorpej 42 1.13 mrg #include <uvm/uvm_extern.h> 43 1.2 thorpej 44 1.14 thorpej #define _ALPHA_BUS_DMA_PRIVATE 45 1.25 dyoung #include <sys/bus.h> 46 1.2 thorpej 47 1.2 thorpej #include <alpha/common/sgmapvar.h> 48 1.2 thorpej 49 1.6 thorpej /* 50 1.6 thorpej * Some systems will prefetch the next page during a memory -> device DMA. 51 1.6 thorpej * This can cause machine checks if there is not a spill page after the 52 1.6 thorpej * last page of the DMA (thus avoiding hitting an invalid SGMAP PTE). 53 1.6 thorpej */ 54 1.11 thorpej vaddr_t alpha_sgmap_prefetch_spill_page_va; 55 1.6 thorpej bus_addr_t alpha_sgmap_prefetch_spill_page_pa; 56 1.6 thorpej 57 1.2 thorpej void 58 1.16 thorpej alpha_sgmap_init(bus_dma_tag_t t, struct alpha_sgmap *sgmap, const char *name, 59 1.16 thorpej bus_addr_t wbase, bus_addr_t sgvabase, bus_size_t sgvasize, size_t ptesize, 60 1.16 thorpej void *ptva, bus_size_t minptalign) 61 1.2 thorpej { 62 1.2 thorpej bus_dma_segment_t seg; 63 1.2 thorpej size_t ptsize; 64 1.2 thorpej int rseg; 65 1.2 thorpej 66 1.10 thorpej if (sgvasize & PGOFSET) { 67 1.10 thorpej printf("size botch for sgmap `%s'\n", name); 68 1.10 thorpej goto die; 69 1.10 thorpej } 70 1.2 thorpej 71 1.29 thorpej /* 72 1.29 thorpej * If we don't yet have a minimum SGVA alignment, default 73 1.29 thorpej * to the system page size. 74 1.29 thorpej */ 75 1.29 thorpej if (t->_sgmap_minalign < PAGE_SIZE) { 76 1.29 thorpej t->_sgmap_minalign = PAGE_SIZE; 77 1.29 thorpej } 78 1.29 thorpej 79 1.2 thorpej sgmap->aps_wbase = wbase; 80 1.2 thorpej sgmap->aps_sgvabase = sgvabase; 81 1.2 thorpej sgmap->aps_sgvasize = sgvasize; 82 1.2 thorpej 83 1.2 thorpej if (ptva != NULL) { 84 1.2 thorpej /* 85 1.2 thorpej * We already have a page table; this may be a system 86 1.2 thorpej * where the page table resides in bridge-resident SRAM. 87 1.2 thorpej */ 88 1.2 thorpej sgmap->aps_pt = ptva; 89 1.2 thorpej sgmap->aps_ptpa = 0; 90 1.2 thorpej } else { 91 1.2 thorpej /* 92 1.4 thorpej * Compute the page table size and allocate it. At minimum, 93 1.4 thorpej * this must be aligned to the page table size. However, 94 1.4 thorpej * some platforms have more strict alignment reqirements. 95 1.2 thorpej */ 96 1.20 thorpej ptsize = (sgvasize / PAGE_SIZE) * ptesize; 97 1.4 thorpej if (minptalign != 0) { 98 1.4 thorpej if (minptalign < ptsize) 99 1.4 thorpej minptalign = ptsize; 100 1.4 thorpej } else 101 1.4 thorpej minptalign = ptsize; 102 1.4 thorpej if (bus_dmamem_alloc(t, ptsize, minptalign, 0, &seg, 1, &rseg, 103 1.10 thorpej BUS_DMA_NOWAIT)) { 104 1.19 provos panic("unable to allocate page table for sgmap `%s'", 105 1.10 thorpej name); 106 1.10 thorpej goto die; 107 1.10 thorpej } 108 1.2 thorpej sgmap->aps_ptpa = seg.ds_addr; 109 1.23 christos sgmap->aps_pt = (void *)ALPHA_PHYS_TO_K0SEG(sgmap->aps_ptpa); 110 1.2 thorpej } 111 1.2 thorpej 112 1.2 thorpej /* 113 1.27 thorpej * Create the arena used to manage the virtual address 114 1.2 thorpej * space. 115 1.27 thorpej * 116 1.27 thorpej * XXX Consider using a quantum cache up to MAXPHYS+PAGE_SIZE 117 1.27 thorpej * XXX (extra page to handle the spill page). For now, we don't, 118 1.27 thorpej * XXX because we are using constrained allocations everywhere. 119 1.2 thorpej */ 120 1.27 thorpej sgmap->aps_arena = vmem_create(name, sgvabase, sgvasize, 121 1.27 thorpej PAGE_SIZE, /* quantum */ 122 1.27 thorpej NULL, /* importfn */ 123 1.27 thorpej NULL, /* releasefn */ 124 1.27 thorpej NULL, /* source */ 125 1.27 thorpej 0, /* qcache_max */ 126 1.27 thorpej VM_SLEEP, 127 1.27 thorpej IPL_VM); 128 1.27 thorpej KASSERT(sgmap->aps_arena != NULL); 129 1.6 thorpej 130 1.6 thorpej /* 131 1.6 thorpej * Allocate a spill page if that hasn't already been done. 132 1.6 thorpej */ 133 1.6 thorpej if (alpha_sgmap_prefetch_spill_page_va == 0) { 134 1.20 thorpej if (bus_dmamem_alloc(t, PAGE_SIZE, 0, 0, &seg, 1, &rseg, 135 1.10 thorpej BUS_DMA_NOWAIT)) { 136 1.10 thorpej printf("unable to allocate spill page for sgmap `%s'\n", 137 1.10 thorpej name); 138 1.10 thorpej goto die; 139 1.10 thorpej } 140 1.6 thorpej alpha_sgmap_prefetch_spill_page_pa = seg.ds_addr; 141 1.6 thorpej alpha_sgmap_prefetch_spill_page_va = 142 1.6 thorpej ALPHA_PHYS_TO_K0SEG(alpha_sgmap_prefetch_spill_page_pa); 143 1.23 christos memset((void *)alpha_sgmap_prefetch_spill_page_va, 0, 144 1.20 thorpej PAGE_SIZE); 145 1.6 thorpej } 146 1.10 thorpej 147 1.10 thorpej return; 148 1.10 thorpej die: 149 1.10 thorpej panic("alpha_sgmap_init"); 150 1.2 thorpej } 151 1.2 thorpej 152 1.2 thorpej int 153 1.16 thorpej alpha_sgmap_dmamap_create(bus_dma_tag_t t, bus_size_t size, int nsegments, 154 1.16 thorpej bus_size_t maxsegsz, bus_size_t boundary, int flags, bus_dmamap_t *dmamp) 155 1.14 thorpej { 156 1.14 thorpej bus_dmamap_t map; 157 1.14 thorpej int error; 158 1.14 thorpej 159 1.14 thorpej error = _bus_dmamap_create(t, size, nsegments, maxsegsz, 160 1.15 thorpej boundary, flags, &map); 161 1.14 thorpej if (error) 162 1.14 thorpej return (error); 163 1.14 thorpej 164 1.18 thorpej /* XXX BUS_DMA_ALLOCNOW */ 165 1.15 thorpej 166 1.15 thorpej if (error == 0) 167 1.15 thorpej *dmamp = map; 168 1.15 thorpej else 169 1.15 thorpej alpha_sgmap_dmamap_destroy(t, map); 170 1.14 thorpej 171 1.14 thorpej return (error); 172 1.14 thorpej } 173 1.14 thorpej 174 1.14 thorpej void 175 1.16 thorpej alpha_sgmap_dmamap_destroy(bus_dma_tag_t t, bus_dmamap_t map) 176 1.14 thorpej { 177 1.14 thorpej 178 1.18 thorpej KASSERT(map->dm_mapsize == 0); 179 1.14 thorpej 180 1.14 thorpej _bus_dmamap_destroy(t, map); 181 1.2 thorpej } 182