Home | History | Annotate | Line # | Download | only in pmap
      1 /*	$NetBSD: pmap_devmap.c,v 1.2 2023/04/27 06:23:31 skrll Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2022 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Nick Hudson
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 __RCSID("$NetBSD: pmap_devmap.c,v 1.2 2023/04/27 06:23:31 skrll Exp $");
     34 
     35 
     36 #include <sys/param.h>
     37 #include <sys/types.h>
     38 
     39 #include <uvm/uvm.h>
     40 #include <uvm/uvm_extern.h>
     41 #include <uvm/pmap/pmap_devmap.h>
     42 
     43 
     44 static const struct pmap_devmap *pd_table;
     45 static vaddr_t pd_root;
     46 
     47 bool pmap_devmap_bootstrap_done = false;
     48 
     49 bool
     50 pmap_devmap_bootstrapped_p(void)
     51 {
     52 	return pmap_devmap_bootstrap_done;
     53 }
     54 
     55 
     56 vaddr_t
     57 pmap_devmap_root(void)
     58 {
     59 	return pd_root;
     60 }
     61 
     62 /*
     63  * Register the devmap table.  This is provided in case early console
     64  * initialization needs to register mappings created by bootstrap code
     65  * before pmap_devmap_bootstrap() is called.
     66  */
     67 void
     68 pmap_devmap_register(const struct pmap_devmap *table)
     69 {
     70 
     71 	pd_table = table;
     72 }
     73 
     74 /*
     75  * Map all of the static regions in the devmap table, and remember
     76  * the devmap table so other parts of the kernel can look up entries
     77  * later.
     78  */
     79 void
     80 pmap_devmap_bootstrap(vaddr_t root, const struct pmap_devmap *table)
     81 {
     82 	UVMHIST_FUNC(__func__);
     83 	UVMHIST_CALLARGS(maphist, "(root=%#jx, table=%p)", root,
     84 	    (uintptr_t)table, 0, 0);
     85 
     86 	bool done = false;
     87 
     88 	pd_root = root;
     89 	pd_table = table;
     90 
     91 	for (size_t i = 0; table[i].pd_size != 0; i++) {
     92 		const struct pmap_devmap * const pdp = &table[i];
     93 		const vaddr_t vmax = __type_max_u(vaddr_t);
     94 		const paddr_t pmax = __type_max_u(paddr_t);
     95 
     96 		KASSERT(pdp->pd_size != 0);
     97 		KASSERTMSG(vmax - pdp->pd_va >= pdp->pd_size - 1,
     98 		    "va %" PRIxVADDR " sz %" PRIxPSIZE, pdp->pd_va,
     99 		    pdp->pd_size);
    100 		KASSERTMSG(pmax - pdp->pd_pa >= pdp->pd_size - 1,
    101 		    "pa %" PRIxPADDR " sz %" PRIxPSIZE, pdp->pd_pa,
    102 		    pdp->pd_size);
    103 		UVMHIST_LOG(maphist,
    104 		    "pa %#jx -> %#jx @ va %#jx -> %#jx",
    105 		    pdp->pd_pa, pdp->pd_pa + pdp->pd_size - 1,
    106 		    pdp->pd_va, pdp->pd_va + pdp->pd_size - 1);
    107 
    108 		pmap_kenter_range(pdp->pd_va, pdp->pd_pa, pdp->pd_size,
    109 		    pdp->pd_prot, pdp->pd_flags);
    110 		done = true;
    111 	}
    112 	if (done)
    113 		pmap_devmap_bootstrap_done = true;
    114 }
    115 
    116 /*
    117  * Find the table entry that fully covers the physical address
    118  * range [pa, pa + size)
    119  */
    120 const struct pmap_devmap *
    121 pmap_devmap_find_pa(paddr_t pa, psize_t size)
    122 {
    123 	if (pd_table == NULL)
    124 		return NULL;
    125 
    126 	for (size_t i = 0; pd_table[i].pd_size != 0; i++) {
    127 		const paddr_t pd_pa = pd_table[i].pd_pa;
    128 		const psize_t pd_sz = pd_table[i].pd_size;
    129 
    130 		if (pa < pd_pa)
    131 			continue;
    132 
    133 		const psize_t pdiff = pa - pd_pa;
    134 
    135 		if (pd_sz < pdiff)
    136 			continue;
    137 
    138 		if (pd_sz - pdiff >= size)
    139 			return &pd_table[i];
    140 	}
    141 
    142 	return NULL;
    143 }
    144 
    145 /*
    146  * Find the table entry that fully covers the virtual address
    147  * range [va, va + size)
    148  */
    149 const struct pmap_devmap *
    150 pmap_devmap_find_va(vaddr_t va, vsize_t size)
    151 {
    152 	if (pd_table == NULL)
    153 		return NULL;
    154 
    155 	for (size_t i = 0; pd_table[i].pd_size != 0; i++) {
    156 		const vaddr_t pd_va = pd_table[i].pd_va;
    157 		const vsize_t pd_sz = pd_table[i].pd_size;
    158 
    159 		if (va < pd_va)
    160 			continue;
    161 
    162 		const vsize_t vdiff = va - pd_va;
    163 
    164 		if (pd_sz < vdiff)
    165 			continue;
    166 
    167 		if (pd_sz - vdiff >= size)
    168 			return &pd_table[i];
    169 
    170 	}
    171 
    172 	return NULL;
    173 }
    174