1 /* $OpenBSD: pmap.h,v 1.11 2001/12/05 00:11:51 millert Exp $ */ 2 /* $NetBSD: pmap.h,v 1.37 2000/11/19 03:16:35 thorpej Exp $ */ 3 4 /*- 5 * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 10 * NASA Ames Research Center and by Chris G. Demetriou. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the NetBSD 23 * Foundation, Inc. and its contributors. 24 * 4. Neither the name of The NetBSD Foundation nor the names of its 25 * contributors may be used to endorse or promote products derived 26 * from this software without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 29 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 31 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 32 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 38 * POSSIBILITY OF SUCH DAMAGE. 39 */ 40 41 /* 42 * Copyright (c) 1987 Carnegie-Mellon University 43 * Copyright (c) 1991, 1993 44 * The Regents of the University of California. All rights reserved. 45 * 46 * This code is derived from software contributed to Berkeley by 47 * the Systems Programming Group of the University of Utah Computer 48 * Science Department. 49 * 50 * Redistribution and use in source and binary forms, with or without 51 * modification, are permitted provided that the following conditions 52 * are met: 53 * 1. Redistributions of source code must retain the above copyright 54 * notice, this list of conditions and the following disclaimer. 55 * 2. Redistributions in binary form must reproduce the above copyright 56 * notice, this list of conditions and the following disclaimer in the 57 * documentation and/or other materials provided with the distribution. 58 * 3. All advertising materials mentioning features or use of this software 59 * must display the following acknowledgement: 60 * This product includes software developed by the University of 61 * California, Berkeley and its contributors. 62 * 4. Neither the name of the University nor the names of its contributors 63 * may be used to endorse or promote products derived from this software 64 * without specific prior written permission. 65 * 66 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 67 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 68 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 69 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 70 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 71 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 72 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 73 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 74 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 75 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 76 * SUCH DAMAGE. 77 * 78 * @(#)pmap.h 8.1 (Berkeley) 6/10/93 79 */ 80 81 #ifndef _PMAP_MACHINE_ 82 #define _PMAP_MACHINE_ 83 84 #include <sys/lock.h> 85 #include <sys/queue.h> 86 87 #include <machine/pte.h> 88 89 /* 90 * Machine-dependent virtual memory state. 91 * 92 * If we ever support processor numbers higher than 63, we'll have to 93 * rethink the CPU mask. 94 * 95 * Note pm_asn and pm_asngen are arrays allocated in pmap_create(). 96 * Their size is based on the PCS count from the HWRPB, and indexed 97 * by processor ID (from `whami'). 98 * 99 * The kernel pmap is a special case; it gets statically-allocated 100 * arrays which hold enough for ALPHA_MAXPROCS. 101 */ 102 struct pmap { 103 TAILQ_ENTRY(pmap) pm_list; /* list of all pmaps */ 104 pt_entry_t *pm_lev1map; /* level 1 map */ 105 int pm_count; /* pmap reference count */ 106 struct simplelock pm_slock; /* lock on pmap */ 107 struct pmap_statistics pm_stats; /* pmap statistics */ 108 long pm_nlev2; /* level 2 pt page count */ 109 long pm_nlev3; /* level 3 pt page count */ 110 unsigned int *pm_asn; /* address space number */ 111 unsigned long *pm_asngen; /* ASN generation number */ 112 unsigned long pm_cpus; /* mask of CPUs using pmap */ 113 unsigned long pm_needisync; /* mask of CPUs needing isync */ 114 }; 115 116 typedef struct pmap *pmap_t; 117 118 #define PMAP_ASN_RESERVED 0 /* reserved for Lev1map users */ 119 120 extern struct pmap kernel_pmap_store; 121 122 #define pmap_kernel() (&kernel_pmap_store) 123 124 /* 125 * For each vm_page_t, there is a list of all currently valid virtual 126 * mappings of that page. An entry is a pv_entry_t, the list is pv_table. 127 */ 128 typedef struct pv_entry { 129 LIST_ENTRY(pv_entry) pv_list; /* pv_entry list */ 130 struct pmap *pv_pmap; /* pmap where mapping lies */ 131 vaddr_t pv_va; /* virtual address for mapping */ 132 pt_entry_t *pv_pte; /* PTE that maps the VA */ 133 } *pv_entry_t; 134 135 /* 136 * The head of the list of pv_entry_t's, also contains page attributes. 137 */ 138 struct pv_head { 139 LIST_HEAD(, pv_entry) pvh_list; /* pv_entry list */ 140 struct simplelock pvh_slock; /* lock on this head */ 141 int pvh_attrs; /* page attributes */ 142 int pvh_usage; /* page usage */ 143 int pvh_refcnt; /* special use ref count */ 144 }; 145 146 /* pvh_attrs */ 147 #define PGA_MODIFIED 0x01 /* modified */ 148 #define PGA_REFERENCED 0x02 /* referenced */ 149 150 /* pvh_usage */ 151 #define PGU_NORMAL 0 /* free or normal use */ 152 #define PGU_PVENT 1 /* PV entries */ 153 #define PGU_L1PT 2 /* level 1 page table */ 154 #define PGU_L2PT 3 /* level 2 page table */ 155 #define PGU_L3PT 4 /* level 3 page table */ 156 157 #define PGU_ISPTPAGE(pgu) ((pgu) >= PGU_L1PT) 158 159 #define PGU_STRINGS \ 160 { \ 161 "normal", \ 162 "pvent", \ 163 "l1pt", \ 164 "l2pt", \ 165 "l3pt", \ 166 } 167 168 #ifdef _KERNEL 169 170 #ifndef _LKM 171 #if defined(NEW_SCC_DRIVER) 172 #if defined(DEC_KN8AE) 173 #define _PMAP_MAY_USE_PROM_CONSOLE 174 #endif 175 #else /* ! NEW_SCC_DRIVER */ 176 #if defined(DEC_3000_300) \ 177 || defined(DEC_3000_500) \ 178 || defined(DEC_KN8AE) /* XXX */ 179 #define _PMAP_MAY_USE_PROM_CONSOLE /* XXX */ 180 #endif /* XXX */ 181 #endif /* NEW_SCC_DRIVER */ 182 183 #if defined(MULTIPROCESSOR) 184 void pmap_tlb_shootdown(pmap_t, vaddr_t, pt_entry_t); 185 void pmap_do_tlb_shootdown(void); 186 void pmap_tlb_shootdown_q_drain(u_long, boolean_t); 187 #define PMAP_TLB_SHOOTDOWN(pm, va, pte) \ 188 pmap_tlb_shootdown((pm), (va), (pte)) 189 #else 190 #define PMAP_TLB_SHOOTDOWN(pm, va, pte) /* nothing */ 191 #endif /* MULTIPROCESSOR */ 192 #endif /* _LKM */ 193 194 #define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count) 195 #define pmap_wired_count(pmap) ((pmap)->pm_stats.wired_count) 196 #define pmap_update(pmap) /* nothing (yet) */ 197 198 extern pt_entry_t *VPT; /* Virtual Page Table */ 199 200 #define PMAP_STEAL_MEMORY /* enable pmap_steal_memory() */ 201 #define PMAP_GROWKERNEL /* enable pmap_growkernel() */ 202 203 /* 204 * Alternate mapping hooks for pool pages. Avoids thrashing the TLB. 205 */ 206 #define PMAP_MAP_POOLPAGE(pa) ALPHA_PHYS_TO_K0SEG((pa)) 207 #define PMAP_UNMAP_POOLPAGE(va) ALPHA_K0SEG_TO_PHYS((va)) 208 209 paddr_t vtophys(vaddr_t); 210 211 /* Machine-specific functions. */ 212 void pmap_bootstrap(paddr_t ptaddr, u_int maxasn, u_long ncpuids); 213 void pmap_emulate_reference(struct proc *p, vaddr_t v, 214 int user, int write); 215 #ifdef _PMAP_MAY_USE_PROM_CONSOLE 216 int pmap_uses_prom_console(void); 217 #endif 218 219 #define pmap_pte_pa(pte) (PG_PFNUM(*(pte)) << PGSHIFT) 220 #define pmap_pte_prot(pte) (*(pte) & PG_PROT) 221 #define pmap_pte_w(pte) (*(pte) & PG_WIRED) 222 #define pmap_pte_v(pte) (*(pte) & PG_V) 223 #define pmap_pte_pv(pte) (*(pte) & PG_PVLIST) 224 #define pmap_pte_asm(pte) (*(pte) & PG_ASM) 225 #define pmap_pte_exec(pte) (*(pte) & PG_EXEC) 226 227 #define pmap_pte_set_w(pte, v) \ 228 do { \ 229 if (v) \ 230 *(pte) |= PG_WIRED; \ 231 else \ 232 *(pte) &= ~PG_WIRED; \ 233 } while (0) 234 235 #define pmap_pte_w_chg(pte, nw) ((nw) ^ pmap_pte_w(pte)) 236 237 #define pmap_pte_set_prot(pte, np) \ 238 do { \ 239 *(pte) &= ~PG_PROT; \ 240 *(pte) |= (np); \ 241 } while (0) 242 243 #define pmap_pte_prot_chg(pte, np) ((np) ^ pmap_pte_prot(pte)) 244 245 static __inline pt_entry_t *pmap_l2pte(pmap_t, vaddr_t, pt_entry_t *); 246 static __inline pt_entry_t *pmap_l3pte(pmap_t, vaddr_t, pt_entry_t *); 247 248 #define pmap_l1pte(pmap, v) \ 249 (&(pmap)->pm_lev1map[l1pte_index((vaddr_t)(v))]) 250 251 static __inline pt_entry_t * 252 pmap_l2pte(pmap, v, l1pte) 253 pmap_t pmap; 254 vaddr_t v; 255 pt_entry_t *l1pte; 256 { 257 pt_entry_t *lev2map; 258 259 if (l1pte == NULL) { 260 l1pte = pmap_l1pte(pmap, v); 261 if (pmap_pte_v(l1pte) == 0) 262 return (NULL); 263 } 264 265 lev2map = (pt_entry_t *)ALPHA_PHYS_TO_K0SEG(pmap_pte_pa(l1pte)); 266 return (&lev2map[l2pte_index(v)]); 267 } 268 269 static __inline pt_entry_t * 270 pmap_l3pte(pmap, v, l2pte) 271 pmap_t pmap; 272 vaddr_t v; 273 pt_entry_t *l2pte; 274 { 275 pt_entry_t *l1pte, *lev2map, *lev3map; 276 277 if (l2pte == NULL) { 278 l1pte = pmap_l1pte(pmap, v); 279 if (pmap_pte_v(l1pte) == 0) 280 return (NULL); 281 282 lev2map = (pt_entry_t *)ALPHA_PHYS_TO_K0SEG(pmap_pte_pa(l1pte)); 283 l2pte = &lev2map[l2pte_index(v)]; 284 if (pmap_pte_v(l2pte) == 0) 285 return (NULL); 286 } 287 288 lev3map = (pt_entry_t *)ALPHA_PHYS_TO_K0SEG(pmap_pte_pa(l2pte)); 289 return (&lev3map[l3pte_index(v)]); 290 } 291 292 /* 293 * Macros for locking pmap structures. 294 * 295 * Note that we if we access the kernel pmap in interrupt context, it 296 * is only to update statistics. Since stats are updated using atomic 297 * operations, locking the kernel pmap is not necessary. Therefore, 298 * it is not necessary to block interrupts when locking pmap strucutres. 299 */ 300 #define PMAP_LOCK(pmap) simple_lock(&(pmap)->pm_slock) 301 #define PMAP_UNLOCK(pmap) simple_unlock(&(pmap)->pm_slock) 302 303 /* 304 * Macro for processing deferred I-stream synchronization. 305 * 306 * The pmap module may defer syncing the user I-stream until the 307 * return to userspace, since the IMB PALcode op can be quite 308 * expensive. Since user instructions won't be executed until 309 * the return to userspace, this can be deferred until userret(). 310 */ 311 #define PMAP_USERRET(pmap) \ 312 do { \ 313 u_long cpu_mask = (1UL << cpu_number()); \ 314 \ 315 if ((pmap)->pm_needisync & cpu_mask) { \ 316 atomic_clearbits_ulong(&(pmap)->pm_needisync, \ 317 cpu_mask); \ 318 alpha_pal_imb(); \ 319 } \ 320 } while (0) 321 322 #endif /* _KERNEL */ 323 324 #endif /* _PMAP_MACHINE_ */ 325