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