1 /* $NetBSD: pmap_sunmmu.c,v 1.5 2026/09/01 18:01:25 andvar Exp $ */ 2 3 /*- 4 * Copyright (c) 1996 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Adam Glass, Gordon W. Ross, and Matthew Fredette. 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 /* 33 * Unified pmap module for 68010 (Sun 2) and 68020 (Sun 3) systems with 34 * the Sun MMU. Origins: 35 * 36 * sys/arch/sun3/sun3/pmap.c 1.189 37 * sys/arch/sun2/sun2/pmap.c 1.62 38 * 39 * ...smooshed together by thorpej, July 2026. 40 * 41 * Some notes: 42 * 43 * The Sun MMU has a 2-level translation scheme; the level-1 map is called 44 * the Segment Map and the level-2 map is called the Page Map. The Segment 45 * Map is broken up into 8 contexts, and each context provides the root for 46 * an address space. 47 * 48 * The Sun 2 MMU has separate user vs. kernel context registers. This 49 * pmap statically assigns context 0 to the kernel. 50 * 51 * The Sun 3 MMU, on the other hand, has only a single context register, 52 * and thus the kernel must be mapped into all contexts. 53 * 54 * In both cases, context 0 is also assigned as the "empty context", devoid 55 * of user-accessible mappings. This is the context that pmaps are assigned 56 * when they are brand new or when they have been evicted from the MMU. 57 * 58 * The context itself selects a window in the Segment Map. The Segment Map 59 * is comprised of single byte entries that index a Page Map Entry Group 60 * (PMEG). Each PMEG is a group of 16 Page Map entries. 61 * 62 * Sun 2: 63 * 512 Segment Map entries * 64 * 16 entries per PMEG * 65 * 2K page size = (32KB segments) 66 * 16MB virtual address space per context (i.e. the 68010 limit) 67 * (kernel gets its own 16MB context) 68 * 69 * Sun 3: 70 * 2048 Segment Map entries * 71 * 16 entries per PMEG * 72 * 8K page size = (128KB segments) 73 * 256MB virtual address space per context 74 * (kernel lives in the upper 32MB of each context) 75 * 76 * As you might guess, both contexts and PMEGs are in short supply and 77 * heavy demand. PMEGs allocated to the kernel are "static" in the sense 78 * that they can't be stolen from it. PMEGs allocated to a particular 79 * segment of a pmap's virtual space will by fought over by the other 80 * pmaps. 81 * 82 * The same is true for contexts. With one context set aside as the 83 * "empty" contexts, there are 7 available for user processes. If you 84 * have more than 7 user processes running at any given time, then some 85 * of those processes are getting evicted from the MMU entirely. 86 * 87 * Ultimately, the resources must be shared. 88 * 89 * On the Sun 3, we also have to worry about cache management. 90 * - All Sun 3 cache implementations are write-back. 91 * - Cache flushes must be performed *before* removing translations 92 * because the cache is virtually-addressed. 93 * 94 * Other desired attributes of this implementation: 95 * - PMEGs are aren't needed by a pmap remain in the MMU and 96 * are lazily-reclaimed. 97 * - Quick context switches between pmaps 98 * - Something not applicable on a given platform are optimized 99 * out a compile-time. 100 */ 101 102 /* 103 * [Historical notes here; it's unclear if Project1 is necessary, 104 * since it that idea predates NetBSD's kthread(9) interface.] 105 * 106 * Project1: Use a "null" context for processes that have not 107 * touched any user-space address recently. This is efficient 108 * for things that stay in the kernel for a while, waking up 109 * to handle some I/O then going back to sleep (i.e. nfsd). 110 * If and when such a process returns to user-mode, it will 111 * fault and be given a real context at that time. 112 * 113 * This also lets context switch be fast, because all we need 114 * to do there for the MMU is slam the context register. 115 * 116 * Project2: Use a private pool of PV elements. This pool can be 117 * fixed size because the total mapped virtual space supported by 118 * the MMU H/W (and this pmap) is fixed for all time. 119 */ 120 121 #include <sys/cdefs.h> 122 __KERNEL_RCSID(0, "$NetBSD: pmap_sunmmu.c,v 1.5 2026/09/01 18:01:25 andvar Exp $"); 123 124 #include "opt_ddb.h" 125 #include "opt_kgdb.h" 126 #include "opt_pmap_debug.h" 127 128 #include <sys/param.h> 129 #include <sys/systm.h> 130 #include <sys/proc.h> 131 #include <sys/kmem.h> 132 #include <sys/pool.h> 133 #include <sys/queue.h> 134 #include <sys/kcore.h> 135 #include <sys/atomic.h> 136 137 #include <uvm/uvm.h> 138 139 #include <machine/cpu.h> 140 #include <machine/dvma.h> 141 #include <machine/fcode.h> 142 #include <machine/idprom.h> 143 #include <machine/kcore.h> 144 #include <machine/promlib.h> 145 #include <machine/pmap.h> 146 #include <machine/pte.h> 147 #include <machine/vmparam.h> 148 #include <m68k/cacheops.h> 149 #include <m68k/seglist.h> 150 151 #ifdef DDB 152 #include <ddb/db_output.h> 153 #else 154 #define db_printf printf 155 #endif 156 157 #ifdef __mc68010__ 158 #define IS_SUN2 1 159 #define IS_SUN3 0 160 #else 161 #define IS_SUN2 0 162 #define IS_SUN3 1 163 #endif /* __mc68010__ */ 164 165 #if IS_SUN2 166 167 #include <sun2/sun2/control.h> 168 #include <sun2/sun2/machdep.h> 169 170 #define sun_round_seg(va) sun2_round_seg(va) 171 #define sun_trunc_seg(va) sun2_trunc_seg(va) 172 173 /* Type bits in a "pseudo" physical address. (XXX: pmap.h?) */ 174 #define PMAP_TYPE PMAP_MBIO 175 176 /* User segments are all of them. */ 177 #define NUSEG (NSEGMAP) 178 179 /* 180 * Only "main memory" pages are registered in the pv_lists. 181 * This macro is used to determine if a given pte refers to 182 * "main memory" or not. One slight hack here deserves more 183 * explanation: On the Sun-2, the bwtwo and zs1 appear 184 * as PG_OBMEM devices at 0x00700000 and 0x00780000, 185 * respectively. We do not want to consider these as 186 * "main memory" so the macro below treats obmem addresses 187 * >= 0x00700000 as device addresses. NB: this means for now, 188 * you can't have a headless Sun-2 with 8MB of main memory. 189 */ 190 #define IS_MAIN_MEM(pte) (((pte) & PG_TYPE) == 0 && PG_PA(pte) < 0x00700000) 191 192 /* Does this (pseudo) PA represent device space? */ 193 #define PA_IS_DEV(pa) (((pa) & PMAP_TYPE) != 0 || (pa) >= 0x00700000) 194 195 /* 196 * No virtually-address cache aliases to worry about on Sun-2. 197 */ 198 #define BADALIAS(a1, a2) (0) 199 200 #else /* IS_SUN3 */ 201 202 #include <sun3/sun3/control.h> 203 #include <sun3/sun3/machdep.h> 204 #include <sun3/sun3/obmem.h> 205 206 #define sun_round_seg(va) sun3_round_seg(va) 207 #define sun_trunc_seg(va) sun3_trunc_seg(va) 208 209 /* Type bits in a "pseudo" physical address. (XXX: pmap.h?) */ 210 #define PMAP_TYPE PMAP_VME32 211 212 /* User segments from 0 to KERNBASE */ 213 #define NUSEG (KERNBASE3 / NBSG) 214 /* The remainder are kernel segments. */ 215 #define NKSEG (NSEGMAP - NUSEG) 216 217 /* 218 * Only "main memory" pages are registered in the pv_lists. 219 * This macro is used to determine if a given pte refers to 220 * "main memory" or not. One slight hack here deserves more 221 * explanation: The Sun frame buffers all appear as PG_OBMEM 222 * devices but way up near the end of the address space. 223 * We do not want to consider these as "main memory" so the 224 * macro below treats the high bits of the PFN as type bits. 225 * 226 * Note that on the 3/60 only 16 bits of PFN are stored in the 227 * MMU and the top 3 bits read back as zero. This means a 228 * translation entered into the mmu for physical address 229 * 0xFF000000 will look like 0x1F000000 after one reads back 230 * the pte and converts the PFN to a physical address. 231 */ 232 #define MEM_BITS (PG_TYPE | PA_PGNUM(0xF8000000)) 233 #define IS_MAIN_MEM(pte) (((pte) & MEM_BITS) == 0) 234 235 /* Does this (pseudo) PA represent device space? */ 236 #define PA_DEV_MASK (0xF8000000 | PMAP_TYPE) 237 #define PA_IS_DEV(pa) ((pa) & PA_DEV_MASK) 238 239 /* 240 * Is there a Virtually Addressed Cache (VAC) alias problem 241 * if one page is mapped at both a1 and a2? 242 */ 243 #define BADALIAS(a1, a2) (((int)(a1) ^ (int)(a2)) & SEGOFSET) 244 245 #endif /* IS_SUN2 */ 246 247 /* Verify this correspondence between definitions. */ 248 #if (PMAP_OBIO << PG_MOD_SHIFT) != PGT_OBIO 249 #error "PMAP_XXX definitions don't match pte.h!" 250 #endif 251 252 /* 253 * Local convenience macros 254 */ 255 256 #define DVMA_MAP_END (DVMA_MAP_BASE + DVMA_MAP_AVAIL) 257 #define VA_SEGNUM(x) ((u_int)(x) >> SEGSHIFT) 258 259 /* 260 * Debugging support. 261 */ 262 #define PMD_ENTER 1 263 #define PMD_LINK 2 264 #define PMD_PROTECT 4 265 #define PMD_SWITCH 8 266 #define PMD_COW 0x10 267 #define PMD_MODBIT 0x20 268 #define PMD_REFBIT 0x40 269 #define PMD_WIRING 0x80 270 #define PMD_CONTEXT 0x100 271 #define PMD_CREATE 0x200 272 #define PMD_SEGMAP 0x400 273 #define PMD_SETPTE 0x800 274 #define PMD_FAULT 0x1000 275 #define PMD_KMAP 0x2000 276 277 #define PMD_REMOVE PMD_ENTER 278 #define PMD_UNLINK PMD_LINK 279 280 #ifdef PMAP_DEBUG 281 int pmap_debug = 0; 282 int pmap_db_watchva = -1; 283 int pmap_db_watchpmeg = -1; 284 #endif /* PMAP_DEBUG */ 285 286 /* 287 * Miscellaneous variables. 288 * 289 * For simplicity, this interface retains the variables 290 * that were used in the old interface (without NONCONTIG). 291 */ 292 vaddr_t virtual_avail, virtual_end; 293 paddr_t avail_start, avail_end; 294 295 #if IS_SUN3 296 /* used to skip the Sun3/50 video RAM */ 297 static vaddr_t hole_start, hole_size; 298 #endif 299 300 /* This is where we map a PMEG without a context. */ 301 static vaddr_t temp_seg_va; 302 303 /* 304 * Location to store virtual addresses 305 * to be used in copy/zero operations. 306 */ 307 vaddr_t tmp_vpages[2] = { 308 #if IS_SUN2 309 PAGE_SIZE * 8, 310 PAGE_SIZE * 9 311 #else 312 SUN3_MONSHORTSEG, 313 SUN3_MONSHORTSEG + PAGE_SIZE 314 #endif 315 }; 316 int tmp_vpages_inuse; 317 318 static int pmap_version = 1; 319 static struct pmap kernel_pmap_store; 320 struct pmap *const kernel_pmap_ptr = &kernel_pmap_store; 321 #define kernel_pmap (kernel_pmap_ptr) 322 static u_char kernel_segmap[NSEGMAP]; 323 324 /* memory pool for pmap structures */ 325 struct pool pmap_pmap_pool; 326 327 /* statistics... */ 328 struct pmap_stats { 329 int ps_enter_firstpv; /* pv heads entered */ 330 int ps_enter_secondpv; /* pv nonheads entered */ 331 int ps_unlink_pvfirst; /* of pv_unlinks on head */ 332 int ps_unlink_pvsearch; /* of pv_unlink searches */ 333 int ps_pmeg_faultin; /* pmegs reloaded */ 334 int ps_changeprots; /* of calls to changeprot */ 335 int ps_changewire; /* useless wiring changes */ 336 int ps_npg_prot_all; /* of active pages protected */ 337 int ps_npg_prot_actual; /* pages actually affected */ 338 int ps_vac_uncached; /* non-cached due to bad alias */ 339 int ps_vac_recached; /* re-cached when bad alias gone */ 340 } pmap_stats; 341 342 #ifdef PMAP_DEBUG 343 #define CHECK_SPL() do { \ 344 if ((getsr() & PSL_IPL) < PSL_IPL4) \ 345 panic("pmap: bad spl, line %d", __LINE__); \ 346 } while (0) 347 #else /* PMAP_DEBUG */ 348 #define CHECK_SPL() (void)0 349 #endif /* PMAP_DEBUG */ 350 351 352 /* 353 * PV support. 354 * (i.e. Find all virtual mappings of a physical page.) 355 */ 356 357 int pv_initialized = 0; 358 359 /* One of these for each mapped virtual page. */ 360 struct pv_entry { 361 struct pv_entry *pv_next; 362 pmap_t pv_pmap; 363 vaddr_t pv_va; 364 }; 365 typedef struct pv_entry *pv_entry_t; 366 367 /* Table of PV list heads (per physical page). */ 368 static struct pv_entry **pv_head_tbl; 369 370 /* Free list of PV entries. */ 371 static struct pv_entry *pv_free_list; 372 373 /* Table of flags (per physical page). */ 374 static u_char *pv_flags_tbl; 375 376 /* These are as in the MMU but shifted by PV_SHIFT. */ 377 #if IS_SUN2 378 #define PV_SHIFT 20 379 #else 380 #define PV_SHIFT 24 381 #endif 382 #define PV_NC (PG_NC >> PV_SHIFT) 383 #define PV_REF (PG_REF >> PV_SHIFT) 384 #define PV_MOD (PG_MOD >> PV_SHIFT) 385 386 /* 387 * context structures, and queues 388 */ 389 390 struct context_state { 391 TAILQ_ENTRY(context_state) context_link; 392 int context_num; 393 struct pmap *context_upmap; 394 }; 395 typedef struct context_state *context_t; 396 397 #define INVALID_CONTEXT -1 /* impossible value */ 398 #define EMPTY_CONTEXT 0 399 #define FIRST_CONTEXT 1 400 #if IS_SUN2 401 #define KERNEL_CONTEXT 0 402 #define kernel_context_enter() int saved_ctx = get_context() 403 #define kernel_context_exit() set_context(saved_ctx) 404 #define set_kernel_segmap(v, s) set_segmap((v), (s)) 405 #define set_kernel_context() set_context(KERNEL_CONTEXT) 406 #define has_context(pmap) (((pmap)->pm_ctxnum != EMPTY_CONTEXT) == ((pmap) != kernel_pmap)) 407 #else /* IS_SUN3 */ 408 #define kernel_context_enter() __nothing 409 #define kernel_context_exit() __nothing 410 #define set_kernel_segmap(v, s) set_segmap_allctx((v), (s)) 411 #define set_kernel_context() __nothing 412 #define has_context(pmap) ((pmap)->pm_ctxnum != EMPTY_CONTEXT) 413 #endif /* IS_SUN2 */ 414 415 TAILQ_HEAD(context_tailq, context_state) 416 context_free_queue, context_active_queue; 417 418 static struct context_state context_array[NCONTEXT]; 419 420 421 /* 422 * PMEG structures, queues, and macros 423 */ 424 #define PMEGQ_FREE 0 425 #define PMEGQ_INACTIVE 1 426 #define PMEGQ_ACTIVE 2 427 #define PMEGQ_KERNEL 3 428 #define PMEGQ_NONE 4 429 430 struct pmeg_state { 431 TAILQ_ENTRY(pmeg_state) pmeg_link; 432 int pmeg_index; 433 pmap_t pmeg_owner; 434 int pmeg_version; 435 vaddr_t pmeg_va; 436 int pmeg_wired; 437 int pmeg_reserved; 438 int pmeg_vpages; 439 int pmeg_qstate; 440 }; 441 442 typedef struct pmeg_state *pmeg_t; 443 444 #define PMEG_INVAL (NPMEG-1) 445 #define PMEG_NULL (pmeg_t) NULL 446 447 /* XXX - Replace pmeg_kernel_queue with pmeg_wired_queue ? */ 448 TAILQ_HEAD(pmeg_tailq, pmeg_state) 449 pmeg_free_queue, pmeg_inactive_queue, 450 pmeg_active_queue, pmeg_kernel_queue; 451 452 static struct pmeg_state pmeg_array[NPMEG]; 453 454 455 /* 456 * prototypes 457 */ 458 static int get_pte_pmeg(int, int); 459 static void set_pte_pmeg(int, int, int); 460 461 static void context_allocate(pmap_t); 462 static void context_free(pmap_t); 463 static void context_init(void); 464 465 static void pmeg_init(void); 466 static void pmeg_reserve(int); 467 468 static pmeg_t pmeg_allocate(pmap_t, vaddr_t); 469 static void pmeg_mon_init(vaddr_t, vaddr_t, int); 470 static void pmeg_release(pmeg_t); 471 static void pmeg_free(pmeg_t); 472 static pmeg_t pmeg_cache(pmap_t, vaddr_t); 473 static void pmeg_set_wiring(pmeg_t, vaddr_t, int); 474 475 static int pv_link (pmap_t, int, vaddr_t); 476 static void pv_unlink(pmap_t, int, vaddr_t); 477 static void pv_remove_all(paddr_t); 478 static void pv_changepte(paddr_t, int, int); 479 static u_int pv_syncflags(pv_entry_t); 480 static void pv_init(void); 481 482 static void pmeg_clean(pmeg_t); 483 static void pmeg_clean_free(void); 484 485 static void pmap_common_init(pmap_t); 486 static void pmap_kernel_init(pmap_t); 487 static void pmap_user_init(pmap_t); 488 489 static void pmap_enter_kernel(vaddr_t, int, bool); 490 static void pmap_enter_user(pmap_t, vaddr_t, int, bool); 491 492 static void pmap_protect1(pmap_t, vaddr_t, vaddr_t); 493 static void pmap_protect_mmu(pmap_t, vaddr_t, vaddr_t); 494 static void pmap_protect_noctx(pmap_t, vaddr_t, vaddr_t); 495 496 static void pmap_remove1(pmap_t, vaddr_t, vaddr_t); 497 static void pmap_remove_mmu(pmap_t, vaddr_t, vaddr_t); 498 static void pmap_remove_noctx(pmap_t, vaddr_t, vaddr_t); 499 500 static int pmap_fault_reload(struct pmap *, vaddr_t, int); 501 502 #ifdef PMAP_DEBUG 503 void pmap_print(pmap_t); 504 void pv_print(paddr_t); 505 void pmeg_print(pmeg_t); 506 static void pmeg_verify_empty(vaddr_t); 507 #endif /* PMAP_DEBUG */ 508 void pmap_pinit(pmap_t); 509 void pmap_release(pmap_t); 510 511 /* 512 * Various in-line helper functions. 513 */ 514 515 static inline pmap_t 516 current_pmap(void) 517 { 518 struct vmspace *vm; 519 struct vm_map *map; 520 pmap_t pmap; 521 522 vm = curproc->p_vmspace; 523 map = &vm->vm_map; 524 pmap = vm_map_pmap(map); 525 526 return (pmap); 527 } 528 529 static inline struct pv_entry ** 530 pa_to_pvhead(paddr_t pa) 531 { 532 int idx; 533 534 idx = PA_PGNUM(pa); 535 #ifdef DIAGNOSTIC 536 if (PA_IS_DEV(pa) || (idx >= physmem)) 537 panic("pmap:pa_to_pvhead: bad pa=0x%lx", pa); 538 #endif 539 return (&pv_head_tbl[idx]); 540 } 541 542 static inline u_char * 543 pa_to_pvflags(paddr_t pa) 544 { 545 int idx; 546 547 idx = PA_PGNUM(pa); 548 #ifdef DIAGNOSTIC 549 if (PA_IS_DEV(pa) || (idx >= physmem)) 550 panic("pmap:pa_to_pvflags: bad pa=0x%lx", pa); 551 #endif 552 return (&pv_flags_tbl[idx]); 553 } 554 555 /* 556 * Save the MOD bit from the given PTE using its PA 557 */ 558 static inline void 559 save_modref_bits(int pte) 560 { 561 u_char *pv_flags; 562 563 pv_flags = pa_to_pvflags(PG_PA(pte)); 564 *pv_flags |= ((pte & PG_MODREF) >> PV_SHIFT); 565 } 566 567 static inline pmeg_t 568 pmeg_p(int sme) 569 { 570 #ifdef DIAGNOSTIC 571 if (sme < 0 || sme >= SEGINV) 572 panic("pmeg_p: bad sme"); 573 #endif 574 return &pmeg_array[sme]; 575 } 576 577 #define is_pmeg_wired(pmegp) (pmegp->pmeg_wired != 0) 578 579 static void 580 pmeg_set_wiring(pmeg_t pmegp, vaddr_t va, int flag) 581 { 582 int idx, mask; 583 584 idx = VA_PTE_NUM(va); 585 mask = 1 << idx; 586 587 if (flag) 588 pmegp->pmeg_wired |= mask; 589 else 590 pmegp->pmeg_wired &= ~mask; 591 } 592 593 /**************************************************************** 594 * Context management functions. 595 */ 596 597 /* part of pmap_bootstrap */ 598 static void 599 context_init(void) 600 { 601 int i; 602 603 TAILQ_INIT(&context_free_queue); 604 TAILQ_INIT(&context_active_queue); 605 606 /* Leave EMPTY_CONTEXT out of the free list. */ 607 context_array[0].context_upmap = kernel_pmap; 608 609 for (i = 1; i < NCONTEXT; i++) { 610 context_array[i].context_num = i; 611 context_array[i].context_upmap = NULL; 612 TAILQ_INSERT_TAIL(&context_free_queue, &context_array[i], 613 context_link); 614 #ifdef PMAP_DEBUG 615 if (pmap_debug & PMD_CONTEXT) 616 printf("context_init: sizeof(context_array[0])=%d\n", 617 sizeof(context_array[0])); 618 #endif 619 } 620 } 621 622 /* Get us a context (steal one if necessary). */ 623 static void 624 context_allocate(pmap_t pmap) 625 { 626 context_t context; 627 628 CHECK_SPL(); 629 630 #ifdef DIAGNOSTIC 631 if (pmap == kernel_pmap) 632 panic("context_allocate: kernel_pmap"); 633 if (has_context(pmap)) 634 panic("pmap: pmap already has context allocated to it"); 635 #endif 636 637 context = TAILQ_FIRST(&context_free_queue); 638 if (context == NULL) { 639 /* Steal the head of the active queue. */ 640 context = TAILQ_FIRST(&context_active_queue); 641 if (context == NULL) 642 panic("pmap: no contexts left?"); 643 #ifdef PMAP_DEBUG 644 if (pmap_debug & PMD_CONTEXT) 645 printf("context_allocate: steal ctx %d from pmap %p\n", 646 context->context_num, context->context_upmap); 647 #endif 648 context_free(context->context_upmap); 649 context = TAILQ_FIRST(&context_free_queue); 650 } 651 TAILQ_REMOVE(&context_free_queue, context, context_link); 652 653 #ifdef DIAGNOSTIC 654 if (context->context_upmap != NULL) 655 panic("pmap: context in use???"); 656 #endif 657 658 context->context_upmap = pmap; 659 pmap->pm_ctxnum = context->context_num; 660 661 TAILQ_INSERT_TAIL(&context_active_queue, context, context_link); 662 663 /* 664 * We could reload the MMU here, but that would 665 * artificially move PMEGs from the inactive queue 666 * to the active queue, so do lazy reloading. 667 * XXX - Need to reload wired pmegs though... 668 * XXX: Verify the context it is empty? 669 */ 670 } 671 672 /* 673 * Unload the context and put it on the free queue. 674 */ 675 static void 676 context_free(pmap_t pmap) 677 { 678 int saved_ctxnum, ctxnum; 679 int i, sme; 680 context_t contextp; 681 vaddr_t va; 682 683 CHECK_SPL(); 684 685 ctxnum = pmap->pm_ctxnum; 686 if (ctxnum < FIRST_CONTEXT || ctxnum >= NCONTEXT) 687 panic("pmap: context_free ctxnum"); 688 contextp = &context_array[ctxnum]; 689 690 /* Temporary context change. */ 691 saved_ctxnum = get_context(); 692 set_context(ctxnum); 693 694 /* Before unloading translations, flush cache. */ 695 #ifdef HAVECACHE 696 if (cache_size) 697 cache_flush_context(); 698 #endif 699 700 /* Unload MMU (but keep in SW segmap). */ 701 for (i = 0, va = 0; i < NUSEG; i++, va += NBSG) { 702 703 #if !defined(PMAP_DEBUG) 704 /* Short-cut using the S/W segmap (if !debug). */ 705 if (pmap->pm_segmap[i] == SEGINV) 706 continue; 707 #endif 708 709 /* Check the H/W segmap. */ 710 sme = get_segmap(va); 711 if (sme == SEGINV) 712 continue; 713 714 /* Found valid PMEG in the segmap. */ 715 #ifdef PMAP_DEBUG 716 if (pmap_debug & PMD_SEGMAP) 717 printf("pmap: set_segmap ctx=%d v=0x%lx old=0x%x " 718 "new=ff (cf)\n", ctxnum, va, sme); 719 #endif 720 #ifdef DIAGNOSTIC 721 if (sme != pmap->pm_segmap[i]) 722 panic("context_free: unknown sme at va=0x%lx", va); 723 #endif 724 /* Did cache flush above (whole context). */ 725 set_segmap(va, SEGINV); 726 /* In this case, do not clear pm_segmap. */ 727 /* XXX: Maybe inline this call? */ 728 pmeg_release(pmeg_p(sme)); 729 } 730 731 /* Restore previous context. */ 732 set_context(saved_ctxnum); 733 734 /* Dequeue, update, requeue. */ 735 TAILQ_REMOVE(&context_active_queue, contextp, context_link); 736 pmap->pm_ctxnum = EMPTY_CONTEXT; 737 contextp->context_upmap = NULL; 738 TAILQ_INSERT_TAIL(&context_free_queue, contextp, context_link); 739 } 740 741 742 /**************************************************************** 743 * PMEG management functions. 744 */ 745 746 static void 747 pmeg_init(void) 748 { 749 int x; 750 751 /* clear pmeg array, put it all on the free pmeq queue */ 752 753 TAILQ_INIT(&pmeg_free_queue); 754 TAILQ_INIT(&pmeg_inactive_queue); 755 TAILQ_INIT(&pmeg_active_queue); 756 TAILQ_INIT(&pmeg_kernel_queue); 757 758 memset(pmeg_array, 0, NPMEG*sizeof(struct pmeg_state)); 759 for (x = 0; x < NPMEG; x++) { 760 TAILQ_INSERT_TAIL(&pmeg_free_queue, &pmeg_array[x], pmeg_link); 761 pmeg_array[x].pmeg_qstate = PMEGQ_FREE; 762 pmeg_array[x].pmeg_index = x; 763 } 764 765 /* The last pmeg is not usable. */ 766 pmeg_reserve(SEGINV); 767 } 768 769 /* 770 * Reserve a pmeg (forever) for use by PROM, etc. 771 * Contents are left as-is. Called very early... 772 */ 773 void 774 pmeg_reserve(int sme) 775 { 776 pmeg_t pmegp; 777 778 /* Can not use pmeg_p() because it fails on SEGINV. */ 779 pmegp = &pmeg_array[sme]; 780 781 if (pmegp->pmeg_reserved) { 782 prom_printf("pmeg_reserve: already reserved\n"); 783 prom_abort(); 784 } 785 if (pmegp->pmeg_owner) { 786 prom_printf("pmeg_reserve: already owned\n"); 787 prom_abort(); 788 } 789 790 /* Owned by kernel, but not really usable... */ 791 pmegp->pmeg_owner = kernel_pmap; 792 pmegp->pmeg_reserved++; /* keep count, just in case */ 793 TAILQ_REMOVE(&pmeg_free_queue, pmegp, pmeg_link); 794 pmegp->pmeg_qstate = PMEGQ_NONE; 795 } 796 797 /* 798 * Examine PMEGs used by the monitor, and either 799 * reserve them (keep=1) or clear them (keep=0) 800 */ 801 static void 802 pmeg_mon_init(vaddr_t sva, vaddr_t eva, int keep) 803 { 804 vaddr_t pgva, endseg; 805 int pte, valid; 806 unsigned char sme; 807 808 #ifdef PMAP_DEBUG 809 if (pmap_debug & PMD_SEGMAP) 810 prom_printf("pmeg_mon_init(0x%x, 0x%x, %d)\n", 811 sva, eva, keep); 812 #endif 813 814 sva &= ~(NBSG - 1); 815 816 while (sva < eva) { 817 sme = get_segmap(sva); 818 if (sme != SEGINV) { 819 valid = 0; 820 endseg = sva + NBSG; 821 for (pgva = sva; pgva < endseg; pgva += PAGE_SIZE) { 822 pte = get_pte(pgva); 823 if (pte & PG_VALID) { 824 valid++; 825 } 826 } 827 #ifdef PMAP_DEBUG 828 if (pmap_debug & PMD_SEGMAP) 829 prom_printf(" sva=0x%x seg=0x%x valid=%d\n", 830 sva, sme, valid); 831 #endif 832 if (keep && valid) 833 pmeg_reserve(sme); 834 else 835 set_segmap(sva, SEGINV); 836 } 837 sva += NBSG; 838 } 839 } 840 841 /* 842 * This is used only during pmap_bootstrap, so we can 843 * get away with borrowing a user slot in the segmap. 844 * But we use temp_seg_va because Sun-2 can't do that. 845 */ 846 static void 847 pmeg_clean(pmeg_t pmegp) 848 { 849 int sme; 850 vaddr_t va; 851 852 sme = get_segmap(temp_seg_va); 853 if (sme != SEGINV) 854 panic("pmeg_clean"); 855 856 sme = pmegp->pmeg_index; 857 set_segmap(temp_seg_va, sme); 858 859 for (va = 0; va < NBSG; va += PAGE_SIZE) 860 set_pte(temp_seg_va + va, PG_INVAL); 861 862 set_segmap(temp_seg_va, SEGINV); 863 } 864 865 /* 866 * This routine makes sure that pmegs on the pmeg_free_queue contain 867 * no valid ptes. It pulls things off the queue, cleans them, and 868 * puts them at the end. The ending condition is finding the first 869 * queue element at the head of the queue again. 870 */ 871 static void 872 pmeg_clean_free(void) 873 { 874 pmeg_t pmegp, pmegp_first; 875 876 pmegp = TAILQ_FIRST(&pmeg_free_queue); 877 if (pmegp == NULL) 878 panic("pmap: no free pmegs available to clean"); 879 880 pmegp_first = NULL; 881 882 for (;;) { 883 pmegp = TAILQ_FIRST(&pmeg_free_queue); 884 TAILQ_REMOVE(&pmeg_free_queue, pmegp, pmeg_link); 885 886 pmegp->pmeg_qstate = PMEGQ_NONE; 887 pmeg_clean(pmegp); 888 pmegp->pmeg_qstate = PMEGQ_FREE; 889 890 TAILQ_INSERT_TAIL(&pmeg_free_queue, pmegp, pmeg_link); 891 892 if (pmegp == pmegp_first) 893 break; 894 if (pmegp_first == NULL) 895 pmegp_first = pmegp; 896 } 897 } 898 899 /* 900 * Allocate a PMEG by whatever means necessary. 901 * (May invalidate some mappings!) 902 */ 903 static pmeg_t 904 pmeg_allocate(pmap_t pmap, vaddr_t va) 905 { 906 pmeg_t pmegp; 907 908 CHECK_SPL(); 909 910 #ifdef DIAGNOSTIC 911 if (va & SEGOFSET) { 912 panic("pmap:pmeg_allocate: va=0x%lx", va); 913 } 914 #endif 915 916 /* Get one onto the free list if necessary. */ 917 pmegp = TAILQ_FIRST(&pmeg_free_queue); 918 if (!pmegp) { 919 /* Try inactive queue... */ 920 pmegp = TAILQ_FIRST(&pmeg_inactive_queue); 921 if (!pmegp) { 922 /* Try active queue... */ 923 pmegp = TAILQ_FIRST(&pmeg_active_queue); 924 } 925 if (!pmegp) { 926 panic("pmeg_allocate: failed"); 927 } 928 929 /* 930 * Remove mappings to free-up a pmeg 931 * (so it will go onto the free list). 932 * XXX - Skip this one if it is wired? 933 */ 934 pmap_remove1(pmegp->pmeg_owner, 935 pmegp->pmeg_va, 936 pmegp->pmeg_va + NBSG); 937 } 938 939 /* OK, free list has something for us to take. */ 940 pmegp = TAILQ_FIRST(&pmeg_free_queue); 941 #ifdef DIAGNOSTIC 942 if (pmegp == NULL) 943 panic("pmeg_allocagte: still none free?"); 944 if ((pmegp->pmeg_qstate != PMEGQ_FREE) || 945 (pmegp->pmeg_index == SEGINV) || 946 (pmegp->pmeg_vpages)) 947 panic("pmeg_allocate: bad pmegp=%p", pmegp); 948 #endif 949 #ifdef PMAP_DEBUG 950 if (pmegp->pmeg_index == pmap_db_watchpmeg) { 951 db_printf("pmeg_allocate: watch pmegp=%p\n", pmegp); 952 Debugger(); 953 } 954 #endif 955 956 TAILQ_REMOVE(&pmeg_free_queue, pmegp, pmeg_link); 957 958 /* Reassign this PMEG for the caller. */ 959 pmegp->pmeg_owner = pmap; 960 pmegp->pmeg_version = pmap->pm_version; 961 pmegp->pmeg_va = va; 962 pmegp->pmeg_wired = 0; 963 pmegp->pmeg_reserved = 0; 964 pmegp->pmeg_vpages = 0; 965 if (pmap == kernel_pmap) { 966 TAILQ_INSERT_TAIL(&pmeg_kernel_queue, pmegp, pmeg_link); 967 pmegp->pmeg_qstate = PMEGQ_KERNEL; 968 } else { 969 TAILQ_INSERT_TAIL(&pmeg_active_queue, pmegp, pmeg_link); 970 pmegp->pmeg_qstate = PMEGQ_ACTIVE; 971 } 972 /* Caller will verify that it's empty (if debugging). */ 973 return pmegp; 974 } 975 976 /* 977 * Put pmeg on the inactive queue, leaving its contents intact. 978 * This happens when we lose our context. We may reclaim 979 * this pmeg later if it is still in the inactive queue. 980 */ 981 static void 982 pmeg_release(pmeg_t pmegp) 983 { 984 985 CHECK_SPL(); 986 987 #ifdef DIAGNOSTIC 988 if ((pmegp->pmeg_owner == kernel_pmap) || 989 (pmegp->pmeg_qstate != PMEGQ_ACTIVE)) 990 panic("pmeg_release: bad pmeg=%p", pmegp); 991 #endif 992 993 TAILQ_REMOVE(&pmeg_active_queue, pmegp, pmeg_link); 994 pmegp->pmeg_qstate = PMEGQ_INACTIVE; 995 TAILQ_INSERT_TAIL(&pmeg_inactive_queue, pmegp, pmeg_link); 996 } 997 998 /* 999 * Move the pmeg to the free queue from wherever it is. 1000 * The pmeg will be clean. It might be in kernel_pmap. 1001 */ 1002 static void 1003 pmeg_free(pmeg_t pmegp) 1004 { 1005 1006 CHECK_SPL(); 1007 1008 #ifdef DIAGNOSTIC 1009 /* Caller should verify that it's empty. */ 1010 if (pmegp->pmeg_vpages != 0) 1011 panic("pmeg_free: vpages"); 1012 #endif 1013 1014 switch (pmegp->pmeg_qstate) { 1015 case PMEGQ_ACTIVE: 1016 TAILQ_REMOVE(&pmeg_active_queue, pmegp, pmeg_link); 1017 break; 1018 case PMEGQ_INACTIVE: 1019 TAILQ_REMOVE(&pmeg_inactive_queue, pmegp, pmeg_link); 1020 break; 1021 case PMEGQ_KERNEL: 1022 TAILQ_REMOVE(&pmeg_kernel_queue, pmegp, pmeg_link); 1023 break; 1024 default: 1025 panic("pmeg_free: releasing bad pmeg"); 1026 break; 1027 } 1028 1029 #ifdef PMAP_DEBUG 1030 if (pmegp->pmeg_index == pmap_db_watchpmeg) { 1031 db_printf("pmeg_free: watch pmeg 0x%x\n", 1032 pmegp->pmeg_index); 1033 Debugger(); 1034 } 1035 #endif 1036 1037 pmegp->pmeg_owner = NULL; 1038 pmegp->pmeg_qstate = PMEGQ_FREE; 1039 TAILQ_INSERT_TAIL(&pmeg_free_queue, pmegp, pmeg_link); 1040 } 1041 1042 /* 1043 * Find a PMEG that was put on the inactive queue when we 1044 * had our context stolen. If found, move to active queue. 1045 */ 1046 static pmeg_t 1047 pmeg_cache(pmap_t pmap, vaddr_t va) 1048 { 1049 int sme, segnum; 1050 pmeg_t pmegp; 1051 1052 CHECK_SPL(); 1053 1054 #ifdef DIAGNOSTIC 1055 if (pmap == kernel_pmap) 1056 panic("pmeg_cache: kernel_pmap"); 1057 if (va & SEGOFSET) { 1058 panic("pmap:pmeg_cache: va=0x%lx", va); 1059 } 1060 #endif 1061 1062 if (pmap->pm_segmap == NULL) 1063 return PMEG_NULL; 1064 1065 segnum = VA_SEGNUM(va); 1066 if (segnum > NUSEG) /* out of range */ 1067 return PMEG_NULL; 1068 1069 sme = pmap->pm_segmap[segnum]; 1070 if (sme == SEGINV) /* nothing cached */ 1071 return PMEG_NULL; 1072 1073 pmegp = pmeg_p(sme); 1074 1075 #ifdef PMAP_DEBUG 1076 if (pmegp->pmeg_index == pmap_db_watchpmeg) { 1077 db_printf("pmeg_cache: watch pmeg 0x%x\n", pmegp->pmeg_index); 1078 Debugger(); 1079 } 1080 #endif 1081 1082 /* 1083 * Our segmap named a PMEG. If it is no longer ours, 1084 * invalidate that entry in our segmap and return NULL. 1085 */ 1086 if ((pmegp->pmeg_owner != pmap) || 1087 (pmegp->pmeg_version != pmap->pm_version) || 1088 (pmegp->pmeg_va != va)) 1089 { 1090 #ifdef PMAP_DEBUG 1091 db_printf("pmap:pmeg_cache: invalid pmeg: sme=0x%x\n", sme); 1092 pmeg_print(pmegp); 1093 Debugger(); 1094 #endif 1095 pmap->pm_segmap[segnum] = SEGINV; 1096 return PMEG_NULL; /* cache lookup failed */ 1097 } 1098 1099 #ifdef DIAGNOSTIC 1100 /* Make sure it is on the inactive queue. */ 1101 if (pmegp->pmeg_qstate != PMEGQ_INACTIVE) 1102 panic("pmeg_cache: pmeg was taken: %p", pmegp); 1103 #endif 1104 1105 TAILQ_REMOVE(&pmeg_inactive_queue, pmegp, pmeg_link); 1106 pmegp->pmeg_qstate = PMEGQ_ACTIVE; 1107 TAILQ_INSERT_TAIL(&pmeg_active_queue, pmegp, pmeg_link); 1108 1109 return pmegp; 1110 } 1111 1112 #ifdef PMAP_DEBUG 1113 static void 1114 pmeg_verify_empty(vaddr_t va) 1115 { 1116 vaddr_t eva; 1117 int pte; 1118 1119 for (eva = va + NBSG; va < eva; va += PAGE_SIZE) { 1120 pte = get_pte(va); 1121 if (pte & PG_VALID) 1122 panic("pmeg_verify_empty"); 1123 } 1124 } 1125 #endif /* PMAP_DEBUG */ 1126 1127 1128 /**************************************************************** 1129 * Physical-to-virtual lookup support 1130 * 1131 * Need memory for the pv_alloc/pv_free list heads 1132 * and elements. We know how many to allocate since 1133 * there is one list head for each physical page, and 1134 * at most one element for each PMEG slot. 1135 */ 1136 static void 1137 pv_init(void) 1138 { 1139 int npp, nvp, sz; 1140 pv_entry_t pv; 1141 char *p; 1142 1143 /* total allocation size */ 1144 sz = 0; 1145 1146 /* 1147 * Data for each physical page. 1148 * Each "mod/ref" flag is a char. 1149 * Each PV head is a pointer. 1150 * Note physmem is in pages. 1151 */ 1152 npp = ALIGN(physmem); 1153 sz += (npp * sizeof(*pv_flags_tbl)); 1154 sz += (npp * sizeof(*pv_head_tbl)); 1155 1156 /* 1157 * Data for each virtual page (all PMEGs). 1158 * One pv_entry for each page frame. 1159 */ 1160 nvp = NPMEG * NPAGSEG; 1161 sz += (nvp * sizeof(*pv_free_list)); 1162 1163 /* Now allocate the whole thing. */ 1164 sz = m68k_round_page(sz); 1165 p = (char *)uvm_km_alloc(kernel_map, sz, 0, UVM_KMF_WIRED); 1166 if (p == NULL) 1167 panic("pmap:pv_init: alloc failed"); 1168 memset(p, 0, sz); 1169 1170 /* Now divide up the space. */ 1171 pv_flags_tbl = (void *) p; 1172 p += (npp * sizeof(*pv_flags_tbl)); 1173 pv_head_tbl = (void*) p; 1174 p += (npp * sizeof(*pv_head_tbl)); 1175 pv_free_list = (void *)p; 1176 p += (nvp * sizeof(*pv_free_list)); 1177 1178 /* Finally, make pv_free_list into a list. */ 1179 for (pv = pv_free_list; (char *)pv < p; pv++) 1180 pv->pv_next = &pv[1]; 1181 pv[-1].pv_next = 0; 1182 1183 pv_initialized++; 1184 } 1185 1186 /* 1187 * Set or clear bits in all PTEs mapping a page. 1188 * Also does syncflags work while we are there... 1189 */ 1190 static void 1191 pv_changepte(paddr_t pa, int set_bits, int clear_bits) 1192 { 1193 pv_entry_t *head, pv; 1194 u_char *pv_flags; 1195 pmap_t pmap; 1196 vaddr_t va; 1197 int pte, sme; 1198 int saved_ctx; 1199 bool in_ctx; 1200 u_int flags; 1201 1202 pv_flags = pa_to_pvflags(pa); 1203 head = pa_to_pvhead(pa); 1204 1205 /* If no mappings, no work to do. */ 1206 if (*head == NULL) 1207 return; 1208 1209 #ifdef DIAGNOSTIC 1210 /* This function should only clear these bits: */ 1211 if (clear_bits & ~(PG_WRITE | PG_NC | PG_REF | PG_MOD)) 1212 panic("pv_changepte: clear=0x%x", clear_bits); 1213 #endif 1214 1215 flags = 0; 1216 saved_ctx = get_context(); 1217 for (pv = *head; pv != NULL; pv = pv->pv_next) { 1218 pmap = pv->pv_pmap; 1219 va = pv->pv_va; 1220 1221 #ifdef DIAGNOSTIC 1222 if (pmap->pm_segmap == NULL) 1223 panic("pv_changepte: null segmap"); 1224 #endif 1225 1226 /* Is the PTE currently accessible in some context? */ 1227 in_ctx = false; 1228 sme = SEGINV; /* kill warning */ 1229 if (pmap == kernel_pmap) { 1230 set_kernel_context(); 1231 in_ctx = true; 1232 } 1233 else if (has_context(pmap)) { 1234 /* PMEG may be inactive. */ 1235 set_context(pmap->pm_ctxnum); 1236 sme = get_segmap(va); 1237 if (sme != SEGINV) 1238 in_ctx = true; 1239 } 1240 1241 if (in_ctx == true) { 1242 /* 1243 * The PTE is in the current context. 1244 * Make sure PTE is up-to-date with VAC. 1245 */ 1246 #ifdef HAVECACHE 1247 if (cache_size) 1248 cache_flush_page(va); 1249 #endif 1250 pte = get_pte(va); 1251 } else { 1252 1253 /* 1254 * The PTE is not in any context. 1255 */ 1256 1257 sme = pmap->pm_segmap[VA_SEGNUM(va)]; 1258 #ifdef DIAGNOSTIC 1259 if (sme == SEGINV) 1260 panic("pv_changepte: SEGINV"); 1261 #endif 1262 pte = get_pte_pmeg(sme, VA_PTE_NUM(va)); 1263 } 1264 1265 #ifdef DIAGNOSTIC 1266 /* PV entries point only to valid mappings. */ 1267 if ((pte & PG_VALID) == 0) 1268 panic("pv_changepte: not PG_VALID at va=0x%lx", va); 1269 #endif 1270 /* Get these while it's easy. */ 1271 if (pte & PG_MODREF) { 1272 flags |= (pte & PG_MODREF); 1273 pte &= ~PG_MODREF; 1274 } 1275 1276 /* Finally, set and clear some bits. */ 1277 pte |= set_bits; 1278 pte &= ~clear_bits; 1279 1280 if (in_ctx == true) { 1281 /* Did cache flush above. */ 1282 set_pte(va, pte); 1283 } else { 1284 set_pte_pmeg(sme, VA_PTE_NUM(va), pte); 1285 } 1286 } 1287 set_context(saved_ctx); 1288 1289 *pv_flags |= (flags >> PV_SHIFT); 1290 } 1291 1292 /* 1293 * Return ref and mod bits from pvlist, 1294 * and turns off same in hardware PTEs. 1295 */ 1296 static u_int 1297 pv_syncflags(pv_entry_t pv) 1298 { 1299 pmap_t pmap; 1300 vaddr_t va; 1301 int pte, sme; 1302 int saved_ctx; 1303 bool in_ctx; 1304 u_int flags; 1305 1306 /* If no mappings, no work to do. */ 1307 if (pv == NULL) 1308 return (0); 1309 1310 flags = 0; 1311 saved_ctx = get_context(); 1312 for (; pv != NULL; pv = pv->pv_next) { 1313 pmap = pv->pv_pmap; 1314 va = pv->pv_va; 1315 sme = SEGINV; 1316 1317 #ifdef DIAGNOSTIC 1318 /* 1319 * Only the head may have a null pmap, and 1320 * we checked for that above. 1321 */ 1322 if (pmap->pm_segmap == NULL) 1323 panic("pv_syncflags: null segmap"); 1324 #endif 1325 1326 /* Is the PTE currently accessible in some context? */ 1327 in_ctx = false; 1328 if (pmap == kernel_pmap) { 1329 set_kernel_context(); 1330 in_ctx = true; 1331 } 1332 else if (has_context(pmap)) { 1333 /* PMEG may be inactive. */ 1334 set_context(pmap->pm_ctxnum); 1335 sme = get_segmap(va); 1336 if (sme != SEGINV) 1337 in_ctx = true; 1338 } 1339 1340 if (in_ctx == true) { 1341 1342 /* 1343 * The PTE is in the current context. 1344 * Make sure PTE is up-to-date with VAC. 1345 */ 1346 1347 #ifdef HAVECACHE 1348 if (cache_size) 1349 cache_flush_page(va); 1350 #endif 1351 pte = get_pte(va); 1352 } else { 1353 1354 /* 1355 * The PTE is not in any context. 1356 */ 1357 1358 sme = pmap->pm_segmap[VA_SEGNUM(va)]; 1359 #ifdef DIAGNOSTIC 1360 if (sme == SEGINV) 1361 panic("pv_syncflags: SEGINV"); 1362 #endif 1363 pte = get_pte_pmeg(sme, VA_PTE_NUM(va)); 1364 } 1365 1366 #ifdef DIAGNOSTIC 1367 /* PV entries point only to valid mappings. */ 1368 if ((pte & PG_VALID) == 0) 1369 panic("pv_syncflags: not PG_VALID at va=0x%lx", va); 1370 #endif 1371 /* OK, do what we came here for... */ 1372 if (pte & PG_MODREF) { 1373 flags |= (pte & PG_MODREF); 1374 pte &= ~PG_MODREF; 1375 } 1376 1377 if (in_ctx == true) { 1378 /* Did cache flush above. */ 1379 set_pte(va, pte); 1380 } else { 1381 set_pte_pmeg(sme, VA_PTE_NUM(va), pte); 1382 } 1383 } 1384 set_context(saved_ctx); 1385 1386 return (flags >> PV_SHIFT); 1387 } 1388 1389 /* Remove all mappings for the physical page. */ 1390 static void 1391 pv_remove_all(paddr_t pa) 1392 { 1393 pv_entry_t *head, pv; 1394 pmap_t pmap; 1395 vaddr_t va; 1396 1397 CHECK_SPL(); 1398 1399 #ifdef PMAP_DEBUG 1400 if (pmap_debug & PMD_REMOVE) 1401 printf("pv_remove_all(0x%lx)\n", pa); 1402 #endif 1403 1404 head = pa_to_pvhead(pa); 1405 while ((pv = *head) != NULL) { 1406 pmap = pv->pv_pmap; 1407 va = pv->pv_va; 1408 pmap_remove1(pmap, va, va + PAGE_SIZE); 1409 #ifdef PMAP_DEBUG 1410 /* Make sure it went away. */ 1411 if (pv == *head) { 1412 db_printf("pv_remove_all: " 1413 "head unchanged for pa=0x%lx\n", pa); 1414 Debugger(); 1415 } 1416 #endif 1417 } 1418 } 1419 1420 /* 1421 * The pmap system is asked to lookup all mappings that point to a 1422 * given physical memory address. This function adds a new element 1423 * to the list of mappings maintained for the given physical address. 1424 * Returns PV_NC if the (new) pvlist says that the address cannot 1425 * be cached. 1426 */ 1427 static int 1428 pv_link(pmap_t pmap, int pte, vaddr_t va) 1429 { 1430 paddr_t pa; 1431 pv_entry_t *head, pv; 1432 u_char *pv_flags; 1433 1434 if (!pv_initialized) 1435 return 0; 1436 1437 CHECK_SPL(); 1438 1439 pa = PG_PA(pte); 1440 1441 #ifdef PMAP_DEBUG 1442 if ((pmap_debug & PMD_LINK) || (va == pmap_db_watchva)) { 1443 printf("pv_link(%p, 0x%x, 0x%lx)\n", pmap, pte, va); 1444 /* pv_print(pa); */ 1445 } 1446 #endif 1447 1448 pv_flags = pa_to_pvflags(pa); 1449 head = pa_to_pvhead(pa); 1450 1451 #ifdef DIAGNOSTIC 1452 /* See if this mapping is already in the list. */ 1453 for (pv = *head; pv != NULL; pv = pv->pv_next) { 1454 if ((pv->pv_pmap == pmap) && (pv->pv_va == va)) 1455 panic("pv_link: duplicate entry for PA=0x%lx", pa); 1456 } 1457 #endif 1458 1459 int flags = (pte & (PG_NC | PG_MODREF)) >> PV_SHIFT; 1460 *pv_flags |= flags; 1461 1462 #ifdef HAVECACHE 1463 /* 1464 * Does this new mapping cause VAC alias problems? 1465 */ 1466 if ((*pv_flags & PV_NC) == 0) { 1467 for (pv = *head; pv != NULL; pv = pv->pv_next) { 1468 if (BADALIAS(va, pv->pv_va)) { 1469 *pv_flags |= PV_NC; 1470 pv_changepte(pa, PG_NC, 0); 1471 pmap_stats.ps_vac_uncached++; 1472 break; 1473 } 1474 } 1475 } 1476 #endif 1477 1478 /* Allocate a PV element (pv_alloc()). */ 1479 pv = pv_free_list; 1480 if (pv == NULL) 1481 panic("pv_link: pv_alloc"); 1482 pv_free_list = pv->pv_next; 1483 pv->pv_next = 0; 1484 1485 /* Insert new entry at the head. */ 1486 pv->pv_pmap = pmap; 1487 pv->pv_va = va; 1488 pv->pv_next = *head; 1489 *head = pv; 1490 1491 return (*pv_flags & PV_NC); 1492 } 1493 1494 /* 1495 * pv_unlink is a helper function for pmap_remove. 1496 * It removes the appropriate (pmap, pa, va) entry. 1497 * 1498 * Once the entry is removed, if the pv_table head has the cache 1499 * inhibit bit set, see if we can turn that off; if so, walk the 1500 * pvlist and turn off PG_NC in each PTE. (The pvlist is by 1501 * definition nonempty, since it must have at least two elements 1502 * in it to have PV_NC set, and we only remove one here.) 1503 */ 1504 static void 1505 pv_unlink(pmap_t pmap, int pte, vaddr_t va) 1506 { 1507 paddr_t pa; 1508 pv_entry_t *head, *ppv, pv; 1509 u_char *pv_flags; 1510 1511 CHECK_SPL(); 1512 1513 pa = PG_PA(pte); 1514 #ifdef PMAP_DEBUG 1515 if ((pmap_debug & PMD_LINK) || (va == pmap_db_watchva)) { 1516 printf("pv_unlink(%p, 0x%x, 0x%lx)\n", pmap, pte, va); 1517 /* pv_print(pa); */ 1518 } 1519 #endif 1520 1521 pv_flags = pa_to_pvflags(pa); 1522 head = pa_to_pvhead(pa); 1523 1524 /* 1525 * Find the entry. 1526 */ 1527 ppv = head; 1528 pv = *ppv; 1529 while (pv) { 1530 if ((pv->pv_pmap == pmap) && (pv->pv_va == va)) 1531 goto found; 1532 ppv = &pv->pv_next; 1533 pv = pv->pv_next; 1534 } 1535 #ifdef PMAP_DEBUG 1536 db_printf("pv_unlink: not found (pa=0x%lx,va=0x%lx)\n", pa, va); 1537 Debugger(); 1538 #endif 1539 return; 1540 1541 found: 1542 /* Unlink this entry from the list and clear it. */ 1543 *ppv = pv->pv_next; 1544 pv->pv_pmap = NULL; 1545 pv->pv_va = 0; 1546 1547 /* Insert it on the head of the free list. (pv_free()) */ 1548 pv->pv_next = pv_free_list; 1549 pv_free_list = pv; 1550 pv = NULL; 1551 1552 /* Do any non-cached mappings remain? */ 1553 if ((*pv_flags & PV_NC) == 0) 1554 return; 1555 if ((pv = *head) == NULL) 1556 return; 1557 1558 /* 1559 * Have non-cached mappings. See if we can fix that now. 1560 */ 1561 va = pv->pv_va; 1562 for (pv = pv->pv_next; pv != NULL; pv = pv->pv_next) { 1563 /* If there is a DVMA mapping, leave it NC. */ 1564 if (va >= DVMA_MAP_BASE) 1565 return; 1566 /* If there are VAC alias problems, leave NC. */ 1567 if (BADALIAS(va, pv->pv_va)) 1568 return; 1569 } 1570 /* OK, there are no "problem" mappings. */ 1571 *pv_flags &= ~PV_NC; 1572 pv_changepte(pa, 0, PG_NC); 1573 pmap_stats.ps_vac_recached++; 1574 } 1575 1576 1577 /**************************************************************** 1578 * Bootstrap and Initialization, etc. 1579 */ 1580 1581 void 1582 pmap_common_init(pmap_t pmap) 1583 { 1584 memset(pmap, 0, sizeof(struct pmap)); 1585 pmap->pm_refcount = 1; 1586 pmap->pm_version = pmap_version++; 1587 pmap->pm_ctxnum = EMPTY_CONTEXT; 1588 } 1589 1590 /* 1591 * Prepare the kernel for VM operations. 1592 * This is called by locore2.c:_vm_init() 1593 * after the "start/end" globals are set. 1594 * This function must NOT leave context zero. 1595 */ 1596 paddr_t 1597 pmap_bootstrap(vaddr_t nextva) 1598 { 1599 vaddr_t va, eva; 1600 int i, pte, sme; 1601 extern char etext[]; 1602 extern void *msgbufaddr; 1603 paddr_t nextpa; 1604 1605 nextva = m68k_round_page(nextva); 1606 1607 /* Steal some special-purpose, already mapped pages? */ 1608 1609 /* 1610 * Determine the range of kernel virtual space available. 1611 * It is segment-aligned to simplify PMEG management. 1612 */ 1613 virtual_avail = sun_round_seg(nextva); 1614 virtual_end = VM_MAX_KERNEL_ADDRESS; 1615 1616 /* 1617 * Determine the range of physical memory available. 1618 */ 1619 phys_seg_list[0].ps_start = 0; 1620 1621 #if IS_SUN2 1622 nextpa = nextva; 1623 1624 phys_seg_list[0].ps_end = m68k_trunc_page(prom_memsize()); 1625 #else 1626 /* Physical memory at zero was remapped to KERNBASE. */ 1627 nextpa = nextva - KERNBASE3; 1628 1629 struct sunromvec *rvec = romVectorPtr; 1630 if (rvec->romvecVersion < 1) { 1631 prom_printf("Warning: ancient PROM version=%d\n", 1632 rvec->romvecVersion); 1633 /* Guess that PROM version 0.X used two pages. */ 1634 phys_seg_list[0].ps_end = *rvec->memorySize - (2*PAGE_SIZE); 1635 } else { 1636 /* PROM version 1 or later. */ 1637 phys_seg_list[0].ps_end = *rvec->memoryAvail; 1638 } 1639 #endif /* IS_SUN2 */ 1640 1641 /* 1642 * Report the actual amount of physical memory, 1643 * even though the PROM takes a few pages. 1644 */ 1645 physmem = (btoc(phys_seg_list[0].ps_end) + 0xF) & ~0xF; 1646 1647 #if IS_SUN3 1648 /* 1649 * On the Sun3/50, the video frame buffer is located at 1650 * physical address 1MB so we must step over it. 1651 */ 1652 if (cpu_machine_id == ID_SUN3_50) { 1653 hole_start = m68k_trunc_page(OBMEM_BW50_ADDR); 1654 hole_size = m68k_round_page(OBMEM_BW2_SIZE); 1655 if (nextpa > hole_start) { 1656 prom_printf("kernel too large for Sun3/50\n"); 1657 prom_abort(); 1658 } 1659 phys_seg_list[1].ps_start = hole_start + hole_size; 1660 phys_seg_list[1].ps_end = phys_seg_list[0].ps_end; 1661 phys_seg_list[0].ps_end = hole_start; 1662 } 1663 #endif /* IS_SUN3 */ 1664 1665 /* 1666 * Done allocating PAGES of virtual space, so 1667 * clean out the rest of the last used segment. 1668 */ 1669 for (va = nextva; va < virtual_avail; va += PAGE_SIZE) 1670 set_pte(va, PG_INVAL); 1671 1672 /* 1673 * Now that we are done stealing physical pages, etc. 1674 * figure out which PMEGs are used by those mappings 1675 * and either reserve them or clear them out. 1676 * -- but first, init PMEG management. 1677 * This puts all PMEGs in the free list. 1678 * We will allocate the in-use ones. 1679 */ 1680 pmeg_init(); 1681 1682 #if IS_SUN2 1683 va = KERNBASE; 1684 #else 1685 /* 1686 * Unmap user virtual segments. 1687 * VA range: [0 .. KERNBASE] 1688 */ 1689 for (va = 0; va < KERNBASE3; va += NBSG) 1690 set_segmap(va, SEGINV); 1691 #endif /* IS_SUN2 */ 1692 1693 /* 1694 * Reserve PMEGS for kernel text/data/bss 1695 * and the misc pages taken above. 1696 * VA range: [KERNBASE .. virtual_avail] 1697 */ 1698 for ( ; va < virtual_avail; va += NBSG) { 1699 sme = get_segmap(va); 1700 if (sme == SEGINV) { 1701 prom_printf("kernel text/data/bss not mapped\n"); 1702 prom_abort(); 1703 } 1704 pmeg_reserve(sme); 1705 } 1706 1707 /* 1708 * Unmap kernel virtual space. Make sure to leave no valid 1709 * segmap entries in the MMU unless pmeg_array records them. 1710 * VA range: [vseg_avail .. virtual_end] 1711 */ 1712 for ( ; va < virtual_end; va += NBSG) 1713 set_segmap(va, SEGINV); 1714 1715 #if IS_SUN2 1716 /* 1717 * Reserve PMEGs used by the PROM monitor (device mappings). 1718 * Free up any pmegs in this range which have no mappings. 1719 * VA range: [0x00E00000 .. 0x00F00000] 1720 */ 1721 pmeg_mon_init(SUN2_MONSTART, SUN2_MONEND, true); 1722 1723 /* 1724 * Unmap any pmegs left in DVMA space by the PROM. 1725 * DO NOT kill the last one! (owned by the PROM!) 1726 * VA range: [0x00F00000 .. 0x00FE0000] 1727 */ 1728 pmeg_mon_init(SUN2_MONEND, SUN2_MONEND + DVMA_MAP_SIZE, false); 1729 #else /* IS_SUN3 */ 1730 /* 1731 * Reserve PMEGs used by the PROM monitor (device mappings). 1732 * Free up any pmegs in this range which have no mappings. 1733 * VA range: [0x0FE00000 .. 0x0FF00000] 1734 */ 1735 pmeg_mon_init(SUN3_MONSTART, SUN3_MONEND, true); 1736 1737 /* 1738 * Unmap any pmegs left in DVMA space by the PROM. 1739 * DO NOT kill the last one! (owned by the PROM!) 1740 * VA range: [0x0FF00000 .. 0x0FFE0000] 1741 */ 1742 pmeg_mon_init(SUN3_MONEND, SUN3_MONSHORTSEG, false); 1743 1744 /* 1745 * MONSHORTSEG contains MONSHORTPAGE which is a data page 1746 * allocated by the PROM monitor. Reserve the segment, 1747 * but clear out all but the last PTE inside it. 1748 * Note we use this for tmp_vpages. 1749 */ 1750 va = SUN3_MONSHORTSEG; 1751 eva = SUN3_MONSHORTPAGE; 1752 sme = get_segmap(va); 1753 pmeg_reserve(sme); 1754 for ( ; va < eva; va += PAGE_SIZE) 1755 set_pte(va, PG_INVAL); 1756 #endif /* IS_SUN2 */ 1757 1758 /* 1759 * Done reserving PMEGs and/or clearing out mappings. 1760 * 1761 * Now verify the mapping protections and such for the 1762 * important parts of the address space (in VA order). 1763 * Note that the Sun PROM usually leaves the memory 1764 * mapped with everything non-cached... 1765 */ 1766 1767 #if IS_SUN2 1768 /* 1769 * On a Sun2, the boot loader loads the kernel exactly where 1770 * it is linked, at physical/virtual 0x6000 (KERNBASE). This 1771 * means there are twelve physical/virtual pages before the 1772 * kernel text begins. 1773 */ 1774 va = 0; 1775 1776 /* 1777 * Physical/virtual pages zero through three are used by the 1778 * PROM. prom_init has already saved the PTEs, but we don't 1779 * want to unmap the pages until we've installed our own 1780 * vector table - just in case something happens before then 1781 * and we drop into the PROM. 1782 */ 1783 eva = va + PAGE_SIZE * 4; 1784 va = eva; 1785 1786 /* 1787 * We use pages four through seven for the msgbuf. 1788 */ 1789 eva = va + PAGE_SIZE * 4; 1790 msgbufaddr = (void *)va; 1791 for (; va < eva; va += PAGE_SIZE) { 1792 pte = get_pte(va); 1793 pte |= (PG_SYSTEM | PG_WRITE | PG_NC); 1794 set_pte(va, pte); 1795 } 1796 1797 /* 1798 * On the Sun3, two of the three dead pages in SUN3_MONSHORTSEG 1799 * are used for tmp_vpages. The Sun2 doesn't have this 1800 * short-segment concept, so we reserve virtual pages eight 1801 * and nine for this. 1802 */ 1803 set_pte(va, PG_INVAL); 1804 va += PAGE_SIZE; 1805 set_pte(va, PG_INVAL); 1806 va += PAGE_SIZE; 1807 1808 /* 1809 * Pages ten and eleven remain for the temporary kernel stack, 1810 * which is set up by locore.s. Hopefully this is enough space. 1811 */ 1812 eva = va + PAGE_SIZE * 2; 1813 for (; va < eva ; va += PAGE_SIZE) { 1814 pte = get_pte(va); 1815 pte &= ~(PG_NC); 1816 pte |= (PG_SYSTEM | PG_WRITE); 1817 set_pte(va, pte); 1818 } 1819 #else /* IS_SUN3 */ 1820 /* 1821 * Map the message buffer page at a constant location 1822 * (physical address zero) so its contents will be 1823 * preserved through a reboot. 1824 */ 1825 va = KERNBASE3; 1826 msgbufaddr = (void *)va; 1827 pte = get_pte(va); 1828 pte |= (PG_SYSTEM | PG_WRITE | PG_NC); 1829 set_pte(va, pte); 1830 va += PAGE_SIZE; 1831 1832 /* Next is the tmpstack page. */ 1833 pte = get_pte(va); 1834 pte &= ~(PG_NC); 1835 pte |= (PG_SYSTEM | PG_WRITE); 1836 set_pte(va, pte); 1837 va += PAGE_SIZE; 1838 #endif /* IS_SUN2 */ 1839 1840 /* 1841 * Next is the kernel text. 1842 * 1843 * Verify protection bits on kernel text/data/bss 1844 * All of kernel text, data, and bss are cached. 1845 * Text is read-only (except in db_write_ktext). 1846 */ 1847 eva = m68k_trunc_page(etext); 1848 while (va < eva) { 1849 pte = get_pte(va); 1850 if ((pte & (PG_VALID|PG_TYPE)) != PG_VALID) { 1851 prom_printf("invalid page at 0x%x\n", va); 1852 } 1853 pte &= ~(PG_WRITE|PG_NC); 1854 /* Kernel text is read-only */ 1855 pte |= (PG_SYSTEM); 1856 set_pte(va, pte); 1857 va += PAGE_SIZE; 1858 } 1859 /* data, bss, etc. */ 1860 while (va < nextva) { 1861 pte = get_pte(va); 1862 if ((pte & (PG_VALID|PG_TYPE)) != PG_VALID) { 1863 prom_printf("invalid page at 0x%x\n", va); 1864 } 1865 pte &= ~(PG_NC); 1866 pte |= (PG_SYSTEM | PG_WRITE); 1867 set_pte(va, pte); 1868 va += PAGE_SIZE; 1869 } 1870 1871 #ifdef DIAGNOSTIC 1872 /* 1873 * Sanity checks for context initialization below... 1874 */ 1875 #if IS_SUN3 1876 /* Note: PROM setcxsegmap function needs sfc=dfc=FC_CONTROL */ 1877 if ((getsfc() != FC_CONTROL) || (getdfc() != FC_CONTROL)) { 1878 prom_printf("pmap_bootstrap: bad dfc or sfc\n"); 1879 prom_abort(); 1880 } 1881 #endif 1882 /* Near the beginning of locore.s we set context zero. */ 1883 if (get_context() != 0) { 1884 prom_printf("pmap_bootstrap: not in context zero?\n"); 1885 prom_abort(); 1886 } 1887 #endif /* DIAGNOSTIC */ 1888 1889 #if IS_SUN2 1890 /* 1891 * Initialize all of the other contexts. 1892 */ 1893 for (va = 0; va < (vaddr_t) (NBSG * NSEGMAP); va += NBSG) { 1894 for (i = 1; i < NCONTEXT; i++) { 1895 set_context(i); 1896 set_segmap(va, SEGINV); 1897 } 1898 } 1899 set_context(KERNEL_CONTEXT); 1900 #else /* IS_SUN3 */ 1901 /* 1902 * Duplicate all mappings in the current context into 1903 * every other context. We have to let the PROM do the 1904 * actual segmap manipulation because we can only switch 1905 * the MMU context after we are sure that the kernel is 1906 * identically mapped in all contexts. The PROM can do 1907 * the job using hardware-dependent tricks... 1908 */ 1909 for (va = 0; va < (vaddr_t) (NBSG * NSEGMAP); va += NBSG) { 1910 /* Read the segmap entry from context zero... */ 1911 sme = get_segmap(va); 1912 /* ... then copy it into all other contexts. */ 1913 for (i = 1; i < NCONTEXT; i++) { 1914 (*rvec->setcxsegmap)(i, va, sme); 1915 } 1916 } 1917 #endif /* IS_SUN2 */ 1918 1919 /* 1920 * Reserve a segment for the kernel to use to access a pmeg 1921 * that is not currently mapped into any context/segmap. 1922 * The kernel temporarily maps such a pmeg into this segment. 1923 * 1924 * XXX SUN3: Now that context zero is reserved as kernel-only, 1925 * we could borrow context zero for these temporary uses. 1926 */ 1927 temp_seg_va = virtual_avail; 1928 virtual_avail += NBSG; 1929 #ifdef DIAGNOSTIC 1930 if (temp_seg_va & SEGOFSET) { 1931 prom_printf("pmap_bootstrap: temp_seg_va\n"); 1932 prom_abort(); 1933 } 1934 #endif 1935 1936 uvmexp.pagesize = PAGE_SIZE; 1937 uvm_md_init(); 1938 1939 /* after setting up some structures */ 1940 1941 pmap_common_init(kernel_pmap); 1942 pmap_kernel_init(kernel_pmap); 1943 1944 context_init(); 1945 1946 pmeg_clean_free(); 1947 1948 return nextpa; 1949 } 1950 1951 /* 1952 * Give the kernel pmap a segmap, just so there are not 1953 * so many special cases required. Maybe faster too, 1954 * because this lets pmap_remove() and pmap_protect() 1955 * use a S/W copy of the segmap to avoid function calls. 1956 */ 1957 void 1958 pmap_kernel_init(pmap_t pmap) 1959 { 1960 vaddr_t va; 1961 int i, sme; 1962 1963 for (i=0, va=0; i < NSEGMAP; i++, va+=NBSG) { 1964 sme = get_segmap(va); 1965 kernel_segmap[i] = sme; 1966 } 1967 pmap->pm_segmap = kernel_segmap; 1968 } 1969 1970 1971 /**************************************************************** 1972 * PMAP interface functions. 1973 */ 1974 1975 /* 1976 * Support functions for vm_page_bootstrap(). 1977 */ 1978 1979 /* 1980 * How much virtual space does this kernel have? 1981 * (After mapping kernel text, data, etc.) 1982 */ 1983 void 1984 pmap_virtual_space(vaddr_t *v_start, vaddr_t *v_end) 1985 { 1986 *v_start = virtual_avail; 1987 *v_end = virtual_end; 1988 } 1989 1990 /* 1991 * Initialize the pmap module. 1992 * Called by vm_init, to initialize any structures that the pmap 1993 * system needs to map virtual memory. 1994 */ 1995 void 1996 pmap_init(void) 1997 { 1998 pv_init(); 1999 2000 /* Initialize the pmap pool. */ 2001 pool_init(&pmap_pmap_pool, sizeof(struct pmap), 0, 0, 0, "pmappl", 2002 &pool_allocator_nointr, IPL_NONE); 2003 } 2004 2005 /* 2006 * Map a range of kernel virtual address space. 2007 * This might be used for device mappings, or to 2008 * record the mapping for kernel text/data/bss. 2009 * Return VA following the mapped range. 2010 */ 2011 vaddr_t 2012 pmap_map(vaddr_t va, paddr_t pa, paddr_t endpa, int prot) 2013 { 2014 int sz; 2015 2016 sz = endpa - pa; 2017 do { 2018 pmap_enter(kernel_pmap, va, pa, prot, 0); 2019 va += PAGE_SIZE; 2020 pa += PAGE_SIZE; 2021 sz -= PAGE_SIZE; 2022 } while (sz > 0); 2023 pmap_update(kernel_pmap); 2024 return(va); 2025 } 2026 2027 void 2028 pmap_user_init(pmap_t pmap) 2029 { 2030 int i; 2031 pmap->pm_segmap = kmem_alloc(sizeof(char)*NUSEG, KM_SLEEP); 2032 for (i = 0; i < NUSEG; i++) { 2033 pmap->pm_segmap[i] = SEGINV; 2034 } 2035 } 2036 2037 /* 2038 * Create and return a physical map. 2039 * 2040 * If the size specified for the map 2041 * is zero, the map is an actual physical 2042 * map, and may be referenced by the 2043 * hardware. 2044 * 2045 * If the size specified is non-zero, 2046 * the map will be used in software only, and 2047 * is bounded by that size. 2048 */ 2049 pmap_t 2050 pmap_create(void) 2051 { 2052 pmap_t pmap; 2053 2054 pmap = pool_get(&pmap_pmap_pool, PR_WAITOK); 2055 pmap_pinit(pmap); 2056 return pmap; 2057 } 2058 2059 /* 2060 * Release any resources held by the given physical map. 2061 * Called when a pmap initialized by pmap_pinit is being released. 2062 * Should only be called if the map contains no valid mappings. 2063 */ 2064 void 2065 pmap_release(struct pmap *pmap) 2066 { 2067 int s; 2068 2069 s = splvm(); 2070 2071 if (pmap == kernel_pmap) 2072 panic("pmap_release: kernel_pmap!"); 2073 2074 if (has_context(pmap)) { 2075 #ifdef PMAP_DEBUG 2076 if (pmap_debug & PMD_CONTEXT) 2077 printf("pmap_release(%p): free ctx %d\n", 2078 pmap, pmap->pm_ctxnum); 2079 #endif 2080 context_free(pmap); 2081 } 2082 kmem_free(pmap->pm_segmap, sizeof(char)*NUSEG); 2083 pmap->pm_segmap = NULL; 2084 2085 splx(s); 2086 } 2087 2088 2089 /* 2090 * Retire the given physical map from service. 2091 * Should only be called if the map contains 2092 * no valid mappings. 2093 */ 2094 void 2095 pmap_destroy(pmap_t pmap) 2096 { 2097 int count; 2098 2099 #ifdef PMAP_DEBUG 2100 if (pmap_debug & PMD_CREATE) 2101 printf("pmap_destroy(%p)\n", pmap); 2102 #endif 2103 if (pmap == kernel_pmap) 2104 panic("pmap_destroy: kernel_pmap!"); 2105 count = atomic_dec_uint_nv(&pmap->pm_refcount); 2106 if (count == 0) { 2107 pmap_release(pmap); 2108 pool_put(&pmap_pmap_pool, pmap); 2109 } 2110 } 2111 2112 /* 2113 * Add a reference to the specified pmap. 2114 */ 2115 void 2116 pmap_reference(pmap_t pmap) 2117 { 2118 2119 atomic_inc_uint(&pmap->pm_refcount); 2120 } 2121 2122 2123 /* 2124 * Insert the given physical page (p) at 2125 * the specified virtual address (v) in the 2126 * target physical map with the protection requested. 2127 * 2128 * The physical address is page aligned, but may have some 2129 * low bits set indicating an OBIO or VME bus page, or just 2130 * that the non-cache bit should be set (i.e PMAP_NC). 2131 * 2132 * If specified, the page will be wired down, meaning 2133 * that the related pte can not be reclaimed. 2134 * 2135 * NB: This is the only routine which MAY NOT lazy-evaluate 2136 * or lose information. That is, this routine must actually 2137 * insert this page into the given map NOW. 2138 */ 2139 int 2140 pmap_enter(pmap_t pmap, vaddr_t va, paddr_t pa, vm_prot_t prot, u_int flags) 2141 { 2142 int new_pte, s; 2143 bool wired = (flags & PMAP_WIRED) != 0; 2144 2145 #ifdef PMAP_DEBUG 2146 if ((pmap_debug & PMD_ENTER) || 2147 (va == pmap_db_watchva)) 2148 printf("pmap_enter(%p, 0x%lx, 0x%lx, 0x%x, 0x%x)\n", 2149 pmap, va, pa, prot, wired); 2150 #endif 2151 2152 /* Get page-type bits from low part of the PA... */ 2153 new_pte = (pa & PMAP_SPEC) << PG_MOD_SHIFT; 2154 2155 /* ...now the valid and writable bits... */ 2156 new_pte |= PG_VALID; 2157 if (prot & VM_PROT_WRITE) 2158 new_pte |= PG_WRITE; 2159 if (flags & VM_PROT_ALL) { 2160 new_pte |= PG_REF; 2161 if (flags & VM_PROT_WRITE) { 2162 new_pte |= PG_MOD; 2163 } 2164 } 2165 2166 /* ...and finally the page-frame number. */ 2167 new_pte |= PA_PGNUM(pa); 2168 2169 /* 2170 * treatment varies significantly: 2171 * kernel ptes are always in the mmu 2172 * user ptes may not necessarily? be in the mmu. pmap may not 2173 * be in the mmu either. 2174 */ 2175 s = splvm(); 2176 if (pmap == kernel_pmap) { 2177 new_pte |= PG_SYSTEM; 2178 pmap_enter_kernel(va, new_pte, wired); 2179 } else { 2180 pmap_enter_user(pmap, va, new_pte, wired); 2181 } 2182 splx(s); 2183 return 0; 2184 } 2185 2186 static void 2187 pmap_enter_kernel(vaddr_t pgva, int new_pte, bool wired) 2188 { 2189 pmap_t pmap = kernel_pmap; 2190 pmeg_t pmegp; 2191 int do_pv, old_pte, sme; 2192 vaddr_t segva; 2193 2194 /* 2195 * Kernel mappings are kept in hardware only. On Sun-2, it's 2196 * in context 0, on Sun-3, it's in all contexts. The only 2197 * thing we have to handle here is possibly allocating additional 2198 * PMEGs and inserting them into the appropriate contexts. 2199 */ 2200 2201 /* 2202 * In detail: 2203 * 2204 * (a) lock pmap 2205 * (b) Is the VA in a already mapped segment, if so 2206 * look to see if that VA address is "valid". If it is, then 2207 * action is a change to an existing pte 2208 * (c) if not mapped segment, need to allocate pmeg 2209 * (d) if adding pte entry or changing physaddr of existing one, 2210 * use pv_stuff, for change, pmap_remove() possibly. 2211 * (e) change/add pte 2212 */ 2213 kernel_context_enter(); 2214 2215 #ifdef DIAGNOSTIC 2216 if ((pgva < virtual_avail) || (pgva >= DVMA_MAP_END)) 2217 panic("pmap_enter_kernel: bad va=0x%lx", pgva); 2218 if ((new_pte & (PG_VALID | PG_SYSTEM)) != (PG_VALID | PG_SYSTEM)) 2219 panic("pmap_enter_kernel: bad pte"); 2220 #endif 2221 2222 if (pgva >= DVMA_MAP_BASE) { 2223 /* This is DVMA space. Always want it non-cached. */ 2224 new_pte |= PG_NC; 2225 } 2226 2227 segva = sun_trunc_seg(pgva); 2228 do_pv = true; 2229 2230 /* Do we have a PMEG? */ 2231 sme = get_segmap(segva); 2232 if (sme != SEGINV) { 2233 /* Found a PMEG in the segmap. Cool. */ 2234 pmegp = pmeg_p(sme); 2235 #ifdef DIAGNOSTIC 2236 /* Make sure it is the right PMEG. */ 2237 if (sme != pmap->pm_segmap[VA_SEGNUM(segva)]) 2238 panic("pmap_enter_kernel: wrong sme at VA=0x%lx", 2239 segva); 2240 /* Make sure it is ours. */ 2241 if (pmegp->pmeg_owner != pmap) 2242 panic("pmap_enter_kernel: MMU has bad pmeg 0x%x", sme); 2243 #endif 2244 } else { 2245 /* No PMEG in the segmap. Have to allocate one. */ 2246 pmegp = pmeg_allocate(pmap, segva); 2247 sme = pmegp->pmeg_index; 2248 pmap->pm_segmap[VA_SEGNUM(segva)] = sme; 2249 set_kernel_segmap(segva, sme); 2250 #ifdef PMAP_DEBUG 2251 pmeg_verify_empty(segva); 2252 if (pmap_debug & PMD_SEGMAP) { 2253 printf("pmap: set_segmap pmap=%p va=0x%lx sme=0x%x " 2254 "(ek)\n", pmap, segva, sme); 2255 } 2256 #endif 2257 /* There are no existing mappings to deal with. */ 2258 old_pte = 0; 2259 goto add_pte; 2260 } 2261 2262 /* 2263 * We have a PMEG. Is the VA already mapped to somewhere? 2264 * (a) if so, is it same pa? (really a protection change) 2265 * (b) if not same pa, then we have to unlink from old pa 2266 */ 2267 old_pte = get_pte(pgva); 2268 if ((old_pte & PG_VALID) == 0) 2269 goto add_pte; 2270 2271 /* Have valid translation. Flush cache before changing it. */ 2272 #ifdef HAVECACHE 2273 if (cache_size) { 2274 cache_flush_page(pgva); 2275 /* Get fresh mod/ref bits from write-back. */ 2276 old_pte = get_pte(pgva); 2277 } 2278 #endif 2279 2280 /* XXX - removing valid page here, way lame... -glass */ 2281 pmegp->pmeg_vpages--; 2282 2283 if (!IS_MAIN_MEM(old_pte)) { 2284 /* Was not main memory, so no pv_entry for it. */ 2285 goto add_pte; 2286 } 2287 2288 /* Old mapping was main memory. Save mod/ref bits. */ 2289 save_modref_bits(old_pte); 2290 2291 /* 2292 * If not changing the type or pfnum then re-use pv_entry. 2293 * Note we get here only with old_pte having PGT_OBMEM. 2294 */ 2295 if ((old_pte & (PG_TYPE|PG_FRAME)) == (new_pte & (PG_TYPE|PG_FRAME))) { 2296 do_pv = false; /* re-use pv_entry */ 2297 new_pte |= (old_pte & PG_NC); 2298 goto add_pte; 2299 } 2300 2301 /* OK, different type or PA, have to kill old pv_entry. */ 2302 pv_unlink(pmap, old_pte, pgva); 2303 2304 add_pte: /* can be destructive */ 2305 pmeg_set_wiring(pmegp, pgva, wired); 2306 2307 /* Anything but MAIN_MEM is mapped non-cached. */ 2308 if (!IS_MAIN_MEM(new_pte)) { 2309 new_pte |= PG_NC; 2310 do_pv = false; 2311 } 2312 if (do_pv == true) { 2313 if (pv_link(pmap, new_pte, pgva) & PV_NC) 2314 new_pte |= PG_NC; 2315 } 2316 #ifdef PMAP_DEBUG 2317 if ((pmap_debug & PMD_SETPTE) || (pgva == pmap_db_watchva)) { 2318 printf("pmap: set_pte pmap=%p va=0x%lx old=0x%x new=0x%x " 2319 "(ek)\n", pmap, pgva, old_pte, new_pte); 2320 } 2321 #endif 2322 /* cache flush done above */ 2323 set_pte(pgva, new_pte); 2324 kernel_context_exit(); 2325 pmegp->pmeg_vpages++; 2326 } 2327 2328 2329 static void 2330 pmap_enter_user(pmap_t pmap, vaddr_t pgva, int new_pte, bool wired) 2331 { 2332 int do_pv, old_pte, sme; 2333 vaddr_t segva; 2334 pmeg_t pmegp; 2335 2336 #ifdef DIAGNOSTIC 2337 if (pgva >= VM_MAXUSER_ADDRESS) 2338 panic("pmap_enter_user: bad va=0x%lx", pgva); 2339 if ((new_pte & (PG_VALID | PG_SYSTEM)) != PG_VALID) 2340 panic("pmap_enter_user: bad pte"); 2341 #endif 2342 #ifdef PMAP_DEBUG 2343 /* 2344 * Some user pages are wired here, and a later 2345 * call to pmap_unwire() will unwire them. 2346 * XXX - Need a separate list for wired user pmegs 2347 * so they can not be stolen from the active list. 2348 * XXX - Note: vm_fault.c assumes pmap_extract will 2349 * work on wired mappings, so must preserve them... 2350 * XXX: Maybe keep a list of wired PMEGs? 2351 */ 2352 if (wired && (pmap_debug & PMD_WIRING)) { 2353 db_printf("pmap_enter_user: attempt to wire user page, " 2354 "ignored\n"); 2355 Debugger(); 2356 } 2357 #endif 2358 2359 /* Validate this assumption. */ 2360 if (pmap != current_pmap()) { 2361 #ifdef PMAP_DEBUG 2362 /* Apparently, this never happens. */ 2363 db_printf("pmap_enter_user: not curlwp\n"); 2364 Debugger(); 2365 #endif 2366 /* Just throw it out (fault it in later). */ 2367 /* XXX: But must remember it if wired... */ 2368 return; 2369 } 2370 2371 segva = sun_trunc_seg(pgva); 2372 do_pv = true; 2373 2374 /* 2375 * If this pmap was sharing the "empty" context, 2376 * allocate a real context for its exclusive use. 2377 */ 2378 if (!has_context(pmap)) { 2379 context_allocate(pmap); 2380 #ifdef PMAP_DEBUG 2381 if (pmap_debug & PMD_CONTEXT) 2382 printf("pmap_enter(%p) got context %d\n", 2383 pmap, pmap->pm_ctxnum); 2384 #endif 2385 set_context(pmap->pm_ctxnum); 2386 } else { 2387 #ifdef PMAP_DEBUG 2388 /* Make sure context is correct. */ 2389 if (pmap->pm_ctxnum != get_context()) { 2390 db_printf("pmap_enter_user: wrong context\n"); 2391 Debugger(); 2392 /* XXX: OK to proceed? */ 2393 set_context(pmap->pm_ctxnum); 2394 } 2395 #endif 2396 } 2397 2398 /* 2399 * We have a context. Do we have a PMEG? 2400 */ 2401 sme = get_segmap(segva); 2402 if (sme != SEGINV) { 2403 /* Found a PMEG in the segmap. Cool. */ 2404 pmegp = pmeg_p(sme); 2405 #ifdef DIAGNOSTIC 2406 /* Make sure it is the right PMEG. */ 2407 if (sme != pmap->pm_segmap[VA_SEGNUM(segva)]) 2408 panic("pmap_enter_user: wrong sme at VA=0x%lx", segva); 2409 /* Make sure it is ours. */ 2410 if (pmegp->pmeg_owner != pmap) 2411 panic("pmap_enter_user: MMU has bad pmeg 0x%x", sme); 2412 #endif 2413 } else { 2414 /* Not in the segmap. Try the S/W cache. */ 2415 pmegp = pmeg_cache(pmap, segva); 2416 if (pmegp) { 2417 /* Found PMEG in cache. Just reload it. */ 2418 sme = pmegp->pmeg_index; 2419 set_segmap(segva, sme); 2420 } else { 2421 /* PMEG not in cache, so allocate one. */ 2422 pmegp = pmeg_allocate(pmap, segva); 2423 sme = pmegp->pmeg_index; 2424 pmap->pm_segmap[VA_SEGNUM(segva)] = sme; 2425 set_segmap(segva, sme); 2426 #ifdef PMAP_DEBUG 2427 pmeg_verify_empty(segva); 2428 #endif 2429 } 2430 #ifdef PMAP_DEBUG 2431 if (pmap_debug & PMD_SEGMAP) { 2432 printf("pmap: set_segmap pmap=%p va=0x%lx sme=0x%x " 2433 "(eu)\n", pmap, segva, sme); 2434 } 2435 #endif 2436 } 2437 2438 /* 2439 * We have a PMEG. Is the VA already mapped to somewhere? 2440 * (a) if so, is it same pa? (really a protection change) 2441 * (b) if not same pa, then we have to unlink from old pa 2442 */ 2443 old_pte = get_pte(pgva); 2444 if ((old_pte & PG_VALID) == 0) 2445 goto add_pte; 2446 2447 /* Have valid translation. Flush cache before changing it. */ 2448 #ifdef HAVECACHE 2449 if (cache_size) { 2450 cache_flush_page(pgva); 2451 /* Get fresh mod/ref bits from write-back. */ 2452 old_pte = get_pte(pgva); 2453 } 2454 #endif 2455 2456 /* XXX - removing valid page here, way lame... -glass */ 2457 pmegp->pmeg_vpages--; 2458 2459 if (!IS_MAIN_MEM(old_pte)) { 2460 /* Was not main memory, so no pv_entry for it. */ 2461 goto add_pte; 2462 } 2463 2464 /* Old mapping was main memory. Save mod/ref bits. */ 2465 save_modref_bits(old_pte); 2466 2467 /* 2468 * If not changing the type or pfnum then re-use pv_entry. 2469 * Note we get here only with old_pte having PGT_OBMEM. 2470 */ 2471 if ((old_pte & (PG_TYPE|PG_FRAME)) == (new_pte & (PG_TYPE|PG_FRAME))) { 2472 do_pv = false; /* re-use pv_entry */ 2473 new_pte |= (old_pte & PG_NC); 2474 goto add_pte; 2475 } 2476 2477 /* OK, different type or PA, have to kill old pv_entry. */ 2478 pv_unlink(pmap, old_pte, pgva); 2479 2480 add_pte: 2481 /* XXX - Wiring changes on user pmaps? */ 2482 /* pmeg_set_wiring(pmegp, pgva, wired); */ 2483 2484 /* Anything but MAIN_MEM is mapped non-cached. */ 2485 if (!IS_MAIN_MEM(new_pte)) { 2486 new_pte |= PG_NC; 2487 do_pv = false; 2488 } 2489 if (do_pv == true) { 2490 if (pv_link(pmap, new_pte, pgva) & PV_NC) 2491 new_pte |= PG_NC; 2492 } 2493 #ifdef PMAP_DEBUG 2494 if ((pmap_debug & PMD_SETPTE) || (pgva == pmap_db_watchva)) { 2495 printf("pmap: set_pte pmap=%p va=0x%lx old=0x%x new=0x%x " 2496 "(eu)\n", pmap, pgva, old_pte, new_pte); 2497 } 2498 #endif 2499 /* cache flush done above */ 2500 set_pte(pgva, new_pte); 2501 pmegp->pmeg_vpages++; 2502 } 2503 2504 void 2505 pmap_kenter_pa(vaddr_t va, paddr_t pa, vm_prot_t prot, u_int flags) 2506 { 2507 int new_pte, s; 2508 pmap_t pmap = kernel_pmap; 2509 pmeg_t pmegp; 2510 int sme; 2511 vaddr_t segva; 2512 2513 #ifdef PMAP_DEBUG 2514 if ((pmap_debug & PMD_ENTER) || 2515 (va == pmap_db_watchva)) 2516 printf("pmap_kenter_pa(0x%lx, 0x%lx, 0x%x)\n", 2517 va, pa, prot); 2518 #endif 2519 2520 /* Get page-type bits from low part of the PA... */ 2521 new_pte = (pa & PMAP_SPEC) << PG_MOD_SHIFT; 2522 2523 /* ...now the valid and writable bits... */ 2524 new_pte |= PG_SYSTEM|PG_VALID; 2525 if (prot & VM_PROT_WRITE) 2526 new_pte |= PG_WRITE; 2527 2528 /* ...and finally the page-frame number. */ 2529 new_pte |= PA_PGNUM(pa); 2530 2531 /* 2532 * Kernel mappings are kept in hardware only. On Sun-2, it's 2533 * in context 0, on Sun-3, it's in all contexts. The only 2534 * thing we have to handle here is possibly allocating additional 2535 * PMEGs and inserting them into the appropriate contexts. 2536 */ 2537 kernel_context_enter(); 2538 2539 /* 2540 * In detail: 2541 * 2542 * (a) lock pmap 2543 * (b) Is the VA in a already mapped segment, if so 2544 * look to see if that VA address is "valid". If it is, then 2545 * action is a change to an existing pte 2546 * (c) if not mapped segment, need to allocate pmeg 2547 * (d) change/add pte 2548 */ 2549 2550 #ifdef DIAGNOSTIC 2551 if ((va < virtual_avail) || (va >= DVMA_MAP_END)) 2552 panic("pmap_kenter_pa: bad va=0x%lx", va); 2553 #endif 2554 2555 if (va >= DVMA_MAP_BASE) { 2556 /* This is DVMA space. Always want it non-cached. */ 2557 new_pte |= PG_NC; 2558 } 2559 2560 segva = sun_trunc_seg(va); 2561 2562 s = splvm(); 2563 2564 /* Do we have a PMEG? */ 2565 sme = get_segmap(segva); 2566 if (sme != SEGINV) { 2567 KASSERT((get_pte(va) & PG_VALID) == 0); 2568 2569 /* Found a PMEG in the segmap. Cool. */ 2570 pmegp = pmeg_p(sme); 2571 #ifdef DIAGNOSTIC 2572 /* Make sure it is the right PMEG. */ 2573 if (sme != pmap->pm_segmap[VA_SEGNUM(segva)]) 2574 panic("pmap_kenter_pa: wrong sme at VA=0x%lx", segva); 2575 /* Make sure it is ours. */ 2576 if (pmegp->pmeg_owner != pmap) 2577 panic("pmap_kenter_pa: MMU has bad pmeg 0x%x", sme); 2578 #endif 2579 } else { 2580 2581 /* No PMEG in the segmap. Have to allocate one. */ 2582 pmegp = pmeg_allocate(pmap, segva); 2583 sme = pmegp->pmeg_index; 2584 pmap->pm_segmap[VA_SEGNUM(segva)] = sme; 2585 set_kernel_segmap(segva, sme); 2586 #ifdef PMAP_DEBUG 2587 pmeg_verify_empty(segva); 2588 if (pmap_debug & PMD_SEGMAP) { 2589 printf("pmap: set_segmap pmap=%p va=0x%lx sme=0x%x " 2590 "(ek)\n", pmap, segva, sme); 2591 } 2592 #endif 2593 } 2594 2595 pmeg_set_wiring(pmegp, va, true); 2596 2597 /* Anything but MAIN_MEM is mapped non-cached. */ 2598 if (!IS_MAIN_MEM(new_pte)) { 2599 new_pte |= PG_NC; 2600 } 2601 #ifdef PMAP_DEBUG 2602 if ((pmap_debug & PMD_SETPTE) || (va == pmap_db_watchva)) { 2603 printf("pmap: set_pte pmap=%p va=0x%lx new=0x%x " 2604 "(ek)\n", pmap, va, new_pte); 2605 } 2606 #endif 2607 /* cache flush done above */ 2608 set_pte(va, new_pte); 2609 kernel_context_exit(); 2610 pmegp->pmeg_vpages++; 2611 splx(s); 2612 } 2613 2614 void 2615 pmap_kremove(vaddr_t va, vsize_t len) 2616 { 2617 pmap_t pmap = kernel_pmap; 2618 vaddr_t eva, neva, pgva, segva, segnum; 2619 int pte, sme; 2620 pmeg_t pmegp; 2621 #ifdef HAVECACHE 2622 int flush_by_page = 0; 2623 #endif 2624 int s; 2625 2626 s = splvm(); 2627 kernel_context_enter(); 2628 segnum = VA_SEGNUM(va); 2629 for (eva = va + len; va < eva; va = neva, segnum++) { 2630 neva = sun_trunc_seg(va) + NBSG; 2631 if (neva > eva) { 2632 neva = eva; 2633 } 2634 if (pmap->pm_segmap[segnum] == SEGINV) { 2635 continue; 2636 } 2637 2638 segva = sun_trunc_seg(va); 2639 sme = get_segmap(segva); 2640 pmegp = pmeg_p(sme); 2641 2642 #ifdef HAVECACHE 2643 if (cache_size) { 2644 2645 /* 2646 * If the range to be removed is larger than the cache, 2647 * it will be cheaper to flush this segment entirely. 2648 */ 2649 2650 if (cache_size < (eva - va)) { 2651 /* cheaper to flush whole segment */ 2652 cache_flush_segment(segva); 2653 } else { 2654 flush_by_page = 1; 2655 } 2656 } 2657 #endif 2658 2659 /* Invalidate the PTEs in the given range. */ 2660 for (pgva = va; pgva < neva; pgva += PAGE_SIZE) { 2661 pte = get_pte(pgva); 2662 if (pte & PG_VALID) { 2663 #ifdef HAVECACHE 2664 if (flush_by_page) { 2665 cache_flush_page(pgva); 2666 /* Get fresh mod/ref bits 2667 from write-back. */ 2668 pte = get_pte(pgva); 2669 } 2670 #endif 2671 #ifdef PMAP_DEBUG 2672 if ((pmap_debug & PMD_SETPTE) || 2673 (pgva == pmap_db_watchva)) { 2674 printf("pmap: set_pte pmap=%p va=0x%lx" 2675 " old=0x%x new=0x%x (rrmmu)\n", 2676 pmap, pgva, pte, PG_INVAL); 2677 } 2678 #endif 2679 set_pte(pgva, PG_INVAL); 2680 KASSERT(pmegp->pmeg_vpages > 0); 2681 pmegp->pmeg_vpages--; 2682 } 2683 } 2684 KASSERT(pmegp->pmeg_vpages >= 0); 2685 if (pmegp->pmeg_vpages == 0) { 2686 /* We are done with this pmeg. */ 2687 #ifdef PMAP_DEBUG 2688 if (is_pmeg_wired(pmegp)) { 2689 if (pmap_debug & PMD_WIRING) { 2690 db_printf("pmap: removing wired " 2691 "pmeg: %p\n", pmegp); 2692 Debugger(); 2693 } 2694 } 2695 if (pmap_debug & PMD_SEGMAP) { 2696 printf("pmap: set_segmap ctx=%d v=0x%lx " 2697 "old=0x%x new=ff (rm)\n", 2698 pmap->pm_ctxnum, segva, 2699 pmegp->pmeg_index); 2700 } 2701 pmeg_verify_empty(segva); 2702 #endif 2703 2704 /* Remove it from the MMU. */ 2705 set_kernel_segmap(segva, SEGINV); 2706 pmap->pm_segmap[VA_SEGNUM(segva)] = SEGINV; 2707 2708 /* Now, put it on the free list. */ 2709 pmeg_free(pmegp); 2710 } 2711 } 2712 kernel_context_exit(); 2713 splx(s); 2714 } 2715 2716 2717 /* 2718 * The trap handler calls this so we can try to resolve 2719 * user-level faults by reloading a PMEG. 2720 * If that does not prodce a valid mapping, 2721 * call vm_fault as usual. 2722 * 2723 * XXX: Merge this with the next function? 2724 */ 2725 int 2726 pmap_fault(struct vm_map *map, vaddr_t va, vm_prot_t ftype) 2727 { 2728 pmap_t pmap; 2729 int rv; 2730 2731 pmap = vm_map_pmap(map); 2732 if (map == kernel_map) { 2733 /* Do not allow faults below the "managed" space. */ 2734 if (va < virtual_avail) { 2735 /* 2736 * Most pages below virtual_avail are read-only, 2737 * so I will assume it is a protection failure. 2738 */ 2739 return EACCES; 2740 } 2741 } else { 2742 /* User map. Try reload shortcut. */ 2743 if (pmap_fault_reload(pmap, va, ftype)) 2744 return 0; 2745 } 2746 rv = uvm_fault(map, va, ftype); 2747 2748 #ifdef PMAP_DEBUG 2749 if (pmap_debug & PMD_FAULT) { 2750 printf("pmap_fault(%p, 0x%lx, 0x%x) -> 0x%x\n", 2751 map, va, ftype, rv); 2752 } 2753 #endif 2754 2755 return (rv); 2756 } 2757 2758 /* 2759 * This is a shortcut used by the trap handler to 2760 * reload PMEGs into a user segmap without calling 2761 * the actual VM fault handler. Returns true if: 2762 * the PMEG was reloaded, and 2763 * it has a valid PTE at va. 2764 * Otherwise return zero and let VM code handle it. 2765 */ 2766 int 2767 pmap_fault_reload(pmap_t pmap, vaddr_t pgva, vm_prot_t ftype) 2768 { 2769 int rv, s, pte, chkpte, sme; 2770 vaddr_t segva; 2771 pmeg_t pmegp; 2772 2773 if (pgva >= VM_MAXUSER_ADDRESS) 2774 return (0); 2775 if (pmap->pm_segmap == NULL) { 2776 #ifdef PMAP_DEBUG 2777 db_printf("pmap_fault_reload: null segmap\n"); 2778 Debugger(); 2779 #endif 2780 return (0); 2781 } 2782 2783 /* Short-cut using the S/W segmap. */ 2784 if (pmap->pm_segmap[VA_SEGNUM(pgva)] == SEGINV) 2785 return (0); 2786 2787 segva = sun_trunc_seg(pgva); 2788 chkpte = PG_VALID; 2789 if (ftype & VM_PROT_WRITE) 2790 chkpte |= PG_WRITE; 2791 rv = 0; 2792 2793 s = splvm(); 2794 2795 /* 2796 * Given that we faulted on a user-space address, we will 2797 * probably need a context. Get a context now so we can 2798 * try to resolve the fault with a segmap reload. 2799 */ 2800 if (!has_context(pmap)) { 2801 context_allocate(pmap); 2802 #ifdef PMAP_DEBUG 2803 if (pmap_debug & PMD_CONTEXT) 2804 printf("pmap_fault(%p) got context %d\n", 2805 pmap, pmap->pm_ctxnum); 2806 #endif 2807 set_context(pmap->pm_ctxnum); 2808 } else { 2809 #ifdef PMAP_DEBUG 2810 /* Make sure context is correct. */ 2811 if (pmap->pm_ctxnum != get_context()) { 2812 db_printf("pmap_fault_reload: wrong context\n"); 2813 Debugger(); 2814 /* XXX: OK to proceed? */ 2815 set_context(pmap->pm_ctxnum); 2816 } 2817 #endif 2818 } 2819 2820 sme = get_segmap(segva); 2821 if (sme == SEGINV) { 2822 /* See if there is something to reload. */ 2823 pmegp = pmeg_cache(pmap, segva); 2824 if (pmegp) { 2825 /* Found one! OK, reload it. */ 2826 pmap_stats.ps_pmeg_faultin++; 2827 sme = pmegp->pmeg_index; 2828 set_segmap(segva, sme); 2829 pte = get_pte(pgva); 2830 if (pte & chkpte) 2831 rv = 1; 2832 } 2833 } 2834 2835 splx(s); 2836 return (rv); 2837 } 2838 2839 2840 /* 2841 * Clear the modify bit for the given physical page. 2842 */ 2843 bool 2844 pmap_clear_modify(struct vm_page *pg) 2845 { 2846 paddr_t pa = VM_PAGE_TO_PHYS(pg); 2847 pv_entry_t *head; 2848 u_char *pv_flags; 2849 int s; 2850 bool rv; 2851 2852 pv_flags = pa_to_pvflags(pa); 2853 head = pa_to_pvhead(pa); 2854 2855 s = splvm(); 2856 *pv_flags |= pv_syncflags(*head); 2857 rv = *pv_flags & PV_MOD; 2858 *pv_flags &= ~PV_MOD; 2859 splx(s); 2860 return rv; 2861 } 2862 2863 /* 2864 * Tell whether the given physical page has been modified. 2865 */ 2866 bool 2867 pmap_is_modified(struct vm_page *pg) 2868 { 2869 paddr_t pa = VM_PAGE_TO_PHYS(pg); 2870 pv_entry_t *head; 2871 u_char *pv_flags; 2872 int s; 2873 bool rv; 2874 2875 pv_flags = pa_to_pvflags(pa); 2876 head = pa_to_pvhead(pa); 2877 2878 s = splvm(); 2879 if ((*pv_flags & PV_MOD) == 0) 2880 *pv_flags |= pv_syncflags(*head); 2881 rv = (*pv_flags & PV_MOD); 2882 splx(s); 2883 return (rv); 2884 } 2885 2886 /* 2887 * Clear the reference bit for the given physical page. 2888 * It's OK to just remove mappings if that's easier. 2889 */ 2890 bool 2891 pmap_clear_reference(struct vm_page *pg) 2892 { 2893 paddr_t pa = VM_PAGE_TO_PHYS(pg); 2894 pv_entry_t *head; 2895 u_char *pv_flags; 2896 int s; 2897 bool rv; 2898 2899 pv_flags = pa_to_pvflags(pa); 2900 head = pa_to_pvhead(pa); 2901 2902 s = splvm(); 2903 *pv_flags |= pv_syncflags(*head); 2904 rv = *pv_flags & PV_REF; 2905 *pv_flags &= ~PV_REF; 2906 splx(s); 2907 return rv; 2908 } 2909 2910 /* 2911 * Tell whether the given physical page has been referenced. 2912 * It's OK to just return false if page is not mapped. 2913 */ 2914 bool 2915 pmap_is_referenced(struct vm_page *pg) 2916 { 2917 paddr_t pa = VM_PAGE_TO_PHYS(pg); 2918 pv_entry_t *head; 2919 u_char *pv_flags; 2920 int s; 2921 bool rv; 2922 2923 pv_flags = pa_to_pvflags(pa); 2924 head = pa_to_pvhead(pa); 2925 2926 s = splvm(); 2927 if ((*pv_flags & PV_REF) == 0) 2928 *pv_flags |= pv_syncflags(*head); 2929 rv = (*pv_flags & PV_REF); 2930 splx(s); 2931 return (rv); 2932 } 2933 2934 2935 static inline void 2936 _pmap_switch(pmap_t pmap) 2937 { 2938 #if IS_SUN2 2939 /* 2940 * Since we maintain completely separate user and kernel address 2941 * spaces, whenever we switch to a process, we need to make sure 2942 * that it has a context allocated. 2943 */ 2944 if (!has_context(pmap)) { 2945 context_allocate(pmap); 2946 #ifdef PMAP_DEBUG 2947 if (pmap_debug & PMD_CONTEXT) 2948 printf("_pmap_switch(%p) got context %d\n", 2949 pmap, pmap->pm_ctxnum); 2950 #endif 2951 } 2952 #endif /* IS_SUN2 */ 2953 set_context(pmap->pm_ctxnum); 2954 ICIA(); 2955 } 2956 2957 /* 2958 * Exported version of pmap_activate(). This is called from the 2959 * machine-independent VM code when a process is given a new pmap. 2960 * If (p == curlwp) do like cpu_switch would do; otherwise just 2961 * take this as notification that the process has a new pmap. 2962 */ 2963 void 2964 pmap_activate(struct lwp *l) 2965 { 2966 pmap_t pmap = l->l_proc->p_vmspace->vm_map.pmap; 2967 2968 if (l->l_proc == curproc) { 2969 _pmap_switch(pmap); 2970 } 2971 } 2972 2973 /* 2974 * Deactivate the address space of the specified process. 2975 */ 2976 void 2977 pmap_deactivate(struct lwp *l) 2978 { 2979 /* Nothing to do. */ 2980 } 2981 2982 /* 2983 * Routine: pmap_unwire 2984 * Function: Clear the wired attribute for a map/virtual-address 2985 * pair. 2986 * In/out conditions: 2987 * The mapping must already exist in the pmap. 2988 */ 2989 void 2990 pmap_unwire(pmap_t pmap, vaddr_t va) 2991 { 2992 int s, sme; 2993 int wiremask, ptenum; 2994 pmeg_t pmegp; 2995 2996 #ifdef PMAP_DEBUG 2997 if (pmap_debug & PMD_WIRING) 2998 printf("pmap_unwire(pmap=%p, va=0x%lx)\n", 2999 pmap, va); 3000 #endif 3001 /* 3002 * We are asked to unwire pages that were wired when 3003 * pmap_enter() was called and we ignored wiring. 3004 * (VM code appears to wire a stack page during fork.) 3005 */ 3006 if (pmap != kernel_pmap) { 3007 #ifdef PMAP_DEBUG 3008 if (pmap_debug & PMD_WIRING) { 3009 db_printf(" (user pmap -- ignored)\n"); 3010 Debugger(); 3011 } 3012 #endif 3013 return; 3014 } 3015 3016 ptenum = VA_PTE_NUM(va); 3017 wiremask = 1 << ptenum; 3018 3019 s = splvm(); 3020 kernel_context_enter(); 3021 sme = get_segmap(va); 3022 kernel_context_exit(); 3023 pmegp = pmeg_p(sme); 3024 pmegp->pmeg_wired &= ~wiremask; 3025 splx(s); 3026 } 3027 3028 /* 3029 * Copy the range specified by src_addr/len 3030 * from the source map to the range dst_addr/len 3031 * in the destination map. 3032 * 3033 * This routine is only advisory and need not do anything. 3034 */ 3035 void 3036 pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vaddr_t dst_addr, vsize_t len, 3037 vaddr_t src_addr) 3038 { 3039 } 3040 3041 /* 3042 * Routine: pmap_extract 3043 * Function: 3044 * Extract the physical page address associated 3045 * with the given map/virtual_address pair. 3046 * Returns zero if VA not valid. 3047 */ 3048 bool 3049 pmap_extract(pmap_t pmap, vaddr_t va, paddr_t *pap) 3050 { 3051 int s, sme, segnum, ptenum, pte; 3052 paddr_t pa; 3053 3054 pte = 0; 3055 s = splvm(); 3056 if (pmap == kernel_pmap) { 3057 kernel_context_enter(); 3058 sme = get_segmap(va); 3059 if (sme != SEGINV) 3060 pte = get_pte(va); 3061 kernel_context_exit(); 3062 } else { 3063 /* This is rare, so do it the easy way. */ 3064 segnum = VA_SEGNUM(va); 3065 sme = pmap->pm_segmap[segnum]; 3066 if (sme != SEGINV) { 3067 ptenum = VA_PTE_NUM(va); 3068 pte = get_pte_pmeg(sme, ptenum); 3069 } 3070 } 3071 splx(s); 3072 3073 if ((pte & PG_VALID) == 0) { 3074 #ifdef PMAP_DEBUG 3075 db_printf("pmap_extract: invalid va=0x%lx\n", va); 3076 Debugger(); 3077 #endif 3078 return (false); 3079 } 3080 pa = PG_PA(pte); 3081 #ifdef DIAGNOSTIC 3082 if (pte & PG_TYPE) { 3083 panic("pmap_extract: not main mem, va=0x%lx", va); 3084 } 3085 #endif 3086 if (pap != NULL) 3087 *pap = pa; 3088 return (true); 3089 } 3090 3091 /* 3092 * pmap_phys_address: 3093 * 3094 * Return the physical address corresponding to the specified 3095 * cookie. Used by the device pager to decode a device driver's 3096 * mmap entry point return value. 3097 */ 3098 paddr_t 3099 pmap_phys_address(paddr_t addr) 3100 { 3101 return addr; 3102 } 3103 3104 /* 3105 * pmap_page_protect: 3106 * 3107 * Lower the permission for all mappings to a given page. 3108 */ 3109 void 3110 pmap_page_protect(struct vm_page *pg, vm_prot_t prot) 3111 { 3112 paddr_t pa = VM_PAGE_TO_PHYS(pg); 3113 int s; 3114 3115 s = splvm(); 3116 #ifdef PMAP_DEBUG 3117 if (pmap_debug & PMD_PROTECT) 3118 printf("pmap_page_protect(0x%lx, 0x%x)\n", pa, prot); 3119 #endif 3120 switch (prot) { 3121 case VM_PROT_ALL: 3122 break; 3123 case VM_PROT_READ: 3124 case VM_PROT_READ|VM_PROT_EXECUTE: 3125 pv_changepte(pa, 0, PG_WRITE); 3126 break; 3127 default: 3128 /* remove mapping for all pmaps that have it */ 3129 pv_remove_all(pa); 3130 break; 3131 } 3132 splx(s); 3133 } 3134 3135 /* 3136 * Initialize a preallocated and zeroed pmap structure, 3137 * such as one in a vmspace structure. 3138 */ 3139 void 3140 pmap_pinit(pmap_t pmap) 3141 { 3142 pmap_common_init(pmap); 3143 pmap_user_init(pmap); 3144 } 3145 3146 /* 3147 * Reduce the permissions on the specified 3148 * range of this map as requested. 3149 * (Make pages read-only.) 3150 */ 3151 void 3152 pmap_protect(pmap_t pmap, vaddr_t sva, vaddr_t eva, vm_prot_t prot) 3153 { 3154 vaddr_t va, neva; 3155 int segnum; 3156 3157 /* If leaving writable, nothing to do. */ 3158 if (prot & VM_PROT_WRITE) 3159 return; 3160 3161 /* If removing all permissions, just unmap. */ 3162 if ((prot & VM_PROT_READ) == 0) { 3163 pmap_remove(pmap, sva, eva); 3164 return; 3165 } 3166 3167 #ifdef PMAP_DEBUG 3168 if ((pmap_debug & PMD_PROTECT) || 3169 ((sva <= pmap_db_watchva && eva > pmap_db_watchva))) 3170 printf("pmap_protect(%p, 0x%lx, 0x%lx)\n", pmap, sva, eva); 3171 #endif 3172 3173 KASSERT((pmap == kernel_pmap) ? 3174 sva >= virtual_avail && eva < DVMA_MAP_END : 3175 eva <= VM_MAXUSER_ADDRESS); 3176 va = sva; 3177 segnum = VA_SEGNUM(va); 3178 while (va < eva) { 3179 neva = sun_trunc_seg(va) + NBSG; 3180 if (neva > eva) 3181 neva = eva; 3182 if (pmap->pm_segmap[segnum] != SEGINV) 3183 pmap_protect1(pmap, va, neva); 3184 va = neva; 3185 segnum++; 3186 } 3187 } 3188 3189 /* 3190 * Remove write permissions in given range. 3191 * (guaranteed to be within one segment) 3192 * similar to pmap_remove1() 3193 */ 3194 void 3195 pmap_protect1(pmap_t pmap, vaddr_t sva, vaddr_t eva) 3196 { 3197 int old_ctx, s, sme; 3198 bool in_ctx; 3199 3200 s = splvm(); 3201 3202 #ifdef DIAGNOSTIC 3203 if (sun_trunc_seg(sva) != sun_trunc_seg(eva-1)) 3204 panic("pmap_protect1: bad range!"); 3205 #endif 3206 3207 if (pmap == kernel_pmap) { 3208 kernel_context_enter(); 3209 sme = get_segmap(sva); 3210 if (sme != SEGINV) 3211 pmap_protect_mmu(pmap, sva, eva); 3212 kernel_context_exit(); 3213 goto out; 3214 } 3215 /* It is a user pmap. */ 3216 3217 /* There is a PMEG, but maybe not active. */ 3218 old_ctx = INVALID_CONTEXT; 3219 in_ctx = false; 3220 if (has_context(pmap)) { 3221 /* Temporary context change. */ 3222 old_ctx = get_context(); 3223 set_context(pmap->pm_ctxnum); 3224 sme = get_segmap(sva); 3225 if (sme != SEGINV) 3226 in_ctx = true; 3227 } 3228 3229 if (in_ctx == true) 3230 pmap_protect_mmu(pmap, sva, eva); 3231 else 3232 pmap_protect_noctx(pmap, sva, eva); 3233 3234 if (old_ctx != INVALID_CONTEXT) { 3235 /* Restore previous context. */ 3236 set_context(old_ctx); 3237 } 3238 3239 out: 3240 splx(s); 3241 } 3242 3243 /* 3244 * Remove write permissions, all in one PMEG, 3245 * where that PMEG is currently in the MMU. 3246 * The current context is already correct. 3247 */ 3248 void 3249 pmap_protect_mmu(pmap_t pmap, vaddr_t sva, vaddr_t eva) 3250 { 3251 vaddr_t pgva; 3252 int pte; 3253 #if defined(HAVECACHE) 3254 int flush_by_page = 0; 3255 #endif 3256 #if defined(HAVECACHE) || defined(DIAGNOSTIC) 3257 vaddr_t segva = sun_trunc_seg(sva); 3258 #endif 3259 3260 CHECK_SPL(); 3261 3262 #ifdef DIAGNOSTIC 3263 if ( 3264 #if IS_SUN3 3265 pmap != kernel_pmap && 3266 #endif 3267 pmap->pm_ctxnum != get_context()) { 3268 panic("pmap_protect_mmu: wrong context"); 3269 } 3270 3271 int sme = get_segmap(segva); 3272 /* Make sure it is valid and known. */ 3273 if (sme == SEGINV) 3274 panic("pmap_protect_mmu: SEGINV"); 3275 if (pmap->pm_segmap && (pmap->pm_segmap[VA_SEGNUM(segva)] != sme)) 3276 panic("pmap_protect_mmu: incorrect sme, va=0x%lx", segva); 3277 3278 /* have pmeg, will travel */ 3279 pmeg_t pmegp = pmeg_p(sme); 3280 /* Make sure we own the pmeg, right va, etc. */ 3281 if ((pmegp->pmeg_va != segva) || 3282 (pmegp->pmeg_owner != pmap) || 3283 (pmegp->pmeg_version != pmap->pm_version)) 3284 { 3285 panic("pmap_protect_mmu: bad pmeg=%p", pmegp); 3286 } 3287 if (pmegp->pmeg_vpages < 0) 3288 panic("pmap_protect_mmu: npages corrupted"); 3289 if (pmegp->pmeg_vpages == 0) 3290 panic("pmap_protect_mmu: no valid pages?"); 3291 #endif /* DIAGNOSTIC */ 3292 3293 #ifdef HAVECACHE 3294 if (cache_size) { 3295 /* 3296 * If the range to be removed is larger than the cache, 3297 * it will be cheaper to flush this segment entirely. 3298 */ 3299 if (cache_size < (eva - sva)) { 3300 /* cheaper to flush whole segment */ 3301 cache_flush_segment(segva); 3302 } else { 3303 flush_by_page = 1; 3304 } 3305 } 3306 #endif 3307 3308 /* Remove write permission in the given range. */ 3309 for (pgva = sva; pgva < eva; pgva += PAGE_SIZE) { 3310 pte = get_pte(pgva); 3311 if (pte & PG_VALID) { 3312 #ifdef HAVECACHE 3313 if (flush_by_page) { 3314 cache_flush_page(pgva); 3315 /* Get fresh mod/ref bits from write-back. */ 3316 pte = get_pte(pgva); 3317 } 3318 #endif 3319 if (IS_MAIN_MEM(pte)) { 3320 save_modref_bits(pte); 3321 } 3322 pte &= ~(PG_WRITE | PG_MODREF); 3323 set_pte(pgva, pte); 3324 } 3325 } 3326 } 3327 3328 /* 3329 * Remove write permissions, all in one PMEG, 3330 * where it is not currently in any context. 3331 */ 3332 void 3333 pmap_protect_noctx(pmap_t pmap, vaddr_t sva, vaddr_t eva) 3334 { 3335 int old_ctx, pte, sme, segnum; 3336 vaddr_t pgva, segva; 3337 3338 #ifdef DIAGNOSTIC 3339 /* Kernel always in a context. */ 3340 if (pmap == kernel_pmap) 3341 panic("pmap_protect_noctx: kernel_pmap"); 3342 if (pmap->pm_segmap == NULL) 3343 panic("pmap_protect_noctx: null segmap"); 3344 #endif 3345 3346 segva = sun_trunc_seg(sva); 3347 segnum = VA_SEGNUM(segva); 3348 sme = pmap->pm_segmap[segnum]; 3349 if (sme == SEGINV) 3350 return; 3351 3352 /* 3353 * Borrow the EMPTY_CONTEXT so we can access the PMEG 3354 * at its normal virtual address. 3355 * 3356 * (On Sun-2, we have to use the temporary segment.) 3357 */ 3358 old_ctx = get_context(); 3359 #if IS_SUN2 3360 set_context(KERNEL_CONTEXT); 3361 set_segmap(temp_seg_va, sme); 3362 #ifdef DIAGNOSTIC 3363 if (temp_seg_inuse) 3364 panic("pmap_protect_noctx: temp_seg_inuse"); 3365 temp_seg_inuse++; 3366 #endif 3367 sva += (temp_seg_va - segva); 3368 eva += (temp_seg_va - segva); 3369 #else /* IS_SUN3 */ 3370 set_context(EMPTY_CONTEXT); 3371 set_segmap(segva, sme); 3372 #endif /* IS_SUN2 */ 3373 3374 /* Remove write permission in the given range. */ 3375 for (pgva = sva; pgva < eva; pgva += PAGE_SIZE) { 3376 pte = get_pte(pgva); 3377 if (pte & PG_VALID) { 3378 /* No cache flush needed. */ 3379 if (IS_MAIN_MEM(pte)) { 3380 save_modref_bits(pte); 3381 } 3382 pte &= ~(PG_WRITE | PG_MODREF); 3383 set_pte(pgva, pte); 3384 } 3385 } 3386 3387 /* 3388 * Make the EMPTY_CONTEXT really empty again, and 3389 * restore the previous context. 3390 * 3391 * (On Sun-2, release the temporary segment.) 3392 */ 3393 #if IS_SUN2 3394 set_segmap(temp_seg_va, SEGINV); 3395 #ifdef DIAGNOSTIC 3396 temp_seg_inuse--; 3397 #endif 3398 #else /* IS_SUN3 */ 3399 set_segmap(segva, SEGINV); 3400 #endif /* IS_SUN2 */ 3401 set_context(old_ctx); 3402 } 3403 3404 3405 /* 3406 * Remove the given range of addresses from the specified map. 3407 * 3408 * It is assumed that the start and end are properly 3409 * rounded to the page size. 3410 */ 3411 void 3412 pmap_remove(pmap_t pmap, vaddr_t sva, vaddr_t eva) 3413 { 3414 vaddr_t va, neva; 3415 int segnum; 3416 3417 #ifdef PMAP_DEBUG 3418 if ((pmap_debug & PMD_REMOVE) || 3419 ((sva <= pmap_db_watchva && eva > pmap_db_watchva))) 3420 printf("pmap_remove(%p, 0x%lx, 0x%lx)\n", pmap, sva, eva); 3421 #endif 3422 3423 3424 KASSERT((pmap == kernel_pmap) ? 3425 sva >= virtual_avail && eva < DVMA_MAP_END : 3426 eva <= VM_MAXUSER_ADDRESS); 3427 va = sva; 3428 segnum = VA_SEGNUM(va); 3429 while (va < eva) { 3430 neva = sun_trunc_seg(va) + NBSG; 3431 if (neva > eva) 3432 neva = eva; 3433 if (pmap->pm_segmap[segnum] != SEGINV) 3434 pmap_remove1(pmap, va, neva); 3435 va = neva; 3436 segnum++; 3437 } 3438 } 3439 3440 /* 3441 * Remove user mappings, all within one segment 3442 */ 3443 void 3444 pmap_remove1(pmap_t pmap, vaddr_t sva, vaddr_t eva) 3445 { 3446 int old_ctx, s, sme; 3447 bool in_ctx; 3448 3449 s = splvm(); 3450 3451 #ifdef DIAGNOSTIC 3452 if (sun_trunc_seg(sva) != sun_trunc_seg(eva-1)) 3453 panic("pmap_remove1: bad range!"); 3454 #endif 3455 3456 if (pmap == kernel_pmap) { 3457 kernel_context_enter(); 3458 sme = get_segmap(sva); 3459 if (sme != SEGINV) 3460 pmap_remove_mmu(pmap, sva, eva); 3461 kernel_context_exit(); 3462 goto out; 3463 } 3464 /* It is a user pmap. */ 3465 3466 /* There is a PMEG, but maybe not active. */ 3467 old_ctx = INVALID_CONTEXT; 3468 in_ctx = false; 3469 if (has_context(pmap)) { 3470 /* Temporary context change. */ 3471 old_ctx = get_context(); 3472 set_context(pmap->pm_ctxnum); 3473 sme = get_segmap(sva); 3474 if (sme != SEGINV) 3475 in_ctx = true; 3476 } 3477 3478 if (in_ctx == true) 3479 pmap_remove_mmu(pmap, sva, eva); 3480 else 3481 pmap_remove_noctx(pmap, sva, eva); 3482 3483 if (old_ctx != INVALID_CONTEXT) { 3484 /* Restore previous context. */ 3485 set_context(old_ctx); 3486 } 3487 3488 out: 3489 splx(s); 3490 } 3491 3492 /* 3493 * Remove some mappings, all in one PMEG, 3494 * where that PMEG is currently in the MMU. 3495 * The current context is already correct. 3496 * If no PTEs remain valid in the PMEG, free it. 3497 */ 3498 void 3499 pmap_remove_mmu(pmap_t pmap, vaddr_t sva, vaddr_t eva) 3500 { 3501 pmeg_t pmegp; 3502 vaddr_t pgva, segva; 3503 int pte, sme; 3504 #ifdef HAVECACHE 3505 int flush_by_page = 0; 3506 #endif 3507 3508 CHECK_SPL(); 3509 3510 #ifdef DIAGNOSTIC 3511 if ( 3512 #if IS_SUN3 3513 pmap != kernel_pmap && 3514 #endif 3515 pmap->pm_ctxnum != get_context()) { 3516 panic("pmap_remove_mmu: wrong context"); 3517 } 3518 #endif 3519 3520 segva = sun_trunc_seg(sva); 3521 sme = get_segmap(segva); 3522 3523 #ifdef DIAGNOSTIC 3524 /* Make sure it is valid and known. */ 3525 if (sme == SEGINV) 3526 panic("pmap_remove_mmu: SEGINV"); 3527 if (pmap->pm_segmap && (pmap->pm_segmap[VA_SEGNUM(segva)] != sme)) 3528 panic("pmap_remove_mmu: incorrect sme, va=0x%lx", segva); 3529 #endif 3530 3531 pmegp = pmeg_p(sme); 3532 /* have pmeg, will travel */ 3533 3534 #ifdef DIAGNOSTIC 3535 /* Make sure we own the pmeg, right va, etc. */ 3536 if ((pmegp->pmeg_va != segva) || 3537 (pmegp->pmeg_owner != pmap) || 3538 (pmegp->pmeg_version != pmap->pm_version)) 3539 { 3540 panic("pmap_remove_mmu: bad pmeg=%p", pmegp); 3541 } 3542 if (pmegp->pmeg_vpages < 0) 3543 panic("pmap_remove_mmu: npages corrupted"); 3544 if (pmegp->pmeg_vpages == 0) 3545 panic("pmap_remove_mmu: no valid pages?"); 3546 #endif 3547 3548 #ifdef HAVECACHE 3549 if (cache_size) { 3550 /* 3551 * If the range to be removed is larger than the cache, 3552 * it will be cheaper to flush this segment entirely. 3553 */ 3554 if (cache_size < (eva - sva)) { 3555 /* cheaper to flush whole segment */ 3556 cache_flush_segment(segva); 3557 } else { 3558 flush_by_page = 1; 3559 } 3560 } 3561 #endif 3562 3563 /* Invalidate the PTEs in the given range. */ 3564 for (pgva = sva; pgva < eva; pgva += PAGE_SIZE) { 3565 pte = get_pte(pgva); 3566 if (pte & PG_VALID) { 3567 #ifdef HAVECACHE 3568 if (flush_by_page) { 3569 cache_flush_page(pgva); 3570 /* Get fresh mod/ref bits from write-back. */ 3571 pte = get_pte(pgva); 3572 } 3573 #endif 3574 if (IS_MAIN_MEM(pte)) { 3575 save_modref_bits(pte); 3576 pv_unlink(pmap, pte, pgva); 3577 } 3578 #ifdef PMAP_DEBUG 3579 if ((pmap_debug & PMD_SETPTE) || 3580 (pgva == pmap_db_watchva)) { 3581 printf("pmap: set_pte pmap=%p va=0x%lx" 3582 " old=0x%x new=0x%x (rrmmu)\n", 3583 pmap, pgva, pte, PG_INVAL); 3584 } 3585 #endif 3586 set_pte(pgva, PG_INVAL); 3587 KASSERT(pmegp->pmeg_vpages > 0); 3588 pmegp->pmeg_vpages--; 3589 } 3590 } 3591 3592 KASSERT(pmegp->pmeg_vpages >= 0); 3593 if (pmegp->pmeg_vpages == 0) { 3594 /* We are done with this pmeg. */ 3595 #ifdef PMAP_DEBUG 3596 if (is_pmeg_wired(pmegp)) { 3597 if (pmap_debug & PMD_WIRING) { 3598 db_printf("pmap: removing wired pmeg: %p\n", 3599 pmegp); 3600 Debugger(); 3601 } 3602 } 3603 3604 if (pmap_debug & PMD_SEGMAP) { 3605 printf("pmap: set_segmap ctx=%d v=0x%lx old=0x%x " 3606 "new=ff (rm)\n", 3607 pmap->pm_ctxnum, segva, pmegp->pmeg_index); 3608 } 3609 pmeg_verify_empty(segva); 3610 #endif /* PMAP_DEBUG */ 3611 3612 /* Remove it from the MMU. */ 3613 if (kernel_pmap == pmap) { 3614 /* Did cache flush above. */ 3615 set_kernel_segmap(segva, SEGINV); 3616 } else { 3617 /* Did cache flush above. */ 3618 set_segmap(segva, SEGINV); 3619 } 3620 pmap->pm_segmap[VA_SEGNUM(segva)] = SEGINV; 3621 /* Now, put it on the free list. */ 3622 pmeg_free(pmegp); 3623 } 3624 } 3625 3626 /* 3627 * Remove some mappings, all in one PMEG, 3628 * where it is not currently in any context. 3629 */ 3630 void 3631 pmap_remove_noctx(pmap_t pmap, vaddr_t sva, vaddr_t eva) 3632 { 3633 pmeg_t pmegp; 3634 int old_ctx, pte, sme, segnum; 3635 vaddr_t pgva, segva; 3636 3637 CHECK_SPL(); 3638 3639 #ifdef DIAGNOSTIC 3640 /* Kernel always in a context. */ 3641 if (pmap == kernel_pmap) 3642 panic("pmap_remove_noctx: kernel_pmap"); 3643 if (pmap->pm_segmap == NULL) 3644 panic("pmap_remove_noctx: null segmap"); 3645 #endif 3646 3647 segva = sun_trunc_seg(sva); 3648 segnum = VA_SEGNUM(segva); 3649 sme = pmap->pm_segmap[segnum]; 3650 if (sme == SEGINV) 3651 return; 3652 pmegp = pmeg_p(sme); 3653 3654 /* 3655 * Borrow the EMPTY_CONTEXT so we can access the PMEG 3656 * at its normal virtual address. 3657 * 3658 * (On Sun-2, use the temporary segment.) 3659 */ 3660 old_ctx = get_context(); 3661 #if IS_SUN2 3662 set_context(KERNEL_CONTEXT); 3663 #ifdef DIAGNOSTIC 3664 if (temp_seg_inuse) 3665 panic("pmap_remove_noctx: temp_seg_inuse"); 3666 temp_seg_inuse++; 3667 #endif 3668 set_segmap(temp_seg_va, sme); 3669 sva += (temp_seg_va - segva); 3670 eva += (temp_seg_va - segva); 3671 #else /* IS_SUN3 */ 3672 set_context(EMPTY_CONTEXT); 3673 set_segmap(segva, sme); 3674 #endif /* IS_SUN2 */ 3675 3676 /* Invalidate the PTEs in the given range. */ 3677 for (pgva = sva; pgva < eva; pgva += PAGE_SIZE) { 3678 pte = get_pte(pgva); 3679 if (pte & PG_VALID) { 3680 /* No cache flush needed. */ 3681 if (IS_MAIN_MEM(pte)) { 3682 save_modref_bits(pte); 3683 pv_unlink(pmap, pte, 3684 #if IS_SUN2 3685 pgva - (temp_seg_va - segva) 3686 #else 3687 pgva 3688 #endif 3689 ); 3690 } 3691 #ifdef PMAP_DEBUG 3692 if ((pmap_debug & PMD_SETPTE) || 3693 (pgva == pmap_db_watchva)) { 3694 printf("pmap: set_pte pmap=%p va=0x%lx" 3695 " old=0x%x new=0x%x (rrncx)\n", 3696 pmap, pgva, pte, PG_INVAL); 3697 } 3698 #endif 3699 set_pte(pgva, PG_INVAL); 3700 KASSERT(pmegp->pmeg_vpages > 0); 3701 pmegp->pmeg_vpages--; 3702 } 3703 } 3704 3705 /* 3706 * Make the EMPTY_CONTEXT really empty again, and 3707 * restore the previous context. 3708 * 3709 * (On Sun-2, release the temporary segment.) 3710 */ 3711 #if IS_SUN2 3712 set_segmap(temp_seg_va, SEGINV); 3713 #ifdef DIAGNOSTIC 3714 temp_seg_inuse--; 3715 #endif 3716 #else /* IS_SUN3 */ 3717 set_segmap(segva, SEGINV); 3718 #endif /* IS_SUN2 */ 3719 set_context(old_ctx); 3720 3721 KASSERT(pmegp->pmeg_vpages >= 0); 3722 if (pmegp->pmeg_vpages == 0) { 3723 /* We are done with this pmeg. */ 3724 if (is_pmeg_wired(pmegp)) { 3725 #ifdef PMAP_DEBUG 3726 if (pmap_debug & PMD_WIRING) { 3727 db_printf("pmap: removing wired pmeg: %p\n", 3728 pmegp); 3729 Debugger(); 3730 } 3731 #endif /* PMAP_DEBUG */ 3732 } 3733 3734 pmap->pm_segmap[segnum] = SEGINV; 3735 pmeg_free(pmegp); 3736 } 3737 } 3738 3739 3740 /* 3741 * Count resident pages in this pmap. 3742 * See: kern_sysctl.c:pmap_resident_count 3743 */ 3744 segsz_t 3745 pmap_resident_pages(pmap_t pmap) 3746 { 3747 int i, sme, pages; 3748 pmeg_t pmeg; 3749 3750 if (pmap->pm_segmap == 0) 3751 return (0); 3752 3753 pages = 0; 3754 for (i = 0; i < NUSEG; i++) { 3755 sme = pmap->pm_segmap[i]; 3756 if (sme != SEGINV) { 3757 pmeg = pmeg_p(sme); 3758 pages += pmeg->pmeg_vpages; 3759 } 3760 } 3761 return (pages); 3762 } 3763 3764 /* 3765 * Count wired pages in this pmap. 3766 * See vm_mmap.c:pmap_wired_count 3767 */ 3768 segsz_t 3769 pmap_wired_pages(pmap_t pmap) 3770 { 3771 int i, mask, sme, pages; 3772 pmeg_t pmeg; 3773 3774 if (pmap->pm_segmap == 0) 3775 return (0); 3776 3777 pages = 0; 3778 for (i = 0; i < NUSEG; i++) { 3779 sme = pmap->pm_segmap[i]; 3780 if (sme != SEGINV) { 3781 pmeg = pmeg_p(sme); 3782 mask = 0x8000; 3783 do { 3784 if (pmeg->pmeg_wired & mask) 3785 pages++; 3786 mask = (mask >> 1); 3787 } while (mask); 3788 } 3789 } 3790 return (pages); 3791 } 3792 3793 3794 /* 3795 * pmap_copy_page copies the specified (machine independent) 3796 * page by mapping the page into virtual memory and using 3797 * bcopy to copy the page, one machine dependent page at a 3798 * time. 3799 */ 3800 void 3801 pmap_copy_page(paddr_t src, paddr_t dst) 3802 { 3803 int pte; 3804 int s; 3805 3806 s = splvm(); 3807 3808 #ifdef PMAP_DEBUG 3809 if (pmap_debug & PMD_COW) 3810 printf("pmap_copy_page: 0x%lx -> 0x%lx\n", src, dst); 3811 #endif 3812 3813 #ifdef DIAGNOSTIC 3814 if (tmp_vpages_inuse) 3815 panic("pmap_copy_page: vpages inuse"); 3816 tmp_vpages_inuse++; 3817 #endif 3818 3819 kernel_context_enter(); 3820 3821 /* PG_PERM is short for (PG_VALID|PG_WRITE|PG_SYSTEM|PG_NC) */ 3822 /* All mappings to vmp_vpages are non-cached, so no flush. */ 3823 pte = PG_PERM | PA_PGNUM(src); 3824 set_pte(tmp_vpages[0], pte); 3825 pte = PG_PERM | PA_PGNUM(dst); 3826 set_pte(tmp_vpages[1], pte); 3827 copypage((char *) tmp_vpages[0], (char *) tmp_vpages[1]); 3828 set_pte(tmp_vpages[0], PG_INVAL); 3829 set_pte(tmp_vpages[1], PG_INVAL); 3830 3831 kernel_context_exit(); 3832 3833 #ifdef DIAGNOSTIC 3834 tmp_vpages_inuse--; 3835 #endif 3836 3837 splx(s); 3838 } 3839 3840 /* 3841 * pmap_zero_page zeros the specified (machine independent) 3842 * page by mapping the page into virtual memory and using 3843 * bzero to clear its contents, one machine dependent page 3844 * at a time. 3845 */ 3846 void 3847 pmap_zero_page(paddr_t pa) 3848 { 3849 int pte; 3850 int s; 3851 3852 s = splvm(); 3853 3854 #ifdef PMAP_DEBUG 3855 if (pmap_debug & PMD_COW) 3856 printf("pmap_zero_page: 0x%lx\n", pa); 3857 #endif 3858 3859 #ifdef DIAGNOSTIC 3860 if (tmp_vpages_inuse) 3861 panic("pmap_zero_page: vpages inuse"); 3862 tmp_vpages_inuse++; 3863 #endif 3864 3865 kernel_context_enter(); 3866 3867 /* PG_PERM is short for (PG_VALID|PG_WRITE|PG_SYSTEM|PG_NC) */ 3868 /* All mappings to vmp_vpages are non-cached, so no flush. */ 3869 pte = PG_PERM | PA_PGNUM(pa); 3870 set_pte(tmp_vpages[0], pte); 3871 zeropage((char *) tmp_vpages[0]); 3872 set_pte(tmp_vpages[0], PG_INVAL); 3873 3874 kernel_context_exit(); 3875 3876 #ifdef DIAGNOSTIC 3877 tmp_vpages_inuse--; 3878 #endif 3879 3880 splx(s); 3881 } 3882 3883 /* 3884 * Find first virtual address >= *va that is 3885 * least likely to cause cache aliases. 3886 * (This will just seg-align mappings.) 3887 */ 3888 void 3889 pmap_prefer(vaddr_t fo, vaddr_t *va, int td) 3890 { 3891 long d; 3892 3893 d = fo - *va; 3894 d &= SEGOFSET; 3895 if (d == 0) { 3896 return; 3897 } 3898 if (td) { 3899 *va -= SEGOFSET + 1; 3900 } 3901 *va += d; 3902 } 3903 3904 /* 3905 * Fill in the sun-specific part of the kernel core header 3906 * for dumpsys(). (See machdep.c for the rest.) 3907 */ 3908 void 3909 pmap_kcore_hdr( 3910 #if IS_SUN2 3911 struct sun2_kcore_hdr *sh 3912 #else 3913 struct sun3_kcore_hdr *sh 3914 #endif 3915 ) 3916 { 3917 vaddr_t va; 3918 u_char *cp, *ep; 3919 3920 sh->segshift = SEGSHIFT; 3921 sh->pg_frame = PG_FRAME; 3922 sh->pg_valid = PG_VALID; 3923 3924 kernel_context_enter(); 3925 3926 /* Copy the kernel segmap (256 bytes). */ 3927 #if IS_SUN2 3928 va = KERNBASE; 3929 #else 3930 va = KERNBASE3; 3931 #endif 3932 cp = sh->ksegmap; 3933 ep = cp + sizeof(sh->ksegmap); 3934 do { 3935 *cp = get_segmap(va); 3936 va += NBSG; 3937 cp++; 3938 } while (cp < ep); 3939 3940 kernel_context_exit(); 3941 } 3942 3943 /* 3944 * Copy the pagemap RAM into the passed buffer (one page) 3945 * starting at OFF in the pagemap RAM. 3946 */ 3947 void 3948 pmap_get_pagemap(int *pt, int off) 3949 { 3950 vaddr_t va, va_end; 3951 int sme, sme_end; /* SegMap Entry numbers */ 3952 3953 #if IS_SUN2 3954 sme = (off / (NPAGSEG * sizeof(*pt))); /* PMEG to start on */ 3955 sme_end = 3956 sme + (PAGE_SIZE / (NPAGSEG * sizeof(*pt)));/* where to stop */ 3957 #else 3958 sme = (off >> 6); /* PMEG to start on */ 3959 sme_end = sme + 128; /* where to stop */ 3960 #endif /* IS_SUN2 */ 3961 va_end = temp_seg_va + NBSG; 3962 3963 kernel_context_enter(); 3964 do { 3965 set_segmap(temp_seg_va, sme); 3966 va = temp_seg_va; 3967 do { 3968 *pt++ = get_pte(va); 3969 va += PAGE_SIZE; 3970 } while (va < va_end); 3971 sme++; 3972 } while (sme < sme_end); 3973 set_segmap(temp_seg_va, SEGINV); 3974 kernel_context_exit(); 3975 } 3976 3977 3978 /* 3979 * Helper functions for changing unloaded PMEGs 3980 */ 3981 3982 #ifdef DIAGNOSTIC 3983 static int temp_seg_inuse; 3984 #endif 3985 3986 static int 3987 get_pte_pmeg(int pmeg_num, int page_num) 3988 { 3989 vaddr_t va; 3990 int pte; 3991 3992 CHECK_SPL(); 3993 #ifdef DIAGNOSTIC 3994 if (temp_seg_inuse) 3995 panic("get_pte_pmeg: temp_seg_inuse"); 3996 temp_seg_inuse++; 3997 #endif 3998 3999 kernel_context_enter(); 4000 4001 va = temp_seg_va; 4002 set_segmap(temp_seg_va, pmeg_num); 4003 va += PAGE_SIZE*page_num; 4004 pte = get_pte(va); 4005 set_segmap(temp_seg_va, SEGINV); 4006 4007 kernel_context_exit(); 4008 4009 #ifdef DIAGNOSTIC 4010 temp_seg_inuse--; 4011 #endif 4012 return pte; 4013 } 4014 4015 static void 4016 set_pte_pmeg(int pmeg_num, int page_num, int pte) 4017 { 4018 vaddr_t va; 4019 4020 CHECK_SPL(); 4021 #ifdef DIAGNOSTIC 4022 if (temp_seg_inuse) 4023 panic("set_pte_pmeg: temp_seg_inuse"); 4024 temp_seg_inuse++; 4025 #endif 4026 4027 kernel_context_enter(); 4028 4029 /* We never access data in temp_seg_va so no need to flush. */ 4030 va = temp_seg_va; 4031 set_segmap(temp_seg_va, pmeg_num); 4032 va += PAGE_SIZE*page_num; 4033 set_pte(va, pte); 4034 set_segmap(temp_seg_va, SEGINV); 4035 4036 kernel_context_exit(); 4037 4038 #ifdef DIAGNOSTIC 4039 temp_seg_inuse--; 4040 #endif 4041 } 4042 4043 /* 4044 * Routine: pmap_procwr 4045 * 4046 * Function: 4047 * Synchronize caches corresponding to [addr, addr+len) in p. 4048 */ 4049 void 4050 pmap_procwr(struct proc *p, vaddr_t va, size_t len) 4051 { 4052 #if IS_SUN3 4053 (void)cachectl1(0x80000004, va, len, p); 4054 #endif 4055 } 4056 4057 #if defined(DDB) || defined(KGDB) 4058 /* 4059 * Routine: pmap_db_write_text_enter 4060 * 4061 * Function: 4062 * Temporarily map a page of kernel text read-write for the 4063 * kernel debugger. 4064 */ 4065 bool 4066 pmap_db_write_text_enter(vaddr_t pgva, struct pmap_db_write_text_context *ctx) 4067 { 4068 int oldpte, tmppte; 4069 4070 #ifdef HAVECACHE 4071 if (cache_size) { 4072 cache_flush_page(pgva); 4073 } 4074 #endif 4075 4076 kernel_context_enter(); 4077 4078 oldpte = get_pte(pgva); 4079 if ((oldpte & PG_VALID) == 0) { 4080 return false; 4081 } 4082 4083 /* Make the pte writable and non-cached. */ 4084 tmppte = oldpte; 4085 tmppte |= (PG_WRITE | PG_NC); 4086 set_pte(pgva, tmppte); 4087 4088 kernel_context_exit(); 4089 4090 ctx->pgva = pgva; 4091 ctx->opte = oldpte; 4092 4093 return true; 4094 } 4095 4096 /* 4097 * Routine: pmap_db_write_text_exit 4098 * 4099 * Function: 4100 * Undo the effects of pmap_db_write_text_enter(). 4101 */ 4102 void 4103 pmap_db_write_text_exit(struct pmap_db_write_text_context *ctx) 4104 { 4105 kernel_context_enter(); 4106 set_pte(ctx->pgva, ctx->opte); 4107 kernel_context_exit(); 4108 } 4109 #endif /* DDB || KGDB */ 4110 4111 #ifdef PMAP_DEBUG 4112 /* Things to call from the debugger. */ 4113 4114 void 4115 pmap_print(pmap_t pmap) 4116 { 4117 db_printf(" pm_ctxnum=%d\n", pmap->pm_ctxnum); 4118 db_printf(" pm_version=0x%x\n", pmap->pm_version); 4119 db_printf(" pm_segmap=%p\n", pmap->pm_segmap); 4120 } 4121 4122 void 4123 pmeg_print(pmeg_t pmegp) 4124 { 4125 db_printf("link_next=%p link_prev=%p\n", 4126 TAILQ_NEXT(pmegp, pmeg_link), 4127 TAILQ_PREV(pmegp, pmeg_tailq, pmeg_link)); 4128 db_printf("index=0x%x owner=%p own_vers=0x%x\n", 4129 pmegp->pmeg_index, pmegp->pmeg_owner, pmegp->pmeg_version); 4130 db_printf("va=0x%lx wired=0x%x reserved=0x%x vpgs=0x%x qstate=0x%x\n", 4131 pmegp->pmeg_va, pmegp->pmeg_wired, 4132 pmegp->pmeg_reserved, pmegp->pmeg_vpages, 4133 pmegp->pmeg_qstate); 4134 } 4135 4136 void 4137 pv_print(paddr_t pa) 4138 { 4139 pv_entry_t pv; 4140 int idx; 4141 4142 idx = PA_PGNUM(pa); 4143 if (idx >= physmem) { 4144 db_printf("bad address\n"); 4145 return; 4146 } 4147 db_printf("pa=0x%lx, flags=0x%x\n", 4148 pa, pv_flags_tbl[idx]); 4149 4150 pv = pv_head_tbl[idx]; 4151 while (pv) { 4152 db_printf(" pv_entry %p pmap %p va 0x%lx next %p\n", 4153 pv, pv->pv_pmap, pv->pv_va, pv->pv_next); 4154 pv = pv->pv_next; 4155 } 4156 } 4157 #endif /* PMAP_DEBUG */ 4158