pmap.c revision 1.126
1/* $OpenBSD: pmap.c,v 1.126 2014/03/31 18:58:41 mpi Exp $ */ 2 3/* 4 * Copyright (c) 2001, 2002, 2007 Dale Rahn. 5 * All rights reserved. 6 * 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Effort sponsored in part by the Defense Advanced Research Projects 29 * Agency (DARPA) and Air Force Research Laboratory, Air Force 30 * Materiel Command, USAF, under agreement number F30602-01-2-0537. 31 */ 32 33/* 34 * powerpc lazy icache managment. 35 * The icache does not snoop dcache accesses. The icache also will not load 36 * modified data from the dcache, but the unmodified data in ram. 37 * Before the icache is loaded, the dcache must be synced to ram to prevent 38 * the icache from loading stale data. 39 * pg->pg_flags PG_PMAP_EXE bit is used to track if the dcache is clean 40 * and the icache may have valid data in it. 41 * if the PG_PMAP_EXE bit is set (and the page is not currently RWX) 42 * the icache will only have valid code in it. If the bit is clear 43 * memory may not match the dcache contents or the icache may contain 44 * data from a previous page. 45 * 46 * pmap enter 47 * !E NONE -> R no action 48 * !E NONE|R -> RW no action 49 * !E NONE|R -> RX flush dcache, inval icache (that page only), set E 50 * !E NONE|R -> RWX flush dcache, inval icache (that page only), set E 51 * !E NONE|RW -> RWX flush dcache, inval icache (that page only), set E 52 * E NONE -> R no action 53 * E NONE|R -> RW clear PG_PMAP_EXE bit 54 * E NONE|R -> RX no action 55 * E NONE|R -> RWX no action 56 * E NONE|RW -> RWX -invalid source state 57 * 58 * pamp_protect 59 * E RW -> R - invalid source state 60 * !E RW -> R - no action 61 * * RX -> R - no action 62 * * RWX -> R - sync dcache, inval icache 63 * * RWX -> RW - clear PG_PMAP_EXE 64 * * RWX -> RX - sync dcache, inval icache 65 * * * -> NONE - no action 66 * 67 * pmap_page_protect (called with arg PROT_NONE if page is to be reused) 68 * * RW -> R - as pmap_protect 69 * * RX -> R - as pmap_protect 70 * * RWX -> R - as pmap_protect 71 * * RWX -> RW - as pmap_protect 72 * * RWX -> RX - as pmap_protect 73 * * * -> NONE - clear PG_PMAP_EXE 74 * 75 */ 76 77#include <sys/param.h> 78#include <sys/malloc.h> 79#include <sys/proc.h> 80#include <sys/queue.h> 81#include <sys/systm.h> 82#include <sys/pool.h> 83 84#include <uvm/uvm_extern.h> 85 86#include <machine/pcb.h> 87#include <machine/powerpc.h> 88#include <machine/pmap.h> 89 90#include <machine/db_machdep.h> 91#include <ddb/db_extern.h> 92#include <ddb/db_output.h> 93 94#include <powerpc/lock.h> 95 96struct pmap kernel_pmap_; 97static struct mem_region *pmap_mem, *pmap_avail; 98struct mem_region pmap_allocated[10]; 99int pmap_cnt_avail; 100int pmap_cnt_allocated; 101 102struct pte_64 *pmap_ptable64; 103struct pte_32 *pmap_ptable32; 104int pmap_ptab_cnt; 105u_int pmap_ptab_mask; 106 107#define HTABSIZE_32 (pmap_ptab_cnt * 64) 108#define HTABMEMSZ_64 (pmap_ptab_cnt * 8 * sizeof(struct pte_64)) 109#define HTABSIZE_64 (ffs(pmap_ptab_cnt) - 12) 110 111static u_int usedsr[NPMAPS / sizeof(u_int) / 8]; 112paddr_t zero_page; 113paddr_t copy_src_page; 114paddr_t copy_dst_page; 115 116struct pte_desc { 117 /* Linked list of phys -> virt entries */ 118 LIST_ENTRY(pte_desc) pted_pv_list; 119 union { 120 struct pte_32 pted_pte32; 121 struct pte_64 pted_pte64; 122 } p; 123 pmap_t pted_pmap; 124 vaddr_t pted_va; 125}; 126 127void print_pteg(pmap_t pm, vaddr_t va); 128 129static inline void tlbsync(void); 130static inline void tlbie(vaddr_t ea); 131void tlbia(void); 132 133void pmap_attr_save(paddr_t pa, u_int32_t bits); 134void pmap_page_ro64(pmap_t pm, vaddr_t va, vm_prot_t prot); 135void pmap_page_ro32(pmap_t pm, vaddr_t va, vm_prot_t prot); 136 137/* 138 * LOCKING structures. 139 * This may not be correct, and doesn't do anything yet. 140 */ 141#define pmap_simplelock_pm(pm) 142#define pmap_simpleunlock_pm(pm) 143#define pmap_simplelock_pv(pm) 144#define pmap_simpleunlock_pv(pm) 145 146/* 147 * Some functions are called in real mode and cannot be profiled. 148 */ 149#define __noprof __attribute__((__no_instrument_function__)) 150 151/* VP routines */ 152int pmap_vp_enter(pmap_t pm, vaddr_t va, struct pte_desc *pted, int flags); 153struct pte_desc *pmap_vp_remove(pmap_t pm, vaddr_t va); 154void pmap_vp_destroy(pmap_t pm); 155struct pte_desc *pmap_vp_lookup(pmap_t pm, vaddr_t va) __noprof; 156 157/* PV routines */ 158void pmap_enter_pv(struct pte_desc *pted, struct vm_page *); 159void pmap_remove_pv(struct pte_desc *pted); 160 161 162/* pte hash table routines */ 163void pmap_hash_remove(struct pte_desc *); 164void pte_insert32(struct pte_desc *) __noprof; 165void pte_insert64(struct pte_desc *) __noprof; 166void pmap_fill_pte64(pmap_t, vaddr_t, paddr_t, struct pte_desc *, vm_prot_t, 167 int, int) __noprof; 168void pmap_fill_pte32(pmap_t, vaddr_t, paddr_t, struct pte_desc *, vm_prot_t, 169 int, int) __noprof; 170 171void pmap_syncicache_user_virt(pmap_t pm, vaddr_t va); 172 173void _pmap_kenter_pa(vaddr_t va, paddr_t pa, vm_prot_t prot, int flags, 174 int cache); 175void pmap_remove_pg(pmap_t pm, vaddr_t va); 176void pmap_kremove_pg(vaddr_t va); 177 178/* setup/initialization functions */ 179void pmap_avail_setup(void); 180void pmap_avail_fixup(void); 181void pmap_remove_avail(paddr_t base, paddr_t end); 182void *pmap_steal_avail(size_t size, int align); 183 184/* asm interface */ 185int pte_spill_r(u_int32_t, u_int32_t, u_int32_t, int) __noprof; 186 187u_int32_t pmap_setusr(pmap_t pm, vaddr_t va); 188void pmap_popusr(u_int32_t oldsr); 189 190/* pte invalidation */ 191void pte_zap(void *ptp, struct pte_desc *pted); 192 193/* debugging */ 194void pmap_print_pted(struct pte_desc *pted, int(*print)(const char *, ...)); 195 196/* XXX - panic on pool get failures? */ 197struct pool pmap_pmap_pool; 198struct pool pmap_vp_pool; 199struct pool pmap_pted_pool; 200 201int pmap_initialized = 0; 202int physmem; 203int physmaxaddr; 204 205void pmap_hash_lock_init(void); 206void pmap_hash_lock(int entry); 207void pmap_hash_unlock(int entry) __noprof; 208int pmap_hash_lock_try(int entry) __noprof; 209 210volatile unsigned int pmap_hash_lock_word = 0; 211 212void 213pmap_hash_lock_init() 214{ 215 pmap_hash_lock_word = 0; 216} 217 218int 219pmap_hash_lock_try(int entry) 220{ 221 int val = 1 << entry; 222 int success, tmp; 223 __asm volatile ( 224 "1: lwarx %0, 0, %3 \n" 225 " and. %1, %2, %0 \n" 226 " li %1, 0 \n" 227 " bne 2f \n" 228 " or %0, %2, %0 \n" 229 " stwcx. %0, 0, %3 \n" 230 " li %1, 1 \n" 231 " bne- 1b \n" 232 "2: \n" 233 : "=&r" (tmp), "=&r" (success) 234 : "r" (val), "r" (&pmap_hash_lock_word) 235 : "memory"); 236 return success; 237} 238 239 240void 241pmap_hash_lock(int entry) 242{ 243 int attempt = 0; 244 int locked = 0; 245 do { 246 if (pmap_hash_lock_word & (1 << entry)) { 247 attempt++; 248 if(attempt >0x20000000) 249 panic("unable to obtain lock on entry %d", 250 entry); 251 continue; 252 } 253 locked = pmap_hash_lock_try(entry); 254 } while (locked == 0); 255} 256 257void 258pmap_hash_unlock(int entry) 259{ 260 atomic_clearbits_int(&pmap_hash_lock_word, 1 << entry); 261} 262 263/* virtual to physical helpers */ 264static inline int 265VP_SR(vaddr_t va) 266{ 267 return (va >>VP_SR_POS) & VP_SR_MASK; 268} 269 270static inline int 271VP_IDX1(vaddr_t va) 272{ 273 return (va >> VP_IDX1_POS) & VP_IDX1_MASK; 274} 275 276static inline int 277VP_IDX2(vaddr_t va) 278{ 279 return (va >> VP_IDX2_POS) & VP_IDX2_MASK; 280} 281 282#if VP_IDX1_SIZE != VP_IDX2_SIZE 283#error pmap allocation code expects IDX1 and IDX2 size to be same 284#endif 285struct pmapvp { 286 void *vp[VP_IDX1_SIZE]; 287}; 288 289 290/* 291 * VP routines, virtual to physical translation information. 292 * These data structures are based off of the pmap, per process. 293 */ 294 295/* 296 * This is used for pmap_kernel() mappings, they are not to be removed 297 * from the vp table because they were statically initialized at the 298 * initial pmap initialization. This is so that memory allocation 299 * is not necessary in the pmap_kernel() mappings. 300 * Otherwise bad race conditions can appear. 301 */ 302struct pte_desc * 303pmap_vp_lookup(pmap_t pm, vaddr_t va) 304{ 305 struct pmapvp *vp1; 306 struct pmapvp *vp2; 307 struct pte_desc *pted; 308 309 vp1 = pm->pm_vp[VP_SR(va)]; 310 if (vp1 == NULL) { 311 return NULL; 312 } 313 314 vp2 = vp1->vp[VP_IDX1(va)]; 315 if (vp2 == NULL) { 316 return NULL; 317 } 318 319 pted = vp2->vp[VP_IDX2(va)]; 320 321 return pted; 322} 323 324/* 325 * Remove, and return, pted at specified address, NULL if not present 326 */ 327struct pte_desc * 328pmap_vp_remove(pmap_t pm, vaddr_t va) 329{ 330 struct pmapvp *vp1; 331 struct pmapvp *vp2; 332 struct pte_desc *pted; 333 334 vp1 = pm->pm_vp[VP_SR(va)]; 335 if (vp1 == NULL) { 336 return NULL; 337 } 338 339 vp2 = vp1->vp[VP_IDX1(va)]; 340 if (vp2 == NULL) { 341 return NULL; 342 } 343 344 pted = vp2->vp[VP_IDX2(va)]; 345 vp2->vp[VP_IDX2(va)] = NULL; 346 347 return pted; 348} 349 350/* 351 * Create a V -> P mapping for the given pmap and virtual address 352 * with reference to the pte descriptor that is used to map the page. 353 * This code should track allocations of vp table allocations 354 * so they can be freed efficiently. 355 * 356 * Should this be called under splvm? 357 */ 358int 359pmap_vp_enter(pmap_t pm, vaddr_t va, struct pte_desc *pted, int flags) 360{ 361 struct pmapvp *vp1; 362 struct pmapvp *vp2; 363 364 pmap_simplelock_pm(pm); 365 366 vp1 = pm->pm_vp[VP_SR(va)]; 367 if (vp1 == NULL) { 368 vp1 = pool_get(&pmap_vp_pool, PR_NOWAIT | PR_ZERO); 369 if (vp1 == NULL) { 370 if ((flags & PMAP_CANFAIL) == 0) 371 panic("pmap_vp_enter: failed to allocate vp1"); 372 return ENOMEM; 373 } 374 pm->pm_vp[VP_SR(va)] = vp1; 375 } 376 377 vp2 = vp1->vp[VP_IDX1(va)]; 378 if (vp2 == NULL) { 379 vp2 = pool_get(&pmap_vp_pool, PR_NOWAIT | PR_ZERO); 380 if (vp2 == NULL) { 381 if ((flags & PMAP_CANFAIL) == 0) 382 panic("pmap_vp_enter: failed to allocate vp2"); 383 return ENOMEM; 384 } 385 vp1->vp[VP_IDX1(va)] = vp2; 386 } 387 388 vp2->vp[VP_IDX2(va)] = pted; 389 390 pmap_simpleunlock_pm(pm); 391 392 return 0; 393} 394 395/* PTE manipulation/calculations */ 396static inline void 397tlbie(vaddr_t va) 398{ 399 __asm volatile ("tlbie %0" :: "r"(va)); 400} 401 402static inline void 403tlbsync(void) 404{ 405 __asm volatile ("sync; tlbsync; sync"); 406} 407 408void 409tlbia() 410{ 411 vaddr_t va; 412 413 __asm volatile ("sync"); 414 for (va = 0; va < 0x00040000; va += 0x00001000) 415 tlbie(va); 416 tlbsync(); 417} 418 419static inline int 420ptesr(sr_t *sr, vaddr_t va) 421{ 422 return sr[(u_int)va >> ADDR_SR_SHIFT]; 423} 424 425static inline int 426pteidx(sr_t sr, vaddr_t va) 427{ 428 int hash; 429 hash = (sr & SR_VSID) ^ (((u_int)va & ADDR_PIDX) >> ADDR_PIDX_SHIFT); 430 return hash & pmap_ptab_mask; 431} 432 433#define PTED_VA_PTEGIDX_M 0x07 434#define PTED_VA_HID_M 0x08 435#define PTED_VA_MANAGED_M 0x10 436#define PTED_VA_WIRED_M 0x20 437#define PTED_VA_EXEC_M 0x40 438 439static inline u_int32_t 440PTED_HID(struct pte_desc *pted) 441{ 442 return (pted->pted_va & PTED_VA_HID_M); 443} 444 445static inline u_int32_t 446PTED_PTEGIDX(struct pte_desc *pted) 447{ 448 return (pted->pted_va & PTED_VA_PTEGIDX_M); 449} 450 451static inline u_int32_t 452PTED_MANAGED(struct pte_desc *pted) 453{ 454 return (pted->pted_va & PTED_VA_MANAGED_M); 455} 456 457static inline u_int32_t 458PTED_WIRED(struct pte_desc *pted) 459{ 460 return (pted->pted_va & PTED_VA_WIRED_M); 461} 462 463static inline u_int32_t 464PTED_VALID(struct pte_desc *pted) 465{ 466 if (ppc_proc_is_64b) 467 return (pted->p.pted_pte64.pte_hi & PTE_VALID_64); 468 else 469 return (pted->p.pted_pte32.pte_hi & PTE_VALID_32); 470} 471 472/* 473 * PV entries - 474 * manipulate the physical to virtual translations for the entire system. 475 * 476 * QUESTION: should all mapped memory be stored in PV tables? Or 477 * is it alright to only store "ram" memory. Currently device mappings 478 * are not stored. 479 * It makes sense to pre-allocate mappings for all of "ram" memory, since 480 * it is likely that it will be mapped at some point, but would it also 481 * make sense to use a tree/table like is use for pmap to store device 482 * mappings? 483 * Further notes: It seems that the PV table is only used for pmap_protect 484 * and other paging related operations. Given this, it is not necessary 485 * to store any pmap_kernel() entries in PV tables and does not make 486 * sense to store device mappings in PV either. 487 * 488 * Note: unlike other powerpc pmap designs, the array is only an array 489 * of pointers. Since the same structure is used for holding information 490 * in the VP table, the PV table, and for kernel mappings, the wired entries. 491 * Allocate one data structure to hold all of the info, instead of replicating 492 * it multiple times. 493 * 494 * One issue of making this a single data structure is that two pointers are 495 * wasted for every page which does not map ram (device mappings), this 496 * should be a low percentage of mapped pages in the system, so should not 497 * have too noticable unnecessary ram consumption. 498 */ 499 500void 501pmap_enter_pv(struct pte_desc *pted, struct vm_page *pg) 502{ 503 if (__predict_false(!pmap_initialized)) { 504 return; 505 } 506 507 LIST_INSERT_HEAD(&(pg->mdpage.pv_list), pted, pted_pv_list); 508 pted->pted_va |= PTED_VA_MANAGED_M; 509} 510 511void 512pmap_remove_pv(struct pte_desc *pted) 513{ 514 LIST_REMOVE(pted, pted_pv_list); 515} 516 517 518/* PTE_CHG_32 == PTE_CHG_64 */ 519/* PTE_REF_32 == PTE_REF_64 */ 520static __inline u_int 521pmap_pte2flags(u_int32_t pte) 522{ 523 return (((pte & PTE_REF_32) ? PG_PMAP_REF : 0) | 524 ((pte & PTE_CHG_32) ? PG_PMAP_MOD : 0)); 525} 526 527static __inline u_int 528pmap_flags2pte(u_int32_t flags) 529{ 530 return (((flags & PG_PMAP_REF) ? PTE_REF_32 : 0) | 531 ((flags & PG_PMAP_MOD) ? PTE_CHG_32 : 0)); 532} 533 534void 535pmap_attr_save(paddr_t pa, u_int32_t bits) 536{ 537 struct vm_page *pg; 538 539 pg = PHYS_TO_VM_PAGE(pa); 540 if (pg == NULL) 541 return; 542 543 atomic_setbits_int(&pg->pg_flags, pmap_pte2flags(bits)); 544} 545 546int 547pmap_enter(pmap_t pm, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags) 548{ 549 struct pte_desc *pted; 550 struct vm_page *pg; 551 boolean_t nocache = (pa & PMAP_NOCACHE) != 0; 552 int s; 553 int need_sync = 0; 554 int cache; 555 int error; 556 557 /* MP - Acquire lock for this pmap */ 558 559 s = splvm(); 560 pted = pmap_vp_lookup(pm, va); 561 if (pted && PTED_VALID(pted)) { 562 pmap_remove_pg(pm, va); 563 /* we lost our pted if it was user */ 564 if (pm != pmap_kernel()) 565 pted = pmap_vp_lookup(pm, va); 566 } 567 568 pm->pm_stats.resident_count++; 569 570 /* Do not have pted for this, get one and put it in VP */ 571 if (pted == NULL) { 572 pted = pool_get(&pmap_pted_pool, PR_NOWAIT | PR_ZERO); 573 if (pted == NULL) { 574 if ((flags & PMAP_CANFAIL) == 0) { 575 splx(s); 576 return ENOMEM; 577 } 578 panic("pmap_enter: failed to allocate pted"); 579 } 580 error = pmap_vp_enter(pm, va, pted, flags); 581 if (error) { 582 pool_put(&pmap_pted_pool, pted); 583 splx(s); 584 return error; 585 } 586 } 587 588 pa &= PMAP_PA_MASK; 589 590 /* Calculate PTE */ 591 pg = PHYS_TO_VM_PAGE(pa); 592 if (pg != NULL && !nocache) 593 cache = PMAP_CACHE_WB; /* managed memory is cacheable */ 594 else 595 cache = PMAP_CACHE_CI; 596 597 if (ppc_proc_is_64b) 598 pmap_fill_pte64(pm, va, pa, pted, prot, flags, cache); 599 else 600 pmap_fill_pte32(pm, va, pa, pted, prot, flags, cache); 601 602 if (pg != NULL) { 603 pmap_enter_pv(pted, pg); /* only managed mem */ 604 } 605 606 /* 607 * Insert into HTAB 608 * We were told to map the page, probably called from vm_fault, 609 * so map the page! 610 */ 611 if (ppc_proc_is_64b) 612 pte_insert64(pted); 613 else 614 pte_insert32(pted); 615 616 if (prot & VM_PROT_EXECUTE) { 617 u_int sn = VP_SR(va); 618 619 pm->pm_exec[sn]++; 620 if (pm->pm_sr[sn] & SR_NOEXEC) 621 pm->pm_sr[sn] &= ~SR_NOEXEC; 622 623 if (pg != NULL) { 624 need_sync = ((pg->pg_flags & PG_PMAP_EXE) == 0); 625 if (prot & VM_PROT_WRITE) 626 atomic_clearbits_int(&pg->pg_flags, 627 PG_PMAP_EXE); 628 else 629 atomic_setbits_int(&pg->pg_flags, 630 PG_PMAP_EXE); 631 } else 632 need_sync = 1; 633 } else { 634 /* 635 * Should we be paranoid about writeable non-exec 636 * mappings ? if so, clear the exec tag 637 */ 638 if ((prot & VM_PROT_WRITE) && (pg != NULL)) 639 atomic_clearbits_int(&pg->pg_flags, PG_PMAP_EXE); 640 } 641 642 splx(s); 643 644 /* only instruction sync executable pages */ 645 if (need_sync) 646 pmap_syncicache_user_virt(pm, va); 647 648 /* MP - free pmap lock */ 649 return 0; 650} 651 652/* 653 * Remove the given range of mapping entries. 654 */ 655void 656pmap_remove(pmap_t pm, vaddr_t va, vaddr_t endva) 657{ 658 int i_sr, s_sr, e_sr; 659 int i_vp1, s_vp1, e_vp1; 660 int i_vp2, s_vp2, e_vp2; 661 struct pmapvp *vp1; 662 struct pmapvp *vp2; 663 664 /* I suspect that if this loop were unrolled better 665 * it would have better performance, testing i_sr and i_vp1 666 * in the middle loop seems excessive 667 */ 668 669 s_sr = VP_SR(va); 670 e_sr = VP_SR(endva); 671 for (i_sr = s_sr; i_sr <= e_sr; i_sr++) { 672 vp1 = pm->pm_vp[i_sr]; 673 if (vp1 == NULL) 674 continue; 675 676 if (i_sr == s_sr) 677 s_vp1 = VP_IDX1(va); 678 else 679 s_vp1 = 0; 680 681 if (i_sr == e_sr) 682 e_vp1 = VP_IDX1(endva); 683 else 684 e_vp1 = VP_IDX1_SIZE-1; 685 686 for (i_vp1 = s_vp1; i_vp1 <= e_vp1; i_vp1++) { 687 vp2 = vp1->vp[i_vp1]; 688 if (vp2 == NULL) 689 continue; 690 691 if ((i_sr == s_sr) && (i_vp1 == s_vp1)) 692 s_vp2 = VP_IDX2(va); 693 else 694 s_vp2 = 0; 695 696 if ((i_sr == e_sr) && (i_vp1 == e_vp1)) 697 e_vp2 = VP_IDX2(endva); 698 else 699 e_vp2 = VP_IDX2_SIZE; 700 701 for (i_vp2 = s_vp2; i_vp2 < e_vp2; i_vp2++) { 702 if (vp2->vp[i_vp2] != NULL) { 703 pmap_remove_pg(pm, 704 (i_sr << VP_SR_POS) | 705 (i_vp1 << VP_IDX1_POS) | 706 (i_vp2 << VP_IDX2_POS)); 707 } 708 } 709 } 710 } 711} 712/* 713 * remove a single mapping, notice that this code is O(1) 714 */ 715void 716pmap_remove_pg(pmap_t pm, vaddr_t va) 717{ 718 struct pte_desc *pted; 719 int s; 720 721 /* 722 * HASH needs to be locked here as well as pmap, and pv list. 723 * so that we know the mapping information is either valid, 724 * or that the mapping is not present in the hash table. 725 */ 726 s = splvm(); 727 if (pm == pmap_kernel()) { 728 pted = pmap_vp_lookup(pm, va); 729 if (pted == NULL || !PTED_VALID(pted)) { 730 splx(s); 731 return; 732 } 733 } else { 734 pted = pmap_vp_remove(pm, va); 735 if (pted == NULL || !PTED_VALID(pted)) { 736 splx(s); 737 return; 738 } 739 } 740 pm->pm_stats.resident_count--; 741 742 pmap_hash_remove(pted); 743 744 if (pted->pted_va & PTED_VA_EXEC_M) { 745 u_int sn = VP_SR(va); 746 747 pted->pted_va &= ~PTED_VA_EXEC_M; 748 pm->pm_exec[sn]--; 749 if (pm->pm_exec[sn] == 0) 750 pm->pm_sr[sn] |= SR_NOEXEC; 751 } 752 753 if (ppc_proc_is_64b) 754 pted->p.pted_pte64.pte_hi &= ~PTE_VALID_64; 755 else 756 pted->p.pted_pte32.pte_hi &= ~PTE_VALID_32; 757 758 if (PTED_MANAGED(pted)) 759 pmap_remove_pv(pted); 760 761 if (pm != pmap_kernel()) 762 pool_put(&pmap_pted_pool, pted); 763 764 splx(s); 765} 766 767/* 768 * Enter a kernel mapping for the given page. 769 * kernel mappings have a larger set of prerequisites than normal mappings. 770 * 771 * 1. no memory should be allocated to create a kernel mapping. 772 * 2. a vp mapping should already exist, even if invalid. (see 1) 773 * 3. all vp tree mappings should already exist (see 1) 774 * 775 */ 776void 777_pmap_kenter_pa(vaddr_t va, paddr_t pa, vm_prot_t prot, int flags, int cache) 778{ 779 struct pte_desc *pted; 780 struct vm_page *pg; 781 int s; 782 pmap_t pm; 783 784 pm = pmap_kernel(); 785 786 /* MP - lock pmap. */ 787 s = splvm(); 788 789 pted = pmap_vp_lookup(pm, va); 790 if (pted && PTED_VALID(pted)) 791 pmap_kremove_pg(va); /* pted is reused */ 792 793 pm->pm_stats.resident_count++; 794 if (prot & VM_PROT_WRITE) { 795 pg = PHYS_TO_VM_PAGE(pa); 796 if (pg != NULL) 797 atomic_clearbits_int(&pg->pg_flags, PG_PMAP_EXE); 798 } 799 800 /* Do not have pted for this, get one and put it in VP */ 801 if (pted == NULL) { 802 panic("pted not preallocated in pmap_kernel() va %lx pa %lx", 803 va, pa); 804 } 805 806 if (cache == PMAP_CACHE_DEFAULT) { 807 pg = PHYS_TO_VM_PAGE(pa); 808 if (pg != NULL && (pg->pg_flags & PG_DEV) == 0) 809 cache = PMAP_CACHE_WB; 810 else 811 cache = PMAP_CACHE_CI; 812 } 813 814 /* Calculate PTE */ 815 if (ppc_proc_is_64b) 816 pmap_fill_pte64(pm, va, pa, pted, prot, flags, cache); 817 else 818 pmap_fill_pte32(pm, va, pa, pted, prot, flags, cache); 819 820 /* 821 * Insert into HTAB 822 * We were told to map the page, probably called from vm_fault, 823 * so map the page! 824 */ 825 if (ppc_proc_is_64b) 826 pte_insert64(pted); 827 else 828 pte_insert32(pted); 829 830 pted->pted_va |= PTED_VA_WIRED_M; 831 832 if (prot & VM_PROT_EXECUTE) { 833 u_int sn = VP_SR(va); 834 835 pm->pm_exec[sn]++; 836 if (pm->pm_sr[sn] & SR_NOEXEC) 837 pm->pm_sr[sn] &= ~SR_NOEXEC; 838 } 839 840 splx(s); 841} 842 843void 844pmap_kenter_pa(vaddr_t va, paddr_t pa, vm_prot_t prot) 845{ 846 _pmap_kenter_pa(va, pa, prot, 0, PMAP_CACHE_DEFAULT); 847} 848 849void 850pmap_kenter_cache(vaddr_t va, paddr_t pa, vm_prot_t prot, int cacheable) 851{ 852 _pmap_kenter_pa(va, pa, prot, 0, cacheable); 853} 854 855 856/* 857 * remove kernel (pmap_kernel()) mapping, one page 858 */ 859void 860pmap_kremove_pg(vaddr_t va) 861{ 862 struct pte_desc *pted; 863 pmap_t pm; 864 int s; 865 866 pm = pmap_kernel(); 867 pted = pmap_vp_lookup(pm, va); 868 if (pted == NULL) 869 return; 870 871 if (!PTED_VALID(pted)) 872 return; /* not mapped */ 873 874 s = splvm(); 875 876 pm->pm_stats.resident_count--; 877 878 /* 879 * HASH needs to be locked here as well as pmap, and pv list. 880 * so that we know the mapping information is either valid, 881 * or that the mapping is not present in the hash table. 882 */ 883 pmap_hash_remove(pted); 884 885 if (pted->pted_va & PTED_VA_EXEC_M) { 886 u_int sn = VP_SR(va); 887 888 pted->pted_va &= ~PTED_VA_EXEC_M; 889 pm->pm_exec[sn]--; 890 if (pm->pm_exec[sn] == 0) 891 pm->pm_sr[sn] |= SR_NOEXEC; 892 } 893 894 if (PTED_MANAGED(pted)) 895 pmap_remove_pv(pted); 896 897 /* invalidate pted; */ 898 if (ppc_proc_is_64b) 899 pted->p.pted_pte64.pte_hi &= ~PTE_VALID_64; 900 else 901 pted->p.pted_pte32.pte_hi &= ~PTE_VALID_32; 902 903 splx(s); 904 905} 906/* 907 * remove kernel (pmap_kernel()) mappings 908 */ 909void 910pmap_kremove(vaddr_t va, vsize_t len) 911{ 912 for (len >>= PAGE_SHIFT; len >0; len--, va += PAGE_SIZE) 913 pmap_kremove_pg(va); 914} 915 916void 917pte_zap(void *ptp, struct pte_desc *pted) 918{ 919 920 struct pte_64 *ptp64 = (void*) ptp; 921 struct pte_32 *ptp32 = (void*) ptp; 922 923 if (ppc_proc_is_64b) 924 ptp64->pte_hi &= ~PTE_VALID_64; 925 else 926 ptp32->pte_hi &= ~PTE_VALID_32; 927 928 __asm volatile ("sync"); 929 tlbie(pted->pted_va); 930 __asm volatile ("sync"); 931 tlbsync(); 932 __asm volatile ("sync"); 933 if (ppc_proc_is_64b) { 934 if (PTED_MANAGED(pted)) 935 pmap_attr_save(pted->p.pted_pte64.pte_lo & PTE_RPGN_64, 936 ptp64->pte_lo & (PTE_REF_64|PTE_CHG_64)); 937 } else { 938 if (PTED_MANAGED(pted)) 939 pmap_attr_save(pted->p.pted_pte32.pte_lo & PTE_RPGN_32, 940 ptp32->pte_lo & (PTE_REF_32|PTE_CHG_32)); 941 } 942} 943 944/* 945 * remove specified entry from hash table. 946 * all information is present in pted to look up entry 947 * LOCKS... should the caller lock? 948 */ 949void 950pmap_hash_remove(struct pte_desc *pted) 951{ 952 vaddr_t va = pted->pted_va; 953 pmap_t pm = pted->pted_pmap; 954 struct pte_64 *ptp64; 955 struct pte_32 *ptp32; 956 int sr, idx; 957 int s; 958 959 sr = ptesr(pm->pm_sr, va); 960 idx = pteidx(sr, va); 961 962 idx = (idx ^ (PTED_HID(pted) ? pmap_ptab_mask : 0)); 963 /* determine which pteg mapping is present in */ 964 965 if (ppc_proc_is_64b) { 966 int entry = PTED_PTEGIDX(pted); 967 ptp64 = pmap_ptable64 + (idx * 8); 968 ptp64 += entry; /* increment by entry into pteg */ 969 s = ppc_intr_disable(); 970 pmap_hash_lock(entry); 971 /* 972 * We now have the pointer to where it will be, if it is 973 * currently mapped. If the mapping was thrown away in 974 * exchange for another page mapping, then this page is not 975 * currently in the HASH. 976 */ 977 if ((pted->p.pted_pte64.pte_hi | 978 (PTED_HID(pted) ? PTE_HID_64 : 0)) == ptp64->pte_hi) { 979 pte_zap((void*)ptp64, pted); 980 } 981 pmap_hash_unlock(entry); 982 ppc_intr_enable(s); 983 } else { 984 int entry = PTED_PTEGIDX(pted); 985 ptp32 = pmap_ptable32 + (idx * 8); 986 ptp32 += entry; /* increment by entry into pteg */ 987 s = ppc_intr_disable(); 988 pmap_hash_lock(entry); 989 /* 990 * We now have the pointer to where it will be, if it is 991 * currently mapped. If the mapping was thrown away in 992 * exchange for another page mapping, then this page is not 993 * currently in the HASH. 994 */ 995 if ((pted->p.pted_pte32.pte_hi | 996 (PTED_HID(pted) ? PTE_HID_32 : 0)) == ptp32->pte_hi) { 997 pte_zap((void*)ptp32, pted); 998 } 999 pmap_hash_unlock(entry); 1000 ppc_intr_enable(s); 1001 } 1002} 1003 1004/* 1005 * What about execution control? Even at only a segment granularity. 1006 */ 1007void 1008pmap_fill_pte64(pmap_t pm, vaddr_t va, paddr_t pa, struct pte_desc *pted, 1009 vm_prot_t prot, int flags, int cache) 1010{ 1011 sr_t sr; 1012 struct pte_64 *pte64; 1013 1014 sr = ptesr(pm->pm_sr, va); 1015 pte64 = &pted->p.pted_pte64; 1016 1017 pte64->pte_hi = (((u_int64_t)sr & SR_VSID) << 1018 PTE_VSID_SHIFT_64) | 1019 ((va >> ADDR_API_SHIFT_64) & PTE_API_64) | PTE_VALID_64; 1020 pte64->pte_lo = (pa & PTE_RPGN_64); 1021 1022 1023 if (cache == PMAP_CACHE_WB) 1024 pte64->pte_lo |= PTE_M_64; 1025 else if (cache == PMAP_CACHE_WT) 1026 pte64->pte_lo |= (PTE_W_64 | PTE_M_64); 1027 else 1028 pte64->pte_lo |= (PTE_M_64 | PTE_I_64 | PTE_G_64); 1029 1030 if (prot & VM_PROT_WRITE) 1031 pte64->pte_lo |= PTE_RW_64; 1032 else 1033 pte64->pte_lo |= PTE_RO_64; 1034 1035 pted->pted_va = va & ~PAGE_MASK; 1036 1037 if (prot & VM_PROT_EXECUTE) 1038 pted->pted_va |= PTED_VA_EXEC_M; 1039 else 1040 pte64->pte_lo |= PTE_N_64; 1041 1042 pted->pted_pmap = pm; 1043} 1044/* 1045 * What about execution control? Even at only a segment granularity. 1046 */ 1047void 1048pmap_fill_pte32(pmap_t pm, vaddr_t va, paddr_t pa, struct pte_desc *pted, 1049 vm_prot_t prot, int flags, int cache) 1050{ 1051 sr_t sr; 1052 struct pte_32 *pte32; 1053 1054 sr = ptesr(pm->pm_sr, va); 1055 pte32 = &pted->p.pted_pte32; 1056 1057 pte32->pte_hi = ((sr & SR_VSID) << PTE_VSID_SHIFT_32) | 1058 ((va >> ADDR_API_SHIFT_32) & PTE_API_32) | PTE_VALID_32; 1059 pte32->pte_lo = (pa & PTE_RPGN_32); 1060 1061 if (cache == PMAP_CACHE_WB) 1062 pte32->pte_lo |= PTE_M_32; 1063 else if (cache == PMAP_CACHE_WT) 1064 pte32->pte_lo |= (PTE_W_32 | PTE_M_32); 1065 else 1066 pte32->pte_lo |= (PTE_M_32 | PTE_I_32 | PTE_G_32); 1067 1068 if (prot & VM_PROT_WRITE) 1069 pte32->pte_lo |= PTE_RW_32; 1070 else 1071 pte32->pte_lo |= PTE_RO_32; 1072 1073 pted->pted_va = va & ~PAGE_MASK; 1074 1075 /* XXX Per-page execution control. */ 1076 if (prot & VM_PROT_EXECUTE) 1077 pted->pted_va |= PTED_VA_EXEC_M; 1078 1079 pted->pted_pmap = pm; 1080} 1081 1082/* 1083 * read/clear bits from pte/attr cache, for reference/change 1084 * ack, copied code in the pte flush code.... 1085 */ 1086int 1087pteclrbits(struct vm_page *pg, u_int flagbit, u_int clear) 1088{ 1089 u_int bits; 1090 int s; 1091 struct pte_desc *pted; 1092 u_int ptebit = pmap_flags2pte(flagbit); 1093 1094 /* PTE_CHG_32 == PTE_CHG_64 */ 1095 /* PTE_REF_32 == PTE_REF_64 */ 1096 1097 /* 1098 * First try the attribute cache 1099 */ 1100 bits = pg->pg_flags & flagbit; 1101 if ((bits == flagbit) && (clear == 0)) 1102 return bits; 1103 1104 /* cache did not contain all necessary bits, 1105 * need to walk thru pv table to collect all mappings for this 1106 * page, copying bits to the attribute cache 1107 * then reread the attribute cache. 1108 */ 1109 /* need lock for this pv */ 1110 s = splvm(); 1111 1112 LIST_FOREACH(pted, &(pg->mdpage.pv_list), pted_pv_list) { 1113 vaddr_t va = pted->pted_va & PAGE_MASK; 1114 pmap_t pm = pted->pted_pmap; 1115 struct pte_64 *ptp64; 1116 struct pte_32 *ptp32; 1117 int sr, idx; 1118 1119 sr = ptesr(pm->pm_sr, va); 1120 idx = pteidx(sr, va); 1121 1122 /* determine which pteg mapping is present in */ 1123 if (ppc_proc_is_64b) { 1124 ptp64 = pmap_ptable64 + 1125 (idx ^ (PTED_HID(pted) ? pmap_ptab_mask : 0)) * 8; 1126 ptp64 += PTED_PTEGIDX(pted); /* increment by index into pteg */ 1127 1128 /* 1129 * We now have the pointer to where it will be, if it is 1130 * currently mapped. If the mapping was thrown away in 1131 * exchange for another page mapping, then this page is 1132 * not currently in the HASH. 1133 * 1134 * if we are not clearing bits, and have found all of the 1135 * bits we want, we can stop 1136 */ 1137 if ((pted->p.pted_pte64.pte_hi | 1138 (PTED_HID(pted) ? PTE_HID_64 : 0)) == ptp64->pte_hi) { 1139 bits |= pmap_pte2flags(ptp64->pte_lo & ptebit); 1140 if (clear) { 1141 ptp64->pte_hi &= ~PTE_VALID_64; 1142 __asm__ volatile ("sync"); 1143 tlbie(va); 1144 tlbsync(); 1145 ptp64->pte_lo &= ~ptebit; 1146 __asm__ volatile ("sync"); 1147 ptp64->pte_hi |= PTE_VALID_64; 1148 } else if (bits == flagbit) 1149 break; 1150 } 1151 } else { 1152 ptp32 = pmap_ptable32 + 1153 (idx ^ (PTED_HID(pted) ? pmap_ptab_mask : 0)) * 8; 1154 ptp32 += PTED_PTEGIDX(pted); /* increment by index into pteg */ 1155 1156 /* 1157 * We now have the pointer to where it will be, if it is 1158 * currently mapped. If the mapping was thrown away in 1159 * exchange for another page mapping, then this page is 1160 * not currently in the HASH. 1161 * 1162 * if we are not clearing bits, and have found all of the 1163 * bits we want, we can stop 1164 */ 1165 if ((pted->p.pted_pte32.pte_hi | 1166 (PTED_HID(pted) ? PTE_HID_32 : 0)) == ptp32->pte_hi) { 1167 bits |= pmap_pte2flags(ptp32->pte_lo & ptebit); 1168 if (clear) { 1169 ptp32->pte_hi &= ~PTE_VALID_32; 1170 __asm__ volatile ("sync"); 1171 tlbie(va); 1172 tlbsync(); 1173 ptp32->pte_lo &= ~ptebit; 1174 __asm__ volatile ("sync"); 1175 ptp32->pte_hi |= PTE_VALID_32; 1176 } else if (bits == flagbit) 1177 break; 1178 } 1179 } 1180 } 1181 1182 if (clear) { 1183 /* 1184 * this is done a second time, because while walking the list 1185 * a bit could have been promoted via pmap_attr_save() 1186 */ 1187 bits |= pg->pg_flags & flagbit; 1188 atomic_clearbits_int(&pg->pg_flags, flagbit); 1189 } else 1190 atomic_setbits_int(&pg->pg_flags, bits); 1191 1192 splx(s); 1193 return bits; 1194} 1195 1196/* 1197 * Garbage collects the physical map system for pages which are 1198 * no longer used. Success need not be guaranteed -- that is, there 1199 * may well be pages which are not referenced, but others may be collected 1200 * Called by the pageout daemon when pages are scarce. 1201 */ 1202void 1203pmap_collect(pmap_t pm) 1204{ 1205 /* This could return unused v->p table layers which 1206 * are empty. 1207 * could malicious programs allocate memory and eat 1208 * these wired pages? These are allocated via pool. 1209 * Are there pool functions which could be called 1210 * to lower the pool usage here? 1211 */ 1212} 1213 1214/* 1215 * Fill the given physical page with zeros. 1216 */ 1217void 1218pmap_zero_page(struct vm_page *pg) 1219{ 1220 paddr_t pa = VM_PAGE_TO_PHYS(pg); 1221#ifdef USE_DCBZ 1222 int i; 1223 paddr_t addr = zero_page; 1224#endif 1225 1226 /* simple_lock(&pmap_zero_page_lock); */ 1227 pmap_kenter_pa(zero_page, pa, VM_PROT_READ|VM_PROT_WRITE); 1228#ifdef USE_DCBZ 1229 for (i = PAGE_SIZE/CACHELINESIZE; i>0; i--) { 1230 __asm volatile ("dcbz 0,%0" :: "r"(addr)); 1231 addr += CACHELINESIZE; 1232 } 1233#else 1234 bzero((void *)zero_page, PAGE_SIZE); 1235#endif 1236 pmap_kremove_pg(zero_page); 1237 1238 /* simple_unlock(&pmap_zero_page_lock); */ 1239} 1240 1241/* 1242 * copy the given physical page with zeros. 1243 */ 1244void 1245pmap_copy_page(struct vm_page *srcpg, struct vm_page *dstpg) 1246{ 1247 paddr_t srcpa = VM_PAGE_TO_PHYS(srcpg); 1248 paddr_t dstpa = VM_PAGE_TO_PHYS(dstpg); 1249 /* simple_lock(&pmap_copy_page_lock); */ 1250 1251 pmap_kenter_pa(copy_src_page, srcpa, VM_PROT_READ); 1252 pmap_kenter_pa(copy_dst_page, dstpa, VM_PROT_READ|VM_PROT_WRITE); 1253 1254 bcopy((void *)copy_src_page, (void *)copy_dst_page, PAGE_SIZE); 1255 1256 pmap_kremove_pg(copy_src_page); 1257 pmap_kremove_pg(copy_dst_page); 1258 /* simple_unlock(&pmap_copy_page_lock); */ 1259} 1260 1261int pmap_id_avail = 0; 1262 1263void 1264pmap_pinit(pmap_t pm) 1265{ 1266 int i, k, try, tblidx, tbloff; 1267 int s, seg; 1268 1269 bzero(pm, sizeof (struct pmap)); 1270 1271 pmap_reference(pm); 1272 1273 /* 1274 * Allocate segment registers for this pmap. 1275 * Try not to reuse pmap ids, to spread the hash table usage. 1276 */ 1277again: 1278 for (i = 0; i < NPMAPS; i++) { 1279 try = pmap_id_avail + i; 1280 try = try % NPMAPS; /* truncate back into bounds */ 1281 tblidx = try / (8 * sizeof usedsr[0]); 1282 tbloff = try % (8 * sizeof usedsr[0]); 1283 if ((usedsr[tblidx] & (1 << tbloff)) == 0) { 1284 /* pmap create lock? */ 1285 s = splvm(); 1286 if ((usedsr[tblidx] & (1 << tbloff)) == 1) { 1287 /* entry was stolen out from under us, retry */ 1288 splx(s); /* pmap create unlock */ 1289 goto again; 1290 } 1291 usedsr[tblidx] |= (1 << tbloff); 1292 pmap_id_avail = try + 1; 1293 splx(s); /* pmap create unlock */ 1294 1295 seg = try << 4; 1296 for (k = 0; k < 16; k++) 1297 pm->pm_sr[k] = (seg + k) | SR_NOEXEC; 1298 return; 1299 } 1300 } 1301 panic("out of pmap slots"); 1302} 1303 1304/* 1305 * Create and return a physical map. 1306 */ 1307pmap_t 1308pmap_create() 1309{ 1310 pmap_t pmap; 1311 1312 pmap = pool_get(&pmap_pmap_pool, PR_WAITOK); 1313 pmap_pinit(pmap); 1314 return (pmap); 1315} 1316 1317/* 1318 * Add a reference to a given pmap. 1319 */ 1320void 1321pmap_reference(pmap_t pm) 1322{ 1323 /* simple_lock(&pmap->pm_obj.vmobjlock); */ 1324 pm->pm_refs++; 1325 /* simple_unlock(&pmap->pm_obj.vmobjlock); */ 1326} 1327 1328/* 1329 * Retire the given pmap from service. 1330 * Should only be called if the map contains no valid mappings. 1331 */ 1332void 1333pmap_destroy(pmap_t pm) 1334{ 1335 int refs; 1336 1337 /* simple_lock(&pmap->pm_obj.vmobjlock); */ 1338 refs = --pm->pm_refs; 1339 /* simple_unlock(&pmap->pm_obj.vmobjlock); */ 1340 if (refs > 0) 1341 return; 1342 1343 /* 1344 * reference count is zero, free pmap resources and free pmap. 1345 */ 1346 pmap_release(pm); 1347 pool_put(&pmap_pmap_pool, pm); 1348} 1349 1350/* 1351 * Release any resources held by the given physical map. 1352 * Called when a pmap initialized by pmap_pinit is being released. 1353 */ 1354void 1355pmap_release(pmap_t pm) 1356{ 1357 int i, tblidx, tbloff; 1358 int s; 1359 1360 pmap_vp_destroy(pm); 1361 i = (pm->pm_sr[0] & SR_VSID) >> 4; 1362 tblidx = i / (8 * sizeof usedsr[0]); 1363 tbloff = i % (8 * sizeof usedsr[0]); 1364 1365 /* LOCK? */ 1366 s = splvm(); 1367 usedsr[tblidx] &= ~(1 << tbloff); 1368 splx(s); 1369} 1370 1371void 1372pmap_vp_destroy(pmap_t pm) 1373{ 1374 int i, j; 1375 struct pmapvp *vp1; 1376 struct pmapvp *vp2; 1377 1378 for (i = 0; i < VP_SR_SIZE; i++) { 1379 vp1 = pm->pm_vp[i]; 1380 if (vp1 == NULL) 1381 continue; 1382 1383 for (j = 0; j < VP_IDX1_SIZE; j++) { 1384 vp2 = vp1->vp[j]; 1385 if (vp2 == NULL) 1386 continue; 1387 1388 pool_put(&pmap_vp_pool, vp2); 1389 } 1390 pm->pm_vp[i] = NULL; 1391 pool_put(&pmap_vp_pool, vp1); 1392 } 1393} 1394 1395void 1396pmap_avail_setup(void) 1397{ 1398 struct mem_region *mp; 1399 int pmap_physmem; 1400 1401 (fw->mem_regions) (&pmap_mem, &pmap_avail); 1402 pmap_cnt_avail = 0; 1403 pmap_physmem = 0; 1404 1405 ndumpmem = 0; 1406 for (mp = pmap_mem; mp->size !=0; mp++, ndumpmem++) { 1407 pmap_physmem += atop(mp->size); 1408 dumpmem[ndumpmem].start = atop(mp->start); 1409 dumpmem[ndumpmem].end = atop(mp->start + mp->size); 1410 } 1411 1412 if (physmem == 0) 1413 physmem = pmap_physmem; 1414 1415 for (mp = pmap_avail; mp->size !=0 ; mp++) { 1416 if (physmaxaddr < mp->start + mp->size) 1417 physmaxaddr = mp->start + mp->size; 1418 } 1419 1420 for (mp = pmap_avail; mp->size !=0; mp++) 1421 pmap_cnt_avail += 1; 1422} 1423 1424void 1425pmap_avail_fixup(void) 1426{ 1427 struct mem_region *mp; 1428 u_int32_t align; 1429 u_int32_t end; 1430 1431 mp = pmap_avail; 1432 while(mp->size !=0) { 1433 align = round_page(mp->start); 1434 if (mp->start != align) { 1435 pmap_remove_avail(mp->start, align); 1436 mp = pmap_avail; 1437 continue; 1438 } 1439 end = mp->start+mp->size; 1440 align = trunc_page(end); 1441 if (end != align) { 1442 pmap_remove_avail(align, end); 1443 mp = pmap_avail; 1444 continue; 1445 } 1446 mp++; 1447 } 1448} 1449 1450/* remove a given region from avail memory */ 1451void 1452pmap_remove_avail(paddr_t base, paddr_t end) 1453{ 1454 struct mem_region *mp; 1455 int i; 1456 int mpend; 1457 1458 /* remove given region from available */ 1459 for (mp = pmap_avail; mp->size; mp++) { 1460 /* 1461 * Check if this region holds all of the region 1462 */ 1463 mpend = mp->start + mp->size; 1464 if (base > mpend) { 1465 continue; 1466 } 1467 if (base <= mp->start) { 1468 if (end <= mp->start) 1469 break; /* region not present -??? */ 1470 1471 if (end >= mpend) { 1472 /* covers whole region */ 1473 /* shorten */ 1474 for (i = mp - pmap_avail; 1475 i < pmap_cnt_avail; 1476 i++) { 1477 pmap_avail[i] = pmap_avail[i+1]; 1478 } 1479 pmap_cnt_avail--; 1480 pmap_avail[pmap_cnt_avail].size = 0; 1481 } else { 1482 mp->start = end; 1483 mp->size = mpend - end; 1484 } 1485 } else { 1486 /* start after the beginning */ 1487 if (end >= mpend) { 1488 /* just truncate */ 1489 mp->size = base - mp->start; 1490 } else { 1491 /* split */ 1492 for (i = pmap_cnt_avail; 1493 i > (mp - pmap_avail); 1494 i--) { 1495 pmap_avail[i] = pmap_avail[i - 1]; 1496 } 1497 pmap_cnt_avail++; 1498 mp->size = base - mp->start; 1499 mp++; 1500 mp->start = end; 1501 mp->size = mpend - end; 1502 } 1503 } 1504 } 1505 for (mp = pmap_allocated; mp->size != 0; mp++) { 1506 if (base < mp->start) { 1507 if (end == mp->start) { 1508 mp->start = base; 1509 mp->size += end - base; 1510 break; 1511 } 1512 /* lengthen */ 1513 for (i = pmap_cnt_allocated; i > (mp - pmap_allocated); 1514 i--) { 1515 pmap_allocated[i] = pmap_allocated[i - 1]; 1516 } 1517 pmap_cnt_allocated++; 1518 mp->start = base; 1519 mp->size = end - base; 1520 return; 1521 } 1522 if (base == (mp->start + mp->size)) { 1523 mp->size += end - base; 1524 return; 1525 } 1526 } 1527 if (mp->size == 0) { 1528 mp->start = base; 1529 mp->size = end - base; 1530 pmap_cnt_allocated++; 1531 } 1532} 1533 1534void * 1535pmap_steal_avail(size_t size, int align) 1536{ 1537 struct mem_region *mp; 1538 int start; 1539 int remsize; 1540 1541 for (mp = pmap_avail; mp->size; mp++) { 1542 if (mp->size > size) { 1543 start = (mp->start + (align -1)) & ~(align -1); 1544 remsize = mp->size - (start - mp->start); 1545 if (remsize >= 0) { 1546 pmap_remove_avail(start, start+size); 1547 return (void *)start; 1548 } 1549 } 1550 } 1551 panic ("unable to allocate region with size %x align %x", 1552 size, align); 1553} 1554 1555/* 1556 * Similar to pmap_steal_avail, but operating on vm_physmem since 1557 * uvm_page_physload() has been called. 1558 */ 1559vaddr_t 1560pmap_steal_memory(vsize_t size, vaddr_t *start, vaddr_t *end) 1561{ 1562 int segno; 1563 u_int npg; 1564 vaddr_t va; 1565 paddr_t pa; 1566 struct vm_physseg *seg; 1567 1568 size = round_page(size); 1569 npg = atop(size); 1570 1571 for (segno = 0, seg = vm_physmem; segno < vm_nphysseg; segno++, seg++) { 1572 if (seg->avail_end - seg->avail_start < npg) 1573 continue; 1574 /* 1575 * We can only steal at an ``unused'' segment boundary, 1576 * i.e. either at the start or at the end. 1577 */ 1578 if (seg->avail_start == seg->start || 1579 seg->avail_end == seg->end) 1580 break; 1581 } 1582 if (segno == vm_nphysseg) 1583 va = 0; 1584 else { 1585 if (seg->avail_start == seg->start) { 1586 pa = ptoa(seg->avail_start); 1587 seg->avail_start += npg; 1588 seg->start += npg; 1589 } else { 1590 pa = ptoa(seg->avail_end) - size; 1591 seg->avail_end -= npg; 1592 seg->end -= npg; 1593 } 1594 /* 1595 * If all the segment has been consumed now, remove it. 1596 * Note that the crash dump code still knows about it 1597 * and will dump it correctly. 1598 */ 1599 if (seg->start == seg->end) { 1600 if (vm_nphysseg-- == 1) 1601 panic("pmap_steal_memory: out of memory"); 1602 while (segno < vm_nphysseg) { 1603 seg[0] = seg[1]; /* struct copy */ 1604 seg++; 1605 segno++; 1606 } 1607 } 1608 1609 va = (vaddr_t)pa; /* 1:1 mapping */ 1610 bzero((void *)va, size); 1611 } 1612 1613 if (start != NULL) 1614 *start = VM_MIN_KERNEL_ADDRESS; 1615 if (end != NULL) 1616 *end = VM_MAX_KERNEL_ADDRESS; 1617 1618 return (va); 1619} 1620 1621void *msgbuf_addr; 1622 1623/* 1624 * Initialize pmap setup. 1625 * ALL of the code which deals with avail needs rewritten as an actual 1626 * memory allocation. 1627 */ 1628void 1629pmap_bootstrap(u_int kernelstart, u_int kernelend) 1630{ 1631 struct mem_region *mp; 1632 int i, k; 1633 struct pmapvp *vp1; 1634 struct pmapvp *vp2; 1635 1636 ppc_check_procid(); 1637 1638 /* 1639 * Get memory. 1640 */ 1641 pmap_avail_setup(); 1642 1643 /* 1644 * Page align all regions. 1645 * Non-page memory isn't very interesting to us. 1646 * Also, sort the entries for ascending addresses. 1647 */ 1648 kernelstart = trunc_page(kernelstart); 1649 kernelend = round_page(kernelend); 1650 pmap_remove_avail(kernelstart, kernelend); 1651 1652 msgbuf_addr = pmap_steal_avail(MSGBUFSIZE,4); 1653 1654#ifdef DEBUG 1655 for (mp = pmap_avail; mp->size; mp++) { 1656 bzero((void *)mp->start, mp->size); 1657 } 1658#endif 1659 1660#define HTABENTS_32 1024 1661#define HTABENTS_64 2048 1662 1663 if (ppc_proc_is_64b) { 1664 pmap_ptab_cnt = HTABENTS_64; 1665 while (pmap_ptab_cnt * 2 < physmem) 1666 pmap_ptab_cnt <<= 1; 1667 } else { 1668 pmap_ptab_cnt = HTABENTS_32; 1669 while (HTABSIZE_32 < (ptoa(physmem) >> 7)) 1670 pmap_ptab_cnt <<= 1; 1671 } 1672 /* 1673 * allocate suitably aligned memory for HTAB 1674 */ 1675 if (ppc_proc_is_64b) { 1676 pmap_ptable64 = pmap_steal_avail(HTABMEMSZ_64, HTABMEMSZ_64); 1677 bzero((void *)pmap_ptable64, HTABMEMSZ_64); 1678 pmap_ptab_mask = pmap_ptab_cnt - 1; 1679 } else { 1680 pmap_ptable32 = pmap_steal_avail(HTABSIZE_32, HTABSIZE_32); 1681 bzero((void *)pmap_ptable32, HTABSIZE_32); 1682 pmap_ptab_mask = pmap_ptab_cnt - 1; 1683 } 1684 1685 /* allocate v->p mappings for pmap_kernel() */ 1686 for (i = 0; i < VP_SR_SIZE; i++) { 1687 pmap_kernel()->pm_vp[i] = NULL; 1688 } 1689 vp1 = pmap_steal_avail(sizeof (struct pmapvp), 4); 1690 bzero (vp1, sizeof(struct pmapvp)); 1691 pmap_kernel()->pm_vp[PPC_KERNEL_SR] = vp1; 1692 for (i = 0; i < VP_IDX1_SIZE; i++) { 1693 vp2 = vp1->vp[i] = pmap_steal_avail(sizeof (struct pmapvp), 4); 1694 bzero (vp2, sizeof(struct pmapvp)); 1695 for (k = 0; k < VP_IDX2_SIZE; k++) { 1696 struct pte_desc *pted; 1697 pted = pmap_steal_avail(sizeof (struct pte_desc), 4); 1698 bzero (pted, sizeof (struct pte_desc)); 1699 vp2->vp[k] = pted; 1700 } 1701 } 1702 1703 if (ppc_proc_is_64b) { 1704 vp1 = pmap_steal_avail(sizeof (struct pmapvp), 4); 1705 bzero (vp1, sizeof(struct pmapvp)); 1706 pmap_kernel()->pm_vp[0] = vp1; 1707 for (i = 0; i < VP_IDX1_SIZE; i++) { 1708 vp2 = vp1->vp[i] = 1709 pmap_steal_avail(sizeof (struct pmapvp), 4); 1710 bzero (vp2, sizeof(struct pmapvp)); 1711 for (k = 0; k < VP_IDX2_SIZE; k++) { 1712 struct pte_desc *pted; 1713 pted = pmap_steal_avail(sizeof (struct pte_desc), 4); 1714 bzero (pted, sizeof (struct pte_desc)); 1715 vp2->vp[k] = pted; 1716 } 1717 } 1718 } 1719 1720 zero_page = VM_MIN_KERNEL_ADDRESS + ppc_kvm_stolen; 1721 ppc_kvm_stolen += PAGE_SIZE; 1722 copy_src_page = VM_MIN_KERNEL_ADDRESS + ppc_kvm_stolen; 1723 ppc_kvm_stolen += PAGE_SIZE; 1724 copy_dst_page = VM_MIN_KERNEL_ADDRESS + ppc_kvm_stolen; 1725 ppc_kvm_stolen += PAGE_SIZE; 1726 ppc_kvm_stolen += reserve_dumppages( (caddr_t)(VM_MIN_KERNEL_ADDRESS + 1727 ppc_kvm_stolen)); 1728 1729 1730 /* 1731 * Initialize kernel pmap and hardware. 1732 */ 1733#if NPMAPS >= PPC_KERNEL_SEGMENT / 16 1734 usedsr[PPC_KERNEL_SEGMENT / 16 / (sizeof usedsr[0] * 8)] 1735 |= 1 << ((PPC_KERNEL_SEGMENT / 16) % (sizeof usedsr[0] * 8)); 1736#endif 1737 for (i = 0; i < 16; i++) { 1738 pmap_kernel()->pm_sr[i] = (PPC_KERNEL_SEG0 + i) | SR_NOEXEC; 1739 ppc_mtsrin(PPC_KERNEL_SEG0 + i, i << ADDR_SR_SHIFT); 1740 } 1741 1742 if (ppc_proc_is_64b) { 1743 for(i = 0; i < 0x10000; i++) 1744 pmap_kenter_cache(ptoa(i), ptoa(i), VM_PROT_ALL, 1745 PMAP_CACHE_WB); 1746 asm volatile ("sync; mtsdr1 %0; isync" 1747 :: "r"((u_int)pmap_ptable64 | HTABSIZE_64)); 1748 } else 1749 asm volatile ("sync; mtsdr1 %0; isync" 1750 :: "r"((u_int)pmap_ptable32 | (pmap_ptab_mask >> 10))); 1751 1752 pmap_avail_fixup(); 1753 1754 1755 tlbia(); 1756 1757 pmap_avail_fixup(); 1758 for (mp = pmap_avail; mp->size; mp++) { 1759 if (mp->start > 0x80000000) 1760 continue; 1761 if (mp->start + mp->size > 0x80000000) 1762 mp->size = 0x80000000 - mp->start; 1763 uvm_page_physload(atop(mp->start), atop(mp->start+mp->size), 1764 atop(mp->start), atop(mp->start+mp->size), 0); 1765 } 1766} 1767 1768/* 1769 * activate a pmap entry 1770 * NOOP on powerpc, all PTE entries exist in the same hash table. 1771 * Segment registers are filled on exit to user mode. 1772 */ 1773void 1774pmap_activate(struct proc *p) 1775{ 1776} 1777 1778/* 1779 * deactivate a pmap entry 1780 * NOOP on powerpc 1781 */ 1782void 1783pmap_deactivate(struct proc *p) 1784{ 1785} 1786 1787/* 1788 * Get the physical page address for the given pmap/virtual address. 1789 */ 1790boolean_t 1791pmap_extract(pmap_t pm, vaddr_t va, paddr_t *pa) 1792{ 1793 struct pte_desc *pted; 1794 1795 pted = pmap_vp_lookup(pm, va); 1796 if (pted == NULL || !PTED_VALID(pted)) { 1797 if (pm == pmap_kernel() && va < 0x80000000) { 1798 /* XXX - this is not true without BATs */ 1799 /* if in kernel, va==pa for 0-0x80000000 */ 1800 *pa = va; 1801 return TRUE; 1802 } 1803 return FALSE; 1804 } 1805 if (ppc_proc_is_64b) 1806 *pa = (pted->p.pted_pte64.pte_lo & PTE_RPGN_64) | 1807 (va & ~PTE_RPGN_64); 1808 else 1809 *pa = (pted->p.pted_pte32.pte_lo & PTE_RPGN_32) | 1810 (va & ~PTE_RPGN_32); 1811 return TRUE; 1812} 1813 1814u_int32_t 1815pmap_setusr(pmap_t pm, vaddr_t va) 1816{ 1817 u_int32_t sr; 1818 u_int32_t oldsr; 1819 1820 sr = pm->pm_sr[(u_int)va >> ADDR_SR_SHIFT]; 1821 1822 /* user address range lock?? */ 1823 asm volatile ("mfsr %0,%1" 1824 : "=r" (oldsr): "n"(PPC_USER_SR)); 1825 asm volatile ("isync; mtsr %0,%1; isync" 1826 :: "n"(PPC_USER_SR), "r"(sr)); 1827 return oldsr; 1828} 1829 1830void 1831pmap_popusr(u_int32_t sr) 1832{ 1833 asm volatile ("isync; mtsr %0,%1; isync" 1834 :: "n"(PPC_USER_SR), "r"(sr)); 1835} 1836 1837int 1838copyin(const void *udaddr, void *kaddr, size_t len) 1839{ 1840 void *p; 1841 size_t l; 1842 u_int32_t oldsr; 1843 faultbuf env; 1844 void *oldh = curpcb->pcb_onfault; 1845 1846 while (len > 0) { 1847 p = PPC_USER_ADDR + ((u_int)udaddr & ~PPC_SEGMENT_MASK); 1848 l = (PPC_USER_ADDR + PPC_SEGMENT_LENGTH) - p; 1849 if (l > len) 1850 l = len; 1851 oldsr = pmap_setusr(curpcb->pcb_pm, (vaddr_t)udaddr); 1852 if (setfault(&env)) { 1853 pmap_popusr(oldsr); 1854 curpcb->pcb_onfault = oldh; 1855 return EFAULT; 1856 } 1857 bcopy(p, kaddr, l); 1858 pmap_popusr(oldsr); 1859 udaddr += l; 1860 kaddr += l; 1861 len -= l; 1862 } 1863 curpcb->pcb_onfault = oldh; 1864 return 0; 1865} 1866 1867int 1868copyout(const void *kaddr, void *udaddr, size_t len) 1869{ 1870 void *p; 1871 size_t l; 1872 u_int32_t oldsr; 1873 faultbuf env; 1874 void *oldh = curpcb->pcb_onfault; 1875 1876 while (len > 0) { 1877 p = PPC_USER_ADDR + ((u_int)udaddr & ~PPC_SEGMENT_MASK); 1878 l = (PPC_USER_ADDR + PPC_SEGMENT_LENGTH) - p; 1879 if (l > len) 1880 l = len; 1881 oldsr = pmap_setusr(curpcb->pcb_pm, (vaddr_t)udaddr); 1882 if (setfault(&env)) { 1883 pmap_popusr(oldsr); 1884 curpcb->pcb_onfault = oldh; 1885 return EFAULT; 1886 } 1887 1888 bcopy(kaddr, p, l); 1889 pmap_popusr(oldsr); 1890 udaddr += l; 1891 kaddr += l; 1892 len -= l; 1893 } 1894 curpcb->pcb_onfault = oldh; 1895 return 0; 1896} 1897 1898int 1899copyinstr(const void *udaddr, void *kaddr, size_t len, size_t *done) 1900{ 1901 const u_char *uaddr = udaddr; 1902 u_char *kp = kaddr; 1903 u_char *up; 1904 u_char c; 1905 void *p; 1906 size_t l; 1907 u_int32_t oldsr; 1908 int cnt = 0; 1909 faultbuf env; 1910 void *oldh = curpcb->pcb_onfault; 1911 1912 while (len > 0) { 1913 p = PPC_USER_ADDR + ((u_int)uaddr & ~PPC_SEGMENT_MASK); 1914 l = (PPC_USER_ADDR + PPC_SEGMENT_LENGTH) - p; 1915 up = p; 1916 if (l > len) 1917 l = len; 1918 len -= l; 1919 oldsr = pmap_setusr(curpcb->pcb_pm, (vaddr_t)uaddr); 1920 if (setfault(&env)) { 1921 if (done != NULL) 1922 *done = cnt; 1923 1924 curpcb->pcb_onfault = oldh; 1925 pmap_popusr(oldsr); 1926 return EFAULT; 1927 } 1928 while (l > 0) { 1929 c = *up; 1930 *kp = c; 1931 if (c == 0) { 1932 if (done != NULL) 1933 *done = cnt + 1; 1934 1935 curpcb->pcb_onfault = oldh; 1936 pmap_popusr(oldsr); 1937 return 0; 1938 } 1939 up++; 1940 kp++; 1941 l--; 1942 cnt++; 1943 uaddr++; 1944 } 1945 pmap_popusr(oldsr); 1946 } 1947 curpcb->pcb_onfault = oldh; 1948 if (done != NULL) 1949 *done = cnt; 1950 1951 return ENAMETOOLONG; 1952} 1953 1954int 1955copyoutstr(const void *kaddr, void *udaddr, size_t len, size_t *done) 1956{ 1957 u_char *uaddr = (void *)udaddr; 1958 const u_char *kp = kaddr; 1959 u_char *up; 1960 u_char c; 1961 void *p; 1962 size_t l; 1963 u_int32_t oldsr; 1964 int cnt = 0; 1965 faultbuf env; 1966 void *oldh = curpcb->pcb_onfault; 1967 1968 while (len > 0) { 1969 p = PPC_USER_ADDR + ((u_int)uaddr & ~PPC_SEGMENT_MASK); 1970 l = (PPC_USER_ADDR + PPC_SEGMENT_LENGTH) - p; 1971 up = p; 1972 if (l > len) 1973 l = len; 1974 len -= l; 1975 oldsr = pmap_setusr(curpcb->pcb_pm, (vaddr_t)uaddr); 1976 if (setfault(&env)) { 1977 if (done != NULL) 1978 *done = cnt; 1979 1980 curpcb->pcb_onfault = oldh; 1981 pmap_popusr(oldsr); 1982 return EFAULT; 1983 } 1984 while (l > 0) { 1985 c = *kp; 1986 *up = c; 1987 if (c == 0) { 1988 if (done != NULL) 1989 *done = cnt + 1; 1990 1991 curpcb->pcb_onfault = oldh; 1992 pmap_popusr(oldsr); 1993 return 0; 1994 } 1995 up++; 1996 kp++; 1997 l--; 1998 cnt++; 1999 uaddr++; 2000 } 2001 pmap_popusr(oldsr); 2002 } 2003 curpcb->pcb_onfault = oldh; 2004 if (done != NULL) 2005 *done = cnt; 2006 2007 return ENAMETOOLONG; 2008} 2009 2010/* 2011 * sync instruction cache for user virtual address. 2012 * The address WAS JUST MAPPED, so we have a VALID USERSPACE mapping 2013 */ 2014void 2015pmap_syncicache_user_virt(pmap_t pm, vaddr_t va) 2016{ 2017 vaddr_t start; 2018 int oldsr; 2019 2020 if (pm != pmap_kernel()) { 2021 start = ((u_int)PPC_USER_ADDR + ((u_int)va & 2022 ~PPC_SEGMENT_MASK)); 2023 /* will only ever be page size, will not cross segments */ 2024 2025 /* USER SEGMENT LOCK - MPXXX */ 2026 oldsr = pmap_setusr(pm, va); 2027 } else { 2028 start = va; /* flush mapped page */ 2029 } 2030 2031 syncicache((void *)start, PAGE_SIZE); 2032 2033 if (pm != pmap_kernel()) { 2034 pmap_popusr(oldsr); 2035 /* USER SEGMENT UNLOCK -MPXXX */ 2036 } 2037} 2038 2039void 2040pmap_page_ro64(pmap_t pm, vaddr_t va, vm_prot_t prot) 2041{ 2042 struct pte_64 *ptp64; 2043 struct pte_desc *pted; 2044 struct vm_page *pg; 2045 int sr, idx; 2046 2047 pted = pmap_vp_lookup(pm, va); 2048 if (pted == NULL || !PTED_VALID(pted)) 2049 return; 2050 2051 pg = PHYS_TO_VM_PAGE(pted->p.pted_pte64.pte_lo & PTE_RPGN_64); 2052 if (pg->pg_flags & PG_PMAP_EXE) { 2053 if ((prot & (VM_PROT_WRITE|VM_PROT_EXECUTE)) == VM_PROT_WRITE) { 2054 atomic_clearbits_int(&pg->pg_flags, PG_PMAP_EXE); 2055 } else { 2056 pmap_syncicache_user_virt(pm, va); 2057 } 2058 } 2059 2060 pted->p.pted_pte64.pte_lo &= ~PTE_PP_64; 2061 pted->p.pted_pte64.pte_lo |= PTE_RO_64; 2062 2063 if ((prot & VM_PROT_EXECUTE) == 0) 2064 pted->p.pted_pte64.pte_lo |= PTE_N_64; 2065 2066 sr = ptesr(pm->pm_sr, va); 2067 idx = pteidx(sr, va); 2068 2069 /* determine which pteg mapping is present in */ 2070 ptp64 = pmap_ptable64 + 2071 (idx ^ (PTED_HID(pted) ? pmap_ptab_mask : 0)) * 8; 2072 ptp64 += PTED_PTEGIDX(pted); /* increment by index into pteg */ 2073 2074 /* 2075 * We now have the pointer to where it will be, if it is 2076 * currently mapped. If the mapping was thrown away in 2077 * exchange for another page mapping, then this page is 2078 * not currently in the HASH. 2079 */ 2080 if ((pted->p.pted_pte64.pte_hi | (PTED_HID(pted) ? PTE_HID_64 : 0)) 2081 == ptp64->pte_hi) { 2082 ptp64->pte_hi &= ~PTE_VALID_64; 2083 __asm__ volatile ("sync"); 2084 tlbie(va); 2085 tlbsync(); 2086 if (PTED_MANAGED(pted)) { /* XXX */ 2087 pmap_attr_save(ptp64->pte_lo & PTE_RPGN_64, 2088 ptp64->pte_lo & (PTE_REF_64|PTE_CHG_64)); 2089 } 2090 ptp64->pte_lo &= ~PTE_CHG_64; 2091 ptp64->pte_lo &= ~PTE_PP_64; 2092 ptp64->pte_lo |= PTE_RO_64; 2093 __asm__ volatile ("sync"); 2094 ptp64->pte_hi |= PTE_VALID_64; 2095 } 2096} 2097 2098void 2099pmap_page_ro32(pmap_t pm, vaddr_t va, vm_prot_t prot) 2100{ 2101 struct pte_32 *ptp32; 2102 struct pte_desc *pted; 2103 struct vm_page *pg = NULL; 2104 int sr, idx; 2105 2106 pted = pmap_vp_lookup(pm, va); 2107 if (pted == NULL || !PTED_VALID(pted)) 2108 return; 2109 2110 pg = PHYS_TO_VM_PAGE(pted->p.pted_pte32.pte_lo & PTE_RPGN_32); 2111 if (pg->pg_flags & PG_PMAP_EXE) { 2112 if ((prot & (VM_PROT_WRITE|VM_PROT_EXECUTE)) == VM_PROT_WRITE) { 2113 atomic_clearbits_int(&pg->pg_flags, PG_PMAP_EXE); 2114 } else { 2115 pmap_syncicache_user_virt(pm, va); 2116 } 2117 } 2118 2119 pted->p.pted_pte32.pte_lo &= ~PTE_PP_32; 2120 pted->p.pted_pte32.pte_lo |= PTE_RO_32; 2121 2122 sr = ptesr(pm->pm_sr, va); 2123 idx = pteidx(sr, va); 2124 2125 /* determine which pteg mapping is present in */ 2126 ptp32 = pmap_ptable32 + 2127 (idx ^ (PTED_HID(pted) ? pmap_ptab_mask : 0)) * 8; 2128 ptp32 += PTED_PTEGIDX(pted); /* increment by index into pteg */ 2129 2130 /* 2131 * We now have the pointer to where it will be, if it is 2132 * currently mapped. If the mapping was thrown away in 2133 * exchange for another page mapping, then this page is 2134 * not currently in the HASH. 2135 */ 2136 if ((pted->p.pted_pte32.pte_hi | (PTED_HID(pted) ? PTE_HID_32 : 0)) 2137 == ptp32->pte_hi) { 2138 ptp32->pte_hi &= ~PTE_VALID_32; 2139 __asm__ volatile ("sync"); 2140 tlbie(va); 2141 tlbsync(); 2142 if (PTED_MANAGED(pted)) { /* XXX */ 2143 pmap_attr_save(ptp32->pte_lo & PTE_RPGN_32, 2144 ptp32->pte_lo & (PTE_REF_32|PTE_CHG_32)); 2145 } 2146 ptp32->pte_lo &= ~PTE_CHG_32; 2147 ptp32->pte_lo &= ~PTE_PP_32; 2148 ptp32->pte_lo |= PTE_RO_32; 2149 __asm__ volatile ("sync"); 2150 ptp32->pte_hi |= PTE_VALID_32; 2151 } 2152} 2153 2154/* 2155 * Lower the protection on the specified physical page. 2156 * 2157 * There are only two cases, either the protection is going to 0, 2158 * or it is going to read-only. 2159 */ 2160void 2161pmap_page_protect(struct vm_page *pg, vm_prot_t prot) 2162{ 2163 int s; 2164 struct pte_desc *pted; 2165 2166 /* need to lock for this pv */ 2167 s = splvm(); 2168 2169 if (prot == VM_PROT_NONE) { 2170 while (!LIST_EMPTY(&(pg->mdpage.pv_list))) { 2171 pted = LIST_FIRST(&(pg->mdpage.pv_list)); 2172 pmap_remove_pg(pted->pted_pmap, pted->pted_va); 2173 } 2174 /* page is being reclaimed, sync icache next use */ 2175 atomic_clearbits_int(&pg->pg_flags, PG_PMAP_EXE); 2176 splx(s); 2177 return; 2178 } 2179 2180 LIST_FOREACH(pted, &(pg->mdpage.pv_list), pted_pv_list) { 2181 if (ppc_proc_is_64b) 2182 pmap_page_ro64(pted->pted_pmap, pted->pted_va, prot); 2183 else 2184 pmap_page_ro32(pted->pted_pmap, pted->pted_va, prot); 2185 } 2186 splx(s); 2187} 2188 2189void 2190pmap_protect(pmap_t pm, vaddr_t sva, vaddr_t eva, vm_prot_t prot) 2191{ 2192 int s; 2193 if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) { 2194 s = splvm(); 2195 if (ppc_proc_is_64b) { 2196 while (sva < eva) { 2197 pmap_page_ro64(pm, sva, prot); 2198 sva += PAGE_SIZE; 2199 } 2200 } else { 2201 while (sva < eva) { 2202 pmap_page_ro32(pm, sva, prot); 2203 sva += PAGE_SIZE; 2204 } 2205 } 2206 splx(s); 2207 return; 2208 } 2209 pmap_remove(pm, sva, eva); 2210} 2211 2212/* 2213 * Restrict given range to physical memory 2214 */ 2215void 2216pmap_real_memory(paddr_t *start, vsize_t *size) 2217{ 2218 struct mem_region *mp; 2219 2220 for (mp = pmap_mem; mp->size; mp++) { 2221 if (((*start + *size) > mp->start) 2222 && (*start < (mp->start + mp->size))) 2223 { 2224 if (*start < mp->start) { 2225 *size -= mp->start - *start; 2226 *start = mp->start; 2227 } 2228 if ((*start + *size) > (mp->start + mp->size)) 2229 *size = mp->start + mp->size - *start; 2230 return; 2231 } 2232 } 2233 *size = 0; 2234} 2235 2236void 2237pmap_init() 2238{ 2239 pool_init(&pmap_pmap_pool, sizeof(struct pmap), 0, 0, 0, "pmap", NULL); 2240 pool_setlowat(&pmap_pmap_pool, 2); 2241 pool_init(&pmap_vp_pool, sizeof(struct pmapvp), 0, 0, 0, "vp", NULL); 2242 pool_setlowat(&pmap_vp_pool, 10); 2243 pool_init(&pmap_pted_pool, sizeof(struct pte_desc), 0, 0, 0, "pted", 2244 NULL); 2245 pool_setlowat(&pmap_pted_pool, 20); 2246 2247 pmap_initialized = 1; 2248} 2249 2250void 2251pmap_proc_iflush(struct proc *p, vaddr_t addr, vsize_t len) 2252{ 2253 paddr_t pa; 2254 vsize_t clen; 2255 2256 while (len > 0) { 2257 /* add one to always round up to the next page */ 2258 clen = round_page(addr + 1) - addr; 2259 if (clen > len) 2260 clen = len; 2261 2262 if (pmap_extract(p->p_vmspace->vm_map.pmap, addr, &pa)) { 2263 syncicache((void *)pa, clen); 2264 } 2265 2266 len -= clen; 2267 addr += clen; 2268 } 2269} 2270 2271/* 2272 * There are two routines, pte_spill_r and pte_spill_v 2273 * the _r version only handles kernel faults which are not user 2274 * accesses. The _v version handles all user faults and kernel copyin/copyout 2275 * "user" accesses. 2276 */ 2277int 2278pte_spill_r(u_int32_t va, u_int32_t msr, u_int32_t dsisr, int exec_fault) 2279{ 2280 pmap_t pm; 2281 struct pte_desc *pted; 2282 struct pte_desc pted_store; 2283 2284 /* lookup is done physical to prevent faults */ 2285 2286 /* 2287 * This function only handles kernel faults, not supervisor copyins. 2288 */ 2289 if (msr & PSL_PR) 2290 return 0; 2291 2292 /* if copyin, throw to full excption handler */ 2293 if (VP_SR(va) == PPC_USER_SR) 2294 return 0; 2295 2296 pm = pmap_kernel(); 2297 2298 2299 if (va < physmaxaddr) { 2300 u_int32_t aligned_va; 2301 pted = &pted_store; 2302 /* 0 - physmaxaddr mapped 1-1 */ 2303 /* XXX - no WRX control */ 2304 2305 aligned_va = trunc_page(va); 2306 if (ppc_proc_is_64b) { 2307 pmap_fill_pte64(pm, aligned_va, aligned_va, 2308 pted, VM_PROT_READ | VM_PROT_WRITE | 2309 VM_PROT_EXECUTE, 0, PMAP_CACHE_WB); 2310 pte_insert64(pted); 2311 return 1; 2312 } else { 2313 pmap_fill_pte32(pm, aligned_va, aligned_va, 2314 &pted_store, VM_PROT_READ | VM_PROT_WRITE | 2315 VM_PROT_EXECUTE, 0, PMAP_CACHE_WB); 2316 pte_insert32(pted); 2317 return 1; 2318 } 2319 /* NOTREACHED */ 2320 } 2321 2322 pted = pmap_vp_lookup(pm, va); 2323 if (pted == NULL) { 2324 return 0; 2325 } 2326 2327 /* if the current mapping is RO and the access was a write 2328 * we return 0 2329 */ 2330 if (!PTED_VALID(pted)) { 2331 return 0; 2332 } 2333 2334 if (ppc_proc_is_64b) { 2335 /* check write fault and we have a readonly mapping */ 2336 if ((dsisr & (1 << (31-6))) && 2337 (pted->p.pted_pte64.pte_lo & 0x1)) 2338 return 0; 2339 if ((exec_fault != 0) 2340 && ((pted->pted_va & PTED_VA_EXEC_M) == 0)) { 2341 /* attempted to execute non-executable page */ 2342 return 0; 2343 } 2344 pte_insert64(pted); 2345 } else { 2346 /* check write fault and we have a readonly mapping */ 2347 if ((dsisr & (1 << (31-6))) && 2348 (pted->p.pted_pte32.pte_lo & 0x1)) 2349 return 0; 2350 if ((exec_fault != 0) 2351 && ((pted->pted_va & PTED_VA_EXEC_M) == 0)) { 2352 /* attempted to execute non-executable page */ 2353 return 0; 2354 } 2355 pte_insert32(pted); 2356 } 2357 2358 return 1; 2359} 2360 2361int 2362pte_spill_v(pmap_t pm, u_int32_t va, u_int32_t dsisr, int exec_fault) 2363{ 2364 struct pte_desc *pted; 2365 2366 pted = pmap_vp_lookup(pm, va); 2367 if (pted == NULL) { 2368 return 0; 2369 } 2370 2371 /* 2372 * if the current mapping is RO and the access was a write 2373 * we return 0 2374 */ 2375 if (!PTED_VALID(pted)) { 2376 return 0; 2377 } 2378 if (ppc_proc_is_64b) { 2379 /* check write fault and we have a readonly mapping */ 2380 if ((dsisr & (1 << (31-6))) && 2381 (pted->p.pted_pte64.pte_lo & 0x1)) 2382 return 0; 2383 } else { 2384 /* check write fault and we have a readonly mapping */ 2385 if ((dsisr & (1 << (31-6))) && 2386 (pted->p.pted_pte32.pte_lo & 0x1)) 2387 return 0; 2388 } 2389 if ((exec_fault != 0) 2390 && ((pted->pted_va & PTED_VA_EXEC_M) == 0)) { 2391 /* attempted to execute non-executable page */ 2392 return 0; 2393 } 2394 if (ppc_proc_is_64b) 2395 pte_insert64(pted); 2396 else 2397 pte_insert32(pted); 2398 return 1; 2399} 2400 2401 2402/* 2403 * should pte_insert code avoid wired mappings? 2404 * is the stack safe? 2405 * is the pted safe? (physical) 2406 * -ugh 2407 */ 2408void 2409pte_insert64(struct pte_desc *pted) 2410{ 2411 int off; 2412 int secondary; 2413 struct pte_64 *ptp64; 2414 int sr, idx; 2415 int i, s; 2416 2417 2418 sr = ptesr(pted->pted_pmap->pm_sr, pted->pted_va); 2419 idx = pteidx(sr, pted->pted_va); 2420 2421 ptp64 = pmap_ptable64 + 2422 (idx ^ (PTED_HID(pted) ? pmap_ptab_mask : 0)) * 8; 2423 ptp64 += PTED_PTEGIDX(pted); /* increment by index into pteg */ 2424 if ((pted->p.pted_pte64.pte_hi | 2425 (PTED_HID(pted) ? PTE_HID_64 : 0)) == ptp64->pte_hi) 2426 pte_zap(ptp64,pted); 2427 2428 pted->pted_va &= ~(PTED_VA_HID_M|PTED_VA_PTEGIDX_M); 2429 2430 /* 2431 * instead of starting at the beginning of each pteg, 2432 * the code should pick a random location with in the primary 2433 * then search all of the entries, then if not yet found, 2434 * do the same for the secondary. 2435 * this would reduce the frontloading of the pteg. 2436 */ 2437 /* first just try fill of primary hash */ 2438 ptp64 = pmap_ptable64 + (idx) * 8; 2439 for (i = 0; i < 8; i++) { 2440 if (ptp64[i].pte_hi & PTE_VALID_64) 2441 continue; 2442 s = ppc_intr_disable(); 2443 if (pmap_hash_lock_try(i) == 0) { 2444 ppc_intr_enable(s); 2445 continue; 2446 } 2447 2448 /* not valid, just load */ 2449 pted->pted_va |= i; 2450 ptp64[i].pte_hi = 2451 pted->p.pted_pte64.pte_hi & ~PTE_VALID_64; 2452 ptp64[i].pte_lo = pted->p.pted_pte64.pte_lo; 2453 __asm__ volatile ("sync"); 2454 ptp64[i].pte_hi |= PTE_VALID_64; 2455 __asm volatile ("sync"); 2456 2457 pmap_hash_unlock(i); 2458 ppc_intr_enable(s); 2459 return; 2460 } 2461 /* try fill of secondary hash */ 2462 ptp64 = pmap_ptable64 + (idx ^ pmap_ptab_mask) * 8; 2463 for (i = 0; i < 8; i++) { 2464 if (ptp64[i].pte_hi & PTE_VALID_64) 2465 continue; 2466 s = ppc_intr_disable(); 2467 if (pmap_hash_lock_try(i) == 0) { 2468 ppc_intr_enable(s); 2469 continue; 2470 } 2471 2472 pted->pted_va |= (i | PTED_VA_HID_M); 2473 ptp64[i].pte_hi = 2474 (pted->p.pted_pte64.pte_hi | PTE_HID_64) & ~PTE_VALID_64; 2475 ptp64[i].pte_lo = pted->p.pted_pte64.pte_lo; 2476 __asm__ volatile ("sync"); 2477 ptp64[i].pte_hi |= PTE_VALID_64; 2478 __asm volatile ("sync"); 2479 2480 pmap_hash_unlock(i); 2481 ppc_intr_enable(s); 2482 return; 2483 } 2484 2485 /* need decent replacement algorithm */ 2486busy: 2487 __asm__ volatile ("mftb %0" : "=r"(off)); 2488 secondary = off & 8; 2489 2490 s = ppc_intr_disable(); 2491 if (pmap_hash_lock_try(off & 7) == 0) { 2492 ppc_intr_enable(s); 2493 goto busy; 2494 } 2495 2496 pted->pted_va |= off & (PTED_VA_PTEGIDX_M|PTED_VA_HID_M); 2497 2498 idx = (idx ^ (PTED_HID(pted) ? pmap_ptab_mask : 0)); 2499 2500 ptp64 = pmap_ptable64 + (idx * 8); 2501 ptp64 += PTED_PTEGIDX(pted); /* increment by index into pteg */ 2502 if (ptp64->pte_hi & PTE_VALID_64) { 2503 vaddr_t va; 2504 ptp64->pte_hi &= ~PTE_VALID_64; 2505 __asm volatile ("sync"); 2506 2507 /* Bits 9-19 */ 2508 idx = (idx ^ ((ptp64->pte_hi & PTE_HID_64) ? 2509 pmap_ptab_mask : 0)); 2510 va = (ptp64->pte_hi >> PTE_VSID_SHIFT_64) ^ idx; 2511 va <<= ADDR_PIDX_SHIFT; 2512 /* Bits 4-8 */ 2513 va |= (ptp64->pte_hi & PTE_API_64) << ADDR_API_SHIFT_32; 2514 /* Bits 0-3 */ 2515 va |= (ptp64->pte_hi >> PTE_VSID_SHIFT_64) 2516 << ADDR_SR_SHIFT; 2517 tlbie(va); 2518 2519 tlbsync(); 2520 pmap_attr_save(ptp64->pte_lo & PTE_RPGN_64, 2521 ptp64->pte_lo & (PTE_REF_64|PTE_CHG_64)); 2522 } 2523 2524 if (secondary) 2525 ptp64->pte_hi = 2526 (pted->p.pted_pte64.pte_hi | PTE_HID_64) & 2527 ~PTE_VALID_64; 2528 else 2529 ptp64->pte_hi = pted->p.pted_pte64.pte_hi & 2530 ~PTE_VALID_64; 2531 2532 ptp64->pte_lo = pted->p.pted_pte64.pte_lo; 2533 __asm__ volatile ("sync"); 2534 ptp64->pte_hi |= PTE_VALID_64; 2535 2536 pmap_hash_unlock(off & 7); 2537 ppc_intr_enable(s); 2538} 2539 2540void 2541pte_insert32(struct pte_desc *pted) 2542{ 2543 int off; 2544 int secondary; 2545 struct pte_32 *ptp32; 2546 int sr, idx; 2547 int i, s; 2548 2549 sr = ptesr(pted->pted_pmap->pm_sr, pted->pted_va); 2550 idx = pteidx(sr, pted->pted_va); 2551 2552 /* determine if ptp is already mapped */ 2553 ptp32 = pmap_ptable32 + 2554 (idx ^ (PTED_HID(pted) ? pmap_ptab_mask : 0)) * 8; 2555 ptp32 += PTED_PTEGIDX(pted); /* increment by index into pteg */ 2556 if ((pted->p.pted_pte32.pte_hi | 2557 (PTED_HID(pted) ? PTE_HID_32 : 0)) == ptp32->pte_hi) 2558 pte_zap(ptp32,pted); 2559 2560 pted->pted_va &= ~(PTED_VA_HID_M|PTED_VA_PTEGIDX_M); 2561 2562 /* 2563 * instead of starting at the beginning of each pteg, 2564 * the code should pick a random location with in the primary 2565 * then search all of the entries, then if not yet found, 2566 * do the same for the secondary. 2567 * this would reduce the frontloading of the pteg. 2568 */ 2569 2570 /* first just try fill of primary hash */ 2571 ptp32 = pmap_ptable32 + (idx) * 8; 2572 for (i = 0; i < 8; i++) { 2573 if (ptp32[i].pte_hi & PTE_VALID_32) 2574 continue; 2575 s = ppc_intr_disable(); 2576 if (pmap_hash_lock_try(i) == 0) { 2577 ppc_intr_enable(s); 2578 continue; 2579 } 2580 2581 /* not valid, just load */ 2582 pted->pted_va |= i; 2583 ptp32[i].pte_hi = pted->p.pted_pte32.pte_hi & ~PTE_VALID_32; 2584 ptp32[i].pte_lo = pted->p.pted_pte32.pte_lo; 2585 __asm__ volatile ("sync"); 2586 ptp32[i].pte_hi |= PTE_VALID_32; 2587 __asm volatile ("sync"); 2588 2589 pmap_hash_unlock(i); 2590 ppc_intr_enable(s); 2591 return; 2592 } 2593 /* try fill of secondary hash */ 2594 ptp32 = pmap_ptable32 + (idx ^ pmap_ptab_mask) * 8; 2595 for (i = 0; i < 8; i++) { 2596 if (ptp32[i].pte_hi & PTE_VALID_32) 2597 continue; 2598 s = ppc_intr_disable(); 2599 if (pmap_hash_lock_try(i) == 0) { 2600 ppc_intr_enable(s); 2601 continue; 2602 } 2603 2604 pted->pted_va |= (i | PTED_VA_HID_M); 2605 ptp32[i].pte_hi = 2606 (pted->p.pted_pte32.pte_hi | PTE_HID_32) & ~PTE_VALID_32; 2607 ptp32[i].pte_lo = pted->p.pted_pte32.pte_lo; 2608 __asm__ volatile ("sync"); 2609 ptp32[i].pte_hi |= PTE_VALID_32; 2610 __asm volatile ("sync"); 2611 2612 pmap_hash_unlock(i); 2613 ppc_intr_enable(s); 2614 return; 2615 } 2616 2617 /* need decent replacement algorithm */ 2618busy: 2619 __asm__ volatile ("mftb %0" : "=r"(off)); 2620 secondary = off & 8; 2621 s = ppc_intr_disable(); 2622 if (pmap_hash_lock_try(off & 7) == 0) { 2623 ppc_intr_enable(s); 2624 goto busy; 2625 } 2626 2627 pted->pted_va |= off & (PTED_VA_PTEGIDX_M|PTED_VA_HID_M); 2628 2629 idx = (idx ^ (PTED_HID(pted) ? pmap_ptab_mask : 0)); 2630 2631 ptp32 = pmap_ptable32 + (idx * 8); 2632 ptp32 += PTED_PTEGIDX(pted); /* increment by index into pteg */ 2633 if (ptp32->pte_hi & PTE_VALID_32) { 2634 vaddr_t va; 2635 ptp32->pte_hi &= ~PTE_VALID_32; 2636 __asm volatile ("sync"); 2637 2638 va = ((ptp32->pte_hi & PTE_API_32) << ADDR_API_SHIFT_32) | 2639 ((((ptp32->pte_hi >> PTE_VSID_SHIFT_32) & SR_VSID) 2640 ^(idx ^ ((ptp32->pte_hi & PTE_HID_32) ? 0x3ff : 0))) 2641 & 0x3ff) << PAGE_SHIFT; 2642 tlbie(va); 2643 2644 tlbsync(); 2645 pmap_attr_save(ptp32->pte_lo & PTE_RPGN_32, 2646 ptp32->pte_lo & (PTE_REF_32|PTE_CHG_32)); 2647 } 2648 if (secondary) 2649 ptp32->pte_hi = 2650 (pted->p.pted_pte32.pte_hi | PTE_HID_32) & ~PTE_VALID_32; 2651 else 2652 ptp32->pte_hi = pted->p.pted_pte32.pte_hi & ~PTE_VALID_32; 2653 ptp32->pte_lo = pted->p.pted_pte32.pte_lo; 2654 __asm__ volatile ("sync"); 2655 ptp32->pte_hi |= PTE_VALID_32; 2656 2657 pmap_hash_unlock(off & 7); 2658 ppc_intr_enable(s); 2659} 2660 2661#ifdef DEBUG_PMAP 2662void 2663print_pteg(pmap_t pm, vaddr_t va) 2664{ 2665 int sr, idx; 2666 struct pte *ptp; 2667 2668 sr = ptesr(pm->pm_sr, va); 2669 idx = pteidx(sr, va); 2670 2671 ptp = pmap_ptable + idx * 8; 2672 db_printf("va %x, sr %x, idx %x\n", va, sr, idx); 2673 2674 db_printf("%08x %08x %08x %08x %08x %08x %08x %08x\n", 2675 ptp[0].pte_hi, ptp[1].pte_hi, ptp[2].pte_hi, ptp[3].pte_hi, 2676 ptp[4].pte_hi, ptp[5].pte_hi, ptp[6].pte_hi, ptp[7].pte_hi); 2677 db_printf("%08x %08x %08x %08x %08x %08x %08x %08x\n", 2678 ptp[0].pte_lo, ptp[1].pte_lo, ptp[2].pte_lo, ptp[3].pte_lo, 2679 ptp[4].pte_lo, ptp[5].pte_lo, ptp[6].pte_lo, ptp[7].pte_lo); 2680 ptp = pmap_ptable + (idx ^ pmap_ptab_mask) * 8; 2681 db_printf("%08x %08x %08x %08x %08x %08x %08x %08x\n", 2682 ptp[0].pte_hi, ptp[1].pte_hi, ptp[2].pte_hi, ptp[3].pte_hi, 2683 ptp[4].pte_hi, ptp[5].pte_hi, ptp[6].pte_hi, ptp[7].pte_hi); 2684 db_printf("%08x %08x %08x %08x %08x %08x %08x %08x\n", 2685 ptp[0].pte_lo, ptp[1].pte_lo, ptp[2].pte_lo, ptp[3].pte_lo, 2686 ptp[4].pte_lo, ptp[5].pte_lo, ptp[6].pte_lo, ptp[7].pte_lo); 2687} 2688 2689 2690/* debugger assist function */ 2691int pmap_prtrans(u_int pid, vaddr_t va); 2692 2693void 2694pmap_print_pted(struct pte_desc *pted, int(*print)(const char *, ...)) 2695{ 2696 vaddr_t va; 2697 va = pted->pted_va & ~PAGE_MASK; 2698 print("\n pted %x", pted); 2699 if (PTED_VALID(pted)) { 2700 print(" va %x:", pted->pted_va & ~PAGE_MASK); 2701 print(" HID %d", PTED_HID(pted) ? 1: 0); 2702 print(" PTEGIDX %x", PTED_PTEGIDX(pted)); 2703 print(" MANAGED %d", PTED_MANAGED(pted) ? 1: 0); 2704 print(" WIRED %d\n", PTED_WIRED(pted) ? 1: 0); 2705 if (ppc_proc_is_64b) { 2706 print("ptehi %x ptelo %x ptp %x Aptp %x\n", 2707 pted->p.pted_pte64.pte_hi, 2708 pted->p.pted_pte64.pte_lo, 2709 pmap_ptable + 2710 8*pteidx(ptesr(pted->pted_pmap->pm_sr, va), va), 2711 pmap_ptable + 2712 8*(pteidx(ptesr(pted->pted_pmap->pm_sr, va), va) 2713 ^ pmap_ptab_mask) 2714 ); 2715 } else { 2716 print("ptehi %x ptelo %x ptp %x Aptp %x\n", 2717 pted->p.pted_pte32.pte_hi, 2718 pted->p.pted_pte32.pte_lo, 2719 pmap_ptable + 2720 8*pteidx(ptesr(pted->pted_pmap->pm_sr, va), va), 2721 pmap_ptable + 2722 8*(pteidx(ptesr(pted->pted_pmap->pm_sr, va), va) 2723 ^ pmap_ptab_mask) 2724 ); 2725 } 2726 } 2727} 2728 2729int pmap_user_read(int size, vaddr_t va); 2730int 2731pmap_user_read(int size, vaddr_t va) 2732{ 2733 unsigned char read1; 2734 unsigned short read2; 2735 unsigned int read4; 2736 int err; 2737 2738 if (size == 1) { 2739 err = copyin((void *)va, &read1, 1); 2740 if (err == 0) { 2741 db_printf("byte read %x\n", read1); 2742 } 2743 } else if (size == 2) { 2744 err = copyin((void *)va, &read2, 2); 2745 if (err == 0) { 2746 db_printf("short read %x\n", read2); 2747 } 2748 } else if (size == 4) { 2749 err = copyin((void *)va, &read4, 4); 2750 if (err == 0) { 2751 db_printf("int read %x\n", read4); 2752 } 2753 } else { 2754 return 1; 2755 } 2756 2757 2758 return 0; 2759} 2760 2761int pmap_dump_pmap(u_int pid); 2762int 2763pmap_dump_pmap(u_int pid) 2764{ 2765 pmap_t pm; 2766 struct proc *p; 2767 if (pid == 0) { 2768 pm = pmap_kernel(); 2769 } else { 2770 p = pfind(pid); 2771 2772 if (p == NULL) { 2773 db_printf("invalid pid %d", pid); 2774 return 1; 2775 } 2776 pm = p->p_vmspace->vm_map.pmap; 2777 } 2778 printf("pmap %x:\n", pm); 2779 printf("segid %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x", 2780 pm->pm_sr[0], pm->pm_sr[1], pm->pm_sr[2], pm->pm_sr[3], 2781 pm->pm_sr[4], pm->pm_sr[5], pm->pm_sr[6], pm->pm_sr[7], 2782 pm->pm_sr[8], pm->pm_sr[9], pm->pm_sr[10], pm->pm_sr[11], 2783 pm->pm_sr[12], pm->pm_sr[13], pm->pm_sr[14], pm->pm_sr[15]); 2784 2785 return 0; 2786} 2787 2788int 2789pmap_prtrans(u_int pid, vaddr_t va) 2790{ 2791 struct proc *p; 2792 pmap_t pm; 2793 struct pmapvp *vp1; 2794 struct pmapvp *vp2; 2795 struct pte_desc *pted; 2796 2797 if (pid == 0) { 2798 pm = pmap_kernel(); 2799 } else { 2800 p = pfind(pid); 2801 2802 if (p == NULL) { 2803 db_printf("invalid pid %d", pid); 2804 return 1; 2805 } 2806 pm = p->p_vmspace->vm_map.pmap; 2807 } 2808 2809 db_printf(" pid %d, va 0x%x pmap %x\n", pid, va, pm); 2810 vp1 = pm->pm_vp[VP_SR(va)]; 2811 db_printf("sr %x id %x vp1 %x", VP_SR(va), pm->pm_sr[VP_SR(va)], 2812 vp1); 2813 2814 if (vp1) { 2815 vp2 = vp1->vp[VP_IDX1(va)]; 2816 db_printf(" vp2 %x", vp2); 2817 2818 if (vp2) { 2819 pted = vp2->vp[VP_IDX2(va)]; 2820 pmap_print_pted(pted, db_printf); 2821 2822 } 2823 } 2824 print_pteg(pm, va); 2825 2826 return 0; 2827} 2828int pmap_show_mappings(paddr_t pa); 2829 2830int 2831pmap_show_mappings(paddr_t pa) 2832{ 2833 struct pte_desc *pted; 2834 struct vm_page *pg; 2835 2836 pg = PHYS_TO_VM_PAGE(pa); 2837 if (pg == NULL) { 2838 db_printf("pa %x: unmanaged\n"); 2839 } else { 2840 LIST_FOREACH(pted, &(pg->mdpage.pv_list), pted_pv_list) { 2841 pmap_print_pted(pted, db_printf); 2842 } 2843 } 2844 return 0; 2845} 2846#endif 2847