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