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