1 /* $NetBSD: pmap_pgmmu.h,v 1.1 2026/07/19 01:48:24 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 2025, 2026 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe. 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 #ifndef _PG68K_PMAP_PGMMU_H_ 33 #define _PG68K_PMAP_PGMMU_H_ 34 35 #if defined(_KERNEL) 36 37 #if !defined(_MODULE) 38 39 #include <sys/queue.h> 40 41 #include <hb68k/pg68k/pgmmu.h> 42 43 #include <sys/kcore.h> 44 #include <m68k/kcore.h> 45 46 /* 47 * Description of a pmap's MMU context. In addition to the context 48 * number, we also keep track of how many mappings we have in each 49 * PMEG we have allocated so we know when we can free them back. 50 * 51 * The number of these context structures is limited to the total 52 * number of contexts the MMU can handle. 53 */ 54 struct pmap_context { 55 unsigned int ctx_num; 56 union { 57 struct pmap_context *ctx_next; 58 uint8_t ctx_segrefs[PGMMU_NUM_SEGS]; 59 }; 60 }; 61 62 /* 63 * This MMU is used in relatively resource-constrained machines, 64 * so we aim to keep this structure as small as possible. 65 */ 66 struct pmap { 67 TAILQ_ENTRY(pmap) pm_list; /* link on global list */ 68 struct pmap_context *pm_context; /* current context */ 69 uint16_t pm_refcnt; /* reference count */ 70 uint16_t pm_busy; /* "busy" (currently loaded in 71 to MMU, or involved in 72 some pmap operation) count */ 73 /* 74 * N.B. we also used wired_count internally to identify 75 * potential victims of resource theft. 76 */ 77 struct pmap_statistics pm_stats; /* statistics */ 78 }; 79 80 /* 81 * One entry per P->V mapping of a managed page. 82 * 83 * N.B. We want to keep this structure's size to be a multiple of 84 * 8; we want to align them to 8 bytes in order to be able to use 85 * the lower 3 bits of the pv_entry list head for page attributes. 86 */ 87 struct pv_entry { 88 /* 0*/ struct pv_entry *pv_next; /* link on page list */ 89 /* 4*/ pmap_t pv_pmap; /* pmap that contains mapping */ 90 /* 8*/ vaddr_t pv_vf; /* virtual address + flags */ 91 /*12*/ unsigned int pv_pmeg; /* PMEG that maps this VA */ 92 /*16*/ 93 }; 94 95 /* Upper bits of pv_vf contain the virtual address */ 96 #define PV_VA(pv) ((pv)->pv_vf & ~PAGE_MASK) 97 98 /* 99 * pmap-specific data store in the vm_page structure. 100 * 101 * We keep the Mod/Ref attrs in the lower 2 bits of the list head 102 * pointer. This is possible because both the Mod and Ref bits are 103 * adjacent; we just need to shift them down 24 bit positions. 104 * 105 * Assumes that PV entries will be 4-byte aligned, but the allocator 106 * guarantees this for us. 107 */ 108 #define __HAVE_VM_PAGE_MD 109 struct vm_page_md { 110 uintptr_t pvh_listx; /* pv_entry list + attrs */ 111 }; 112 113 #define PVH_MR_SHIFT 24 114 #define PVH_MR_MASK __BITS(0,1) 115 #define PVH_ATTR_MASK PVH_MR_MASK 116 #define PVH_PV_MASK (~PVH_ATTR_MASK) 117 118 #define VM_MDPAGE_INIT(pg) \ 119 do { \ 120 (pg)->mdpage.pvh_listx = 0; \ 121 } while (/*CONSTCOND*/0) 122 123 #define VM_MDPAGE_PVS(pg) \ 124 ((struct pv_entry *)((pg)->mdpage.pvh_listx & (uintptr_t)PVH_PV_MASK)) 125 126 #define VM_MDPAGE_HEAD_PVP(pg) \ 127 ((struct pv_entry **)&(pg)->mdpage.pvh_listx) 128 129 #define VM_MDPAGE_SETPVP(pvp, pv) \ 130 do { \ 131 /* \ 132 * The page attributes are in the lower two bits of \ 133 * the first PV pointer. Rather than comparing the \ 134 * address and branching, we just always preserve what \ 135 * might be there (either the attribute bits or zero \ 136 * bits). \ 137 */ \ 138 *(pvp) = (struct pv_entry *) \ 139 ((uintptr_t)(pv) | \ 140 (((uintptr_t)(*(pvp))) & (uintptr_t)PVH_ATTR_MASK));\ 141 } while (/*CONSTCOND*/0) 142 143 #define VM_MDPAGE_MR(pg) \ 144 (((pg)->mdpage.pvh_listx & PVH_MR_MASK) << PVH_MR_SHIFT) 145 146 #define VM_MDPAGE_ADD_MR(pg, a) \ 147 do { \ 148 (pg)->mdpage.pvh_listx |= \ 149 ((a) >> PVH_MR_SHIFT) & PVH_MR_MASK; \ 150 } while (/*CONSTCOND*/0) 151 152 #define VM_MDPAGE_SET_MR(pg, v) \ 153 do { \ 154 (pg)->mdpage.pvh_listx = \ 155 ((pg)->mdpage.pvh_listx & ~PVH_MR_MASK) | \ 156 (((v) >> PVH_MR_SHIFT) & PVH_MR_MASK); \ 157 } while (/*CONSTCOND*/0) 158 159 #define pmap_copy(dp, sp, da, l, sa) __nothing 160 161 #define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count) 162 #define pmap_wired_count(pmap) ((pmap)->pm_stats.wired_count) 163 164 /* 165 * pmap_bootstrap1() is called before the MMU is turned on (well, for 166 * this MMU, it's always on...) 167 * pmap_bootstrap2() is called after. 168 */ 169 paddr_t pmap_bootstrap1(paddr_t/*nextpa*/, paddr_t/*reloff*/); 170 void * pmap_bootstrap2(void); 171 172 /* 173 * Variant of pmap_extract() that returns additional information about 174 * the mapping. Used by bus_dma(9). 175 */ 176 bool pmap_extract_info(pmap_t, vaddr_t, paddr_t *, int *); 177 178 /* 179 * pmap hook for trap()'s page fault handler. We don't need to 180 * do anything special, so it just goes to uvm_fault(). 181 */ 182 #define pmap_fault(m, v, t) uvm_fault((m), (v), (t)) 183 184 /* 185 * Functions to determine if a VA/PA range is a static mapping created 186 * by pmap_bootstrap1(), for the benefit of bus_space(9). 187 */ 188 bool pmap_pa_has_static_mapping(paddr_t, size_t, vm_prot_t, 189 vaddr_t *, int *); 190 bool pmap_va_is_static_mapping(vaddr_t, size_t); 191 192 /* Kernel debugger support functions. */ 193 struct pmap_db_write_text_context { 194 unsigned int pmeidx; 195 pm_entry_t opme; 196 }; 197 bool pmap_db_write_text_enter(vaddr_t, struct pmap_db_write_text_context *); 198 void pmap_db_write_text_exit(struct pmap_db_write_text_context *); 199 200 /* 201 * Functions exported for compatibility with the Hibler pmap, where 202 * these are needed by other shared m68k code. 203 * 204 * XXX Clean this up eventually. 205 */ 206 207 paddr_t vtophys(vaddr_t); 208 209 extern char * vmmap; 210 extern void * msgbufaddr; 211 212 /* Kernel crash dump support. */ 213 phys_ram_seg_t * pmap_init_kcore_hdr(cpu_kcore_hdr_t *); 214 215 /* 216 * pmap_bootstrap1() may need to relocate global references, and perform 217 * VA <-> PA conversions. We don't need to do anything for these accesses 218 * on this MMU, because the MMU is always on. 219 */ 220 #undef PMAP_BOOTSTRAP_RELOC_GLOB 221 #define PMAP_BOOTSTRAP_RELOC_GLOB(va) (va) 222 223 #undef PMAP_BOOTSTRAP_RELOC_PA 224 #define PMAP_BOOTSTRAP_RELOC_PA(pa) (pa) 225 226 #undef PMAP_BOOTSTRAP_VA_TO_PA 227 #define PMAP_BOOTSTRAP_VA_TO_PA(va) (va) 228 229 #undef PMAP_BOOTSTRAP_PA_TO_VA 230 #define PMAP_BOOTSTRAP_PA_TO_VA(pa) (pa) 231 232 #endif /* _MODULE */ 233 234 /* 235 * Some pmap(9) API macros should be defined here for module(7). 236 * Luckily, all m68k pmap implementations behave this way. (see PR/54869) 237 */ 238 #define pmap_update(pmap) __nothing 239 240 #endif /* _KERNEL */ 241 242 #endif /* _PG68K_PMAP_PGMMU_H_ */ 243