xref: /netbsd-src/sys/uvm/pmap/pmap_devmap.c (revision 6fc09aadfb56796c120e0903b134b640935db632)
1*6fc09aadSskrll /*	$NetBSD: pmap_devmap.c,v 1.2 2023/04/27 06:23:31 skrll Exp $	*/
26d5cf357Sskrll 
36d5cf357Sskrll /*-
46d5cf357Sskrll  * Copyright (c) 2022 The NetBSD Foundation, Inc.
56d5cf357Sskrll  * All rights reserved.
66d5cf357Sskrll  *
76d5cf357Sskrll  * This code is derived from software contributed to The NetBSD Foundation
86d5cf357Sskrll  * by Nick Hudson
96d5cf357Sskrll  *
106d5cf357Sskrll  * Redistribution and use in source and binary forms, with or without
116d5cf357Sskrll  * modification, are permitted provided that the following conditions
126d5cf357Sskrll  * are met:
136d5cf357Sskrll  * 1. Redistributions of source code must retain the above copyright
146d5cf357Sskrll  *    notice, this list of conditions and the following disclaimer.
156d5cf357Sskrll  * 2. Redistributions in binary form must reproduce the above copyright
166d5cf357Sskrll  *    notice, this list of conditions and the following disclaimer in the
176d5cf357Sskrll  *    documentation and/or other materials provided with the distribution.
186d5cf357Sskrll  *
196d5cf357Sskrll  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
206d5cf357Sskrll  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
216d5cf357Sskrll  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
226d5cf357Sskrll  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
236d5cf357Sskrll  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
246d5cf357Sskrll  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
256d5cf357Sskrll  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
266d5cf357Sskrll  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
276d5cf357Sskrll  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
286d5cf357Sskrll  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
296d5cf357Sskrll  * POSSIBILITY OF SUCH DAMAGE.
306d5cf357Sskrll  */
316d5cf357Sskrll 
326d5cf357Sskrll #include <sys/cdefs.h>
33*6fc09aadSskrll __RCSID("$NetBSD: pmap_devmap.c,v 1.2 2023/04/27 06:23:31 skrll Exp $");
346d5cf357Sskrll 
356d5cf357Sskrll 
366d5cf357Sskrll #include <sys/param.h>
376d5cf357Sskrll #include <sys/types.h>
386d5cf357Sskrll 
396d5cf357Sskrll #include <uvm/uvm.h>
406d5cf357Sskrll #include <uvm/uvm_extern.h>
416d5cf357Sskrll #include <uvm/pmap/pmap_devmap.h>
426d5cf357Sskrll 
436d5cf357Sskrll 
446d5cf357Sskrll static const struct pmap_devmap *pd_table;
456d5cf357Sskrll static vaddr_t pd_root;
466d5cf357Sskrll 
476d5cf357Sskrll bool pmap_devmap_bootstrap_done = false;
486d5cf357Sskrll 
496d5cf357Sskrll bool
pmap_devmap_bootstrapped_p(void)506d5cf357Sskrll pmap_devmap_bootstrapped_p(void)
516d5cf357Sskrll {
526d5cf357Sskrll 	return pmap_devmap_bootstrap_done;
536d5cf357Sskrll }
546d5cf357Sskrll 
556d5cf357Sskrll 
566d5cf357Sskrll vaddr_t
pmap_devmap_root(void)576d5cf357Sskrll pmap_devmap_root(void)
586d5cf357Sskrll {
596d5cf357Sskrll 	return pd_root;
606d5cf357Sskrll }
616d5cf357Sskrll 
626d5cf357Sskrll /*
636d5cf357Sskrll  * Register the devmap table.  This is provided in case early console
646d5cf357Sskrll  * initialization needs to register mappings created by bootstrap code
656d5cf357Sskrll  * before pmap_devmap_bootstrap() is called.
666d5cf357Sskrll  */
676d5cf357Sskrll void
pmap_devmap_register(const struct pmap_devmap * table)686d5cf357Sskrll pmap_devmap_register(const struct pmap_devmap *table)
696d5cf357Sskrll {
706d5cf357Sskrll 
716d5cf357Sskrll 	pd_table = table;
726d5cf357Sskrll }
736d5cf357Sskrll 
746d5cf357Sskrll /*
756d5cf357Sskrll  * Map all of the static regions in the devmap table, and remember
766d5cf357Sskrll  * the devmap table so other parts of the kernel can look up entries
776d5cf357Sskrll  * later.
786d5cf357Sskrll  */
796d5cf357Sskrll void
pmap_devmap_bootstrap(vaddr_t root,const struct pmap_devmap * table)806d5cf357Sskrll pmap_devmap_bootstrap(vaddr_t root, const struct pmap_devmap *table)
816d5cf357Sskrll {
826d5cf357Sskrll 	UVMHIST_FUNC(__func__);
836d5cf357Sskrll 	UVMHIST_CALLARGS(maphist, "(root=%#jx, table=%p)", root,
846d5cf357Sskrll 	    (uintptr_t)table, 0, 0);
856d5cf357Sskrll 
866d5cf357Sskrll 	bool done = false;
876d5cf357Sskrll 
886d5cf357Sskrll 	pd_root = root;
896d5cf357Sskrll 	pd_table = table;
906d5cf357Sskrll 
916d5cf357Sskrll 	for (size_t i = 0; table[i].pd_size != 0; i++) {
926d5cf357Sskrll 		const struct pmap_devmap * const pdp = &table[i];
936d5cf357Sskrll 		const vaddr_t vmax = __type_max_u(vaddr_t);
94*6fc09aadSskrll 		const paddr_t pmax = __type_max_u(paddr_t);
956d5cf357Sskrll 
966d5cf357Sskrll 		KASSERT(pdp->pd_size != 0);
976d5cf357Sskrll 		KASSERTMSG(vmax - pdp->pd_va >= pdp->pd_size - 1,
986d5cf357Sskrll 		    "va %" PRIxVADDR " sz %" PRIxPSIZE, pdp->pd_va,
996d5cf357Sskrll 		    pdp->pd_size);
1006d5cf357Sskrll 		KASSERTMSG(pmax - pdp->pd_pa >= pdp->pd_size - 1,
1016d5cf357Sskrll 		    "pa %" PRIxPADDR " sz %" PRIxPSIZE, pdp->pd_pa,
1026d5cf357Sskrll 		    pdp->pd_size);
1036d5cf357Sskrll 		UVMHIST_LOG(maphist,
1046d5cf357Sskrll 		    "pa %#jx -> %#jx @ va %#jx -> %#jx",
1056d5cf357Sskrll 		    pdp->pd_pa, pdp->pd_pa + pdp->pd_size - 1,
1066d5cf357Sskrll 		    pdp->pd_va, pdp->pd_va + pdp->pd_size - 1);
1076d5cf357Sskrll 
1086d5cf357Sskrll 		pmap_kenter_range(pdp->pd_va, pdp->pd_pa, pdp->pd_size,
1096d5cf357Sskrll 		    pdp->pd_prot, pdp->pd_flags);
1106d5cf357Sskrll 		done = true;
1116d5cf357Sskrll 	}
1126d5cf357Sskrll 	if (done)
1136d5cf357Sskrll 		pmap_devmap_bootstrap_done = true;
1146d5cf357Sskrll }
1156d5cf357Sskrll 
1166d5cf357Sskrll /*
1176d5cf357Sskrll  * Find the table entry that fully covers the physical address
1186d5cf357Sskrll  * range [pa, pa + size)
1196d5cf357Sskrll  */
1206d5cf357Sskrll const struct pmap_devmap *
pmap_devmap_find_pa(paddr_t pa,psize_t size)1216d5cf357Sskrll pmap_devmap_find_pa(paddr_t pa, psize_t size)
1226d5cf357Sskrll {
1236d5cf357Sskrll 	if (pd_table == NULL)
1246d5cf357Sskrll 		return NULL;
1256d5cf357Sskrll 
1266d5cf357Sskrll 	for (size_t i = 0; pd_table[i].pd_size != 0; i++) {
1276d5cf357Sskrll 		const paddr_t pd_pa = pd_table[i].pd_pa;
1286d5cf357Sskrll 		const psize_t pd_sz = pd_table[i].pd_size;
1296d5cf357Sskrll 
1306d5cf357Sskrll 		if (pa < pd_pa)
1316d5cf357Sskrll 			continue;
1326d5cf357Sskrll 
1336d5cf357Sskrll 		const psize_t pdiff = pa - pd_pa;
1346d5cf357Sskrll 
1356d5cf357Sskrll 		if (pd_sz < pdiff)
1366d5cf357Sskrll 			continue;
1376d5cf357Sskrll 
1386d5cf357Sskrll 		if (pd_sz - pdiff >= size)
1396d5cf357Sskrll 			return &pd_table[i];
1406d5cf357Sskrll 	}
1416d5cf357Sskrll 
1426d5cf357Sskrll 	return NULL;
1436d5cf357Sskrll }
1446d5cf357Sskrll 
1456d5cf357Sskrll /*
1466d5cf357Sskrll  * Find the table entry that fully covers the virtual address
1476d5cf357Sskrll  * range [va, va + size)
1486d5cf357Sskrll  */
1496d5cf357Sskrll const struct pmap_devmap *
pmap_devmap_find_va(vaddr_t va,vsize_t size)1506d5cf357Sskrll pmap_devmap_find_va(vaddr_t va, vsize_t size)
1516d5cf357Sskrll {
1526d5cf357Sskrll 	if (pd_table == NULL)
1536d5cf357Sskrll 		return NULL;
1546d5cf357Sskrll 
1556d5cf357Sskrll 	for (size_t i = 0; pd_table[i].pd_size != 0; i++) {
1566d5cf357Sskrll 		const vaddr_t pd_va = pd_table[i].pd_va;
1576d5cf357Sskrll 		const vsize_t pd_sz = pd_table[i].pd_size;
1586d5cf357Sskrll 
1596d5cf357Sskrll 		if (va < pd_va)
1606d5cf357Sskrll 			continue;
1616d5cf357Sskrll 
1626d5cf357Sskrll 		const vsize_t vdiff = va - pd_va;
1636d5cf357Sskrll 
1646d5cf357Sskrll 		if (pd_sz < vdiff)
1656d5cf357Sskrll 			continue;
1666d5cf357Sskrll 
1676d5cf357Sskrll 		if (pd_sz - vdiff >= size)
1686d5cf357Sskrll 			return &pd_table[i];
1696d5cf357Sskrll 
1706d5cf357Sskrll 	}
1716d5cf357Sskrll 
1726d5cf357Sskrll 	return NULL;
1736d5cf357Sskrll }
174