pmap.c (191300) | pmap.c (191735) |
---|---|
1/* 2 * Copyright (c) 1991 Regents of the University of California. 3 * All rights reserved. 4 * Copyright (c) 1994 John S. Dyson 5 * All rights reserved. 6 * Copyright (c) 1994 David Greenman 7 * All rights reserved. 8 * --- 52 unchanged lines hidden (view full) --- 61 * this module may delay invalidate or reduced protection 62 * operations until such time as they are actually 63 * necessary. This module is given full information as 64 * to which processors are currently using which maps, 65 * and to when physical maps must be made correct. 66 */ 67 68#include <sys/cdefs.h> | 1/* 2 * Copyright (c) 1991 Regents of the University of California. 3 * All rights reserved. 4 * Copyright (c) 1994 John S. Dyson 5 * All rights reserved. 6 * Copyright (c) 1994 David Greenman 7 * All rights reserved. 8 * --- 52 unchanged lines hidden (view full) --- 61 * this module may delay invalidate or reduced protection 62 * operations until such time as they are actually 63 * necessary. This module is given full information as 64 * to which processors are currently using which maps, 65 * and to when physical maps must be made correct. 66 */ 67 68#include <sys/cdefs.h> |
69__FBSDID("$FreeBSD: head/sys/mips/mips/pmap.c 191300 2009-04-20 03:44:54Z alc $"); | 69__FBSDID("$FreeBSD: head/sys/mips/mips/pmap.c 191735 2009-05-02 06:12:38Z alc $"); |
70 71#include "opt_ddb.h" 72#include "opt_msgbuf.h" 73#include <sys/param.h> 74#include <sys/systm.h> 75#include <sys/proc.h> 76#include <sys/msgbuf.h> 77#include <sys/vmmeter.h> --- 52 unchanged lines hidden (view full) --- 130#define pmap_pte_set_prot(pte, v) ((*(int *)pte &= ~PG_PROT), (*(int *)pte |= (v))) 131 132#define MIPS_SEGSIZE (1L << SEGSHIFT) 133#define mips_segtrunc(va) ((va) & ~(MIPS_SEGSIZE-1)) 134#define pmap_TLB_invalidate_all() MIPS_TBIAP() 135#define pmap_va_asid(pmap, va) ((va) | ((pmap)->pm_asid[PCPU_GET(cpuid)].asid << VMTLB_PID_SHIFT)) 136#define is_kernel_pmap(x) ((x) == kernel_pmap) 137 | 70 71#include "opt_ddb.h" 72#include "opt_msgbuf.h" 73#include <sys/param.h> 74#include <sys/systm.h> 75#include <sys/proc.h> 76#include <sys/msgbuf.h> 77#include <sys/vmmeter.h> --- 52 unchanged lines hidden (view full) --- 130#define pmap_pte_set_prot(pte, v) ((*(int *)pte &= ~PG_PROT), (*(int *)pte |= (v))) 131 132#define MIPS_SEGSIZE (1L << SEGSHIFT) 133#define mips_segtrunc(va) ((va) & ~(MIPS_SEGSIZE-1)) 134#define pmap_TLB_invalidate_all() MIPS_TBIAP() 135#define pmap_va_asid(pmap, va) ((va) | ((pmap)->pm_asid[PCPU_GET(cpuid)].asid << VMTLB_PID_SHIFT)) 136#define is_kernel_pmap(x) ((x) == kernel_pmap) 137 |
138static struct pmap kernel_pmap_store; 139pmap_t kernel_pmap; | 138struct pmap kernel_pmap_store; |
140pd_entry_t *kernel_segmap; 141 | 139pd_entry_t *kernel_segmap; 140 |
142vm_offset_t avail_start; /* PA of first available physical page */ 143vm_offset_t avail_end; /* PA of last available physical page */ | |
144vm_offset_t virtual_avail; /* VA of first avail page (after kernel bss) */ 145vm_offset_t virtual_end; /* VA of last avail page (end of kernel AS) */ 146 147static int nkpt; 148unsigned pmap_max_asid; /* max ASID supported by the system */ 149 150 151#define PMAP_ASID_RESERVED 0 --- 4 unchanged lines hidden (view full) --- 156static void pmap_asid_alloc(pmap_t pmap); 157 158/* 159 * Data for the pv entry allocation mechanism 160 */ 161static uma_zone_t pvzone; 162static struct vm_object pvzone_obj; 163static int pv_entry_count = 0, pv_entry_max = 0, pv_entry_high_water = 0; | 141vm_offset_t virtual_avail; /* VA of first avail page (after kernel bss) */ 142vm_offset_t virtual_end; /* VA of last avail page (end of kernel AS) */ 143 144static int nkpt; 145unsigned pmap_max_asid; /* max ASID supported by the system */ 146 147 148#define PMAP_ASID_RESERVED 0 --- 4 unchanged lines hidden (view full) --- 153static void pmap_asid_alloc(pmap_t pmap); 154 155/* 156 * Data for the pv entry allocation mechanism 157 */ 158static uma_zone_t pvzone; 159static struct vm_object pvzone_obj; 160static int pv_entry_count = 0, pv_entry_max = 0, pv_entry_high_water = 0; |
164int pmap_pagedaemon_waken = 0; | |
165 166struct fpage fpages_shared[FPAGES_SHARED]; 167 168struct sysmaps sysmaps_pcpu[MAXCPU]; 169 170static PMAP_INLINE void free_pv_entry(pv_entry_t pv); 171static pv_entry_t get_pv_entry(pmap_t locked_pmap); 172static __inline void pmap_changebit(vm_page_t m, int bit, boolean_t setem); --- 234 unchanged lines hidden (view full) --- 407 * level page table. 408 */ 409 printf("init kernel_segmap va >> = %d nkpt:%d\n", 410 (virtual_avail >> SEGSHIFT), 411 nkpt); 412 for (i = 0, j = (virtual_avail >> SEGSHIFT); i < nkpt; i++, j++) 413 kernel_segmap[j] = (pd_entry_t)(pgtab + (i * NPTEPG)); 414 | 161 162struct fpage fpages_shared[FPAGES_SHARED]; 163 164struct sysmaps sysmaps_pcpu[MAXCPU]; 165 166static PMAP_INLINE void free_pv_entry(pv_entry_t pv); 167static pv_entry_t get_pv_entry(pmap_t locked_pmap); 168static __inline void pmap_changebit(vm_page_t m, int bit, boolean_t setem); --- 234 unchanged lines hidden (view full) --- 403 * level page table. 404 */ 405 printf("init kernel_segmap va >> = %d nkpt:%d\n", 406 (virtual_avail >> SEGSHIFT), 407 nkpt); 408 for (i = 0, j = (virtual_avail >> SEGSHIFT); i < nkpt; i++, j++) 409 kernel_segmap[j] = (pd_entry_t)(pgtab + (i * NPTEPG)); 410 |
415 avail_start = phys_avail[0]; | |
416 for (i = 0; phys_avail[i + 2]; i += 2) 417 continue; | 411 for (i = 0; phys_avail[i + 2]; i += 2) 412 continue; |
418 avail_end = phys_avail[i + 1]; | 413 printf("avail_start:0x%x avail_end:0x%x\n", 414 phys_avail[0], phys_avail[i + 1]); |
419 420 /* 421 * The kernel's pmap is statically allocated so we don't have to use 422 * pmap_create, which is unlikely to work correctly at this part of 423 * the boot sequence (XXX and which no longer exists). 424 */ | 415 416 /* 417 * The kernel's pmap is statically allocated so we don't have to use 418 * pmap_create, which is unlikely to work correctly at this part of 419 * the boot sequence (XXX and which no longer exists). 420 */ |
425 kernel_pmap = &kernel_pmap_store; 426 | |
427 PMAP_LOCK_INIT(kernel_pmap); 428 kernel_pmap->pm_segtab = kernel_segmap; 429 kernel_pmap->pm_active = ~0; 430 TAILQ_INIT(&kernel_pmap->pm_pvlist); | 421 PMAP_LOCK_INIT(kernel_pmap); 422 kernel_pmap->pm_segtab = kernel_segmap; 423 kernel_pmap->pm_active = ~0; 424 TAILQ_INIT(&kernel_pmap->pm_pvlist); |
431 printf("avail_start:0x%x avail_end:0x%x\n", 432 avail_start, avail_end); 433 | |
434 kernel_pmap->pm_asid[PCPU_GET(cpuid)].asid = PMAP_ASID_RESERVED; 435 kernel_pmap->pm_asid[PCPU_GET(cpuid)].gen = 0; 436 pmap_max_asid = VMNUM_PIDS; 437 MachSetPID(0); 438} 439 440/* 441 * Initialize a vm_page's machine-dependent fields. --- 564 unchanged lines hidden (view full) --- 1006 1007#ifdef VM_ALLOC_WIRED_TLB_PG_POOL 1008 if (need_wired_tlb_page_pool) 1009 req |= VM_ALLOC_WIRED_TLB_PG_POOL; 1010#endif 1011 /* 1012 * allocate the page directory page 1013 */ | 425 kernel_pmap->pm_asid[PCPU_GET(cpuid)].asid = PMAP_ASID_RESERVED; 426 kernel_pmap->pm_asid[PCPU_GET(cpuid)].gen = 0; 427 pmap_max_asid = VMNUM_PIDS; 428 MachSetPID(0); 429} 430 431/* 432 * Initialize a vm_page's machine-dependent fields. --- 564 unchanged lines hidden (view full) --- 997 998#ifdef VM_ALLOC_WIRED_TLB_PG_POOL 999 if (need_wired_tlb_page_pool) 1000 req |= VM_ALLOC_WIRED_TLB_PG_POOL; 1001#endif 1002 /* 1003 * allocate the page directory page 1004 */ |
1014 ptdpg = vm_page_alloc(NULL, NUSERPGTBLS, req); | 1005 while ((ptdpg = vm_page_alloc(NULL, NUSERPGTBLS, req)) == NULL) 1006 VM_WAIT; |
1015 | 1007 |
1016#if 0 1017 /* I think we can just delete these, now that PG_BUSY is gone */ 1018 vm_page_lock_queues(); 1019 vm_page_flag_clear(ptdpg, PTE_BUSY); /* not usually mapped */ 1020#endif | |
1021 ptdpg->valid = VM_PAGE_BITS_ALL; 1022 | 1008 ptdpg->valid = VM_PAGE_BITS_ALL; 1009 |
1023#if 0 1024 vm_page_unlock_queues(); 1025#endif 1026 | |
1027 pmap->pm_segtab = (pd_entry_t *) 1028 MIPS_PHYS_TO_CACHED(VM_PAGE_TO_PHYS(ptdpg)); 1029 if ((ptdpg->flags & PG_ZERO) == 0) 1030 bzero(pmap->pm_segtab, PAGE_SIZE); 1031 1032 pmap->pm_active = 0; 1033 pmap->pm_ptphint = NULL; 1034 for (i = 0; i < MAXCPU; i++) { --- 153 unchanged lines hidden (view full) --- 1188{ 1189 vm_page_t ptdpg; 1190 1191 KASSERT(pmap->pm_stats.resident_count == 0, 1192 ("pmap_release: pmap resident count %ld != 0", 1193 pmap->pm_stats.resident_count)); 1194 1195 ptdpg = PHYS_TO_VM_PAGE(MIPS_CACHED_TO_PHYS(pmap->pm_segtab)); | 1010 pmap->pm_segtab = (pd_entry_t *) 1011 MIPS_PHYS_TO_CACHED(VM_PAGE_TO_PHYS(ptdpg)); 1012 if ((ptdpg->flags & PG_ZERO) == 0) 1013 bzero(pmap->pm_segtab, PAGE_SIZE); 1014 1015 pmap->pm_active = 0; 1016 pmap->pm_ptphint = NULL; 1017 for (i = 0; i < MAXCPU; i++) { --- 153 unchanged lines hidden (view full) --- 1171{ 1172 vm_page_t ptdpg; 1173 1174 KASSERT(pmap->pm_stats.resident_count == 0, 1175 ("pmap_release: pmap resident count %ld != 0", 1176 pmap->pm_stats.resident_count)); 1177 1178 ptdpg = PHYS_TO_VM_PAGE(MIPS_CACHED_TO_PHYS(pmap->pm_segtab)); |
1196 1197 vm_page_lock_queues(); | |
1198 ptdpg->wire_count--; 1199 atomic_subtract_int(&cnt.v_wire_count, 1); 1200 vm_page_free_zero(ptdpg); | 1179 ptdpg->wire_count--; 1180 atomic_subtract_int(&cnt.v_wire_count, 1); 1181 vm_page_free_zero(ptdpg); |
1201 vm_page_unlock_queues(); | |
1202} 1203 1204/* 1205 * grow the number of kernel page table entries, if needed 1206 */ 1207void 1208pmap_growkernel(vm_offset_t addr) 1209{ --- 232 unchanged lines hidden (view full) --- 1442/* 1443 * Create a pv entry for page at pa for 1444 * (pmap, va). 1445 */ 1446static void 1447pmap_insert_entry(pmap_t pmap, vm_offset_t va, vm_page_t mpte, vm_page_t m, 1448 boolean_t wired) 1449{ | 1182} 1183 1184/* 1185 * grow the number of kernel page table entries, if needed 1186 */ 1187void 1188pmap_growkernel(vm_offset_t addr) 1189{ --- 232 unchanged lines hidden (view full) --- 1422/* 1423 * Create a pv entry for page at pa for 1424 * (pmap, va). 1425 */ 1426static void 1427pmap_insert_entry(pmap_t pmap, vm_offset_t va, vm_page_t mpte, vm_page_t m, 1428 boolean_t wired) 1429{ |
1450 | |
1451 pv_entry_t pv; 1452 1453 pv = get_pv_entry(pmap); 1454 pv->pv_va = va; 1455 pv->pv_pmap = pmap; 1456 pv->pv_ptem = mpte; 1457 pv->pv_wired = wired; 1458 1459 PMAP_LOCK_ASSERT(pmap, MA_OWNED); 1460 mtx_assert(&vm_page_queue_mtx, MA_OWNED); 1461 TAILQ_INSERT_TAIL(&pmap->pm_pvlist, pv, pv_plist); 1462 TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_list); 1463 m->md.pv_list_count++; | 1430 pv_entry_t pv; 1431 1432 pv = get_pv_entry(pmap); 1433 pv->pv_va = va; 1434 pv->pv_pmap = pmap; 1435 pv->pv_ptem = mpte; 1436 pv->pv_wired = wired; 1437 1438 PMAP_LOCK_ASSERT(pmap, MA_OWNED); 1439 mtx_assert(&vm_page_queue_mtx, MA_OWNED); 1440 TAILQ_INSERT_TAIL(&pmap->pm_pvlist, pv, pv_plist); 1441 TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_list); 1442 m->md.pv_list_count++; |
1464 | |
1465} 1466 1467/* 1468 * Conditionally create a pv entry. 1469 */ 1470static boolean_t 1471pmap_try_insert_pv_entry(pmap_t pmap, vm_page_t mpte, vm_offset_t va, 1472 vm_page_t m) --- 54 unchanged lines hidden (view full) --- 1527 } 1528 if (m->md.pv_flags & PV_TABLE_REF) 1529 vm_page_flag_set(m, PG_REFERENCED); 1530 m->md.pv_flags &= ~(PV_TABLE_REF | PV_TABLE_MOD); 1531 1532 pmap_remove_entry(pmap, m, va); 1533 } 1534 return pmap_unuse_pt(pmap, va, NULL); | 1443} 1444 1445/* 1446 * Conditionally create a pv entry. 1447 */ 1448static boolean_t 1449pmap_try_insert_pv_entry(pmap_t pmap, vm_page_t mpte, vm_offset_t va, 1450 vm_page_t m) --- 54 unchanged lines hidden (view full) --- 1505 } 1506 if (m->md.pv_flags & PV_TABLE_REF) 1507 vm_page_flag_set(m, PG_REFERENCED); 1508 m->md.pv_flags &= ~(PV_TABLE_REF | PV_TABLE_MOD); 1509 1510 pmap_remove_entry(pmap, m, va); 1511 } 1512 return pmap_unuse_pt(pmap, va, NULL); |
1535 | |
1536} 1537 1538/* 1539 * Remove a single page from a process address space 1540 */ 1541static void 1542pmap_remove_page(struct pmap *pmap, vm_offset_t va) 1543{ --- 74 unchanged lines hidden (view full) --- 1618 */ 1619 1620void 1621pmap_remove_all(vm_page_t m) 1622{ 1623 register pv_entry_t pv; 1624 register pt_entry_t *pte, tpte; 1625 | 1513} 1514 1515/* 1516 * Remove a single page from a process address space 1517 */ 1518static void 1519pmap_remove_page(struct pmap *pmap, vm_offset_t va) 1520{ --- 74 unchanged lines hidden (view full) --- 1595 */ 1596 1597void 1598pmap_remove_all(vm_page_t m) 1599{ 1600 register pv_entry_t pv; 1601 register pt_entry_t *pte, tpte; 1602 |
1626#if defined(PMAP_DEBUG) 1627 /* 1628 * XXX This makes pmap_remove_all() illegal for non-managed pages! 1629 */ 1630 if (m->flags & PG_FICTITIOUS) { 1631 panic("pmap_page_protect: illegal for unmanaged page, va: 0x%x", VM_PAGE_TO_PHYS(m)); 1632 } 1633#endif | 1603 KASSERT((m->flags & PG_FICTITIOUS) == 0, 1604 ("pmap_remove_all: page %p is fictitious", m)); |
1634 mtx_assert(&vm_page_queue_mtx, MA_OWNED); 1635 1636 if (m->md.pv_flags & PV_TABLE_REF) 1637 vm_page_flag_set(m, PG_REFERENCED); 1638 1639 while ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) { 1640 PMAP_LOCK(pv->pv_pmap); 1641 pv->pv_pmap->pm_stats.resident_count--; --- 837 unchanged lines hidden (view full) --- 2479pmap_page_exists_quick(pmap_t pmap, vm_page_t m) 2480{ 2481 pv_entry_t pv; 2482 int loops = 0; 2483 2484 if (m->flags & PG_FICTITIOUS) 2485 return FALSE; 2486 | 1605 mtx_assert(&vm_page_queue_mtx, MA_OWNED); 1606 1607 if (m->md.pv_flags & PV_TABLE_REF) 1608 vm_page_flag_set(m, PG_REFERENCED); 1609 1610 while ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) { 1611 PMAP_LOCK(pv->pv_pmap); 1612 pv->pv_pmap->pm_stats.resident_count--; --- 837 unchanged lines hidden (view full) --- 2450pmap_page_exists_quick(pmap_t pmap, vm_page_t m) 2451{ 2452 pv_entry_t pv; 2453 int loops = 0; 2454 2455 if (m->flags & PG_FICTITIOUS) 2456 return FALSE; 2457 |
2487 vm_page_lock_queues(); 2488 PMAP_LOCK(pmap); 2489 2490 /* 2491 * Not found, check current mappings returning immediately if found. 2492 */ | 2458 mtx_assert(&vm_page_queue_mtx, MA_OWNED); |
2493 TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) { 2494 if (pv->pv_pmap == pmap) { | 2459 TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) { 2460 if (pv->pv_pmap == pmap) { |
2495 PMAP_UNLOCK(pmap); 2496 vm_page_unlock_queues(); | |
2497 return TRUE; 2498 } 2499 loops++; 2500 if (loops >= 16) 2501 break; 2502 } | 2461 return TRUE; 2462 } 2463 loops++; 2464 if (loops >= 16) 2465 break; 2466 } |
2503 PMAP_UNLOCK(pmap); 2504 vm_page_unlock_queues(); | |
2505 return (FALSE); 2506} 2507 | 2467 return (FALSE); 2468} 2469 |
2508#define PMAP_REMOVE_PAGES_CURPROC_ONLY | |
2509/* 2510 * Remove all pages from specified address space 2511 * this aids process exit speeds. Also, this code 2512 * is special cased for current process only, but 2513 * can have the more generic (and slightly slower) 2514 * mode enabled. This is much faster than pmap_remove 2515 * in the case of running down an entire address space. 2516 */ 2517void 2518pmap_remove_pages(pmap_t pmap) 2519{ 2520 pt_entry_t *pte, tpte; 2521 pv_entry_t pv, npv; 2522 vm_page_t m; 2523 | 2470/* 2471 * Remove all pages from specified address space 2472 * this aids process exit speeds. Also, this code 2473 * is special cased for current process only, but 2474 * can have the more generic (and slightly slower) 2475 * mode enabled. This is much faster than pmap_remove 2476 * in the case of running down an entire address space. 2477 */ 2478void 2479pmap_remove_pages(pmap_t pmap) 2480{ 2481 pt_entry_t *pte, tpte; 2482 pv_entry_t pv, npv; 2483 vm_page_t m; 2484 |
2524#ifdef PMAP_REMOVE_PAGES_CURPROC_ONLY | |
2525 if (pmap != vmspace_pmap(curthread->td_proc->p_vmspace)) { 2526 printf("warning: pmap_remove_pages called with non-current pmap\n"); 2527 return; 2528 } | 2485 if (pmap != vmspace_pmap(curthread->td_proc->p_vmspace)) { 2486 printf("warning: pmap_remove_pages called with non-current pmap\n"); 2487 return; 2488 } |
2529#endif 2530 | |
2531 vm_page_lock_queues(); 2532 PMAP_LOCK(pmap); 2533 sched_pin(); 2534 //XXX need to be TAILQ_FOREACH_SAFE ? 2535 for (pv = TAILQ_FIRST(&pmap->pm_pvlist); 2536 pv; 2537 pv = npv) { 2538 --- 728 unchanged lines hidden (view full) --- 3267#ifdef VM_ALLOC_WIRED_TLB_PG_POOL 3268 else if (need_wired_tlb_page_pool && ((va >= VM_MIN_KERNEL_ADDRESS) && 3269 (va < (VM_MIN_KERNEL_ADDRESS + VM_KERNEL_ALLOC_OFFSET)))) 3270 pa = MIPS_CACHED_TO_PHYS(va); 3271#endif 3272 else if (va >= MIPS_KSEG2_START && va < VM_MAX_KERNEL_ADDRESS) { 3273 pt_entry_t *ptep; 3274 | 2489 vm_page_lock_queues(); 2490 PMAP_LOCK(pmap); 2491 sched_pin(); 2492 //XXX need to be TAILQ_FOREACH_SAFE ? 2493 for (pv = TAILQ_FIRST(&pmap->pm_pvlist); 2494 pv; 2495 pv = npv) { 2496 --- 728 unchanged lines hidden (view full) --- 3225#ifdef VM_ALLOC_WIRED_TLB_PG_POOL 3226 else if (need_wired_tlb_page_pool && ((va >= VM_MIN_KERNEL_ADDRESS) && 3227 (va < (VM_MIN_KERNEL_ADDRESS + VM_KERNEL_ALLOC_OFFSET)))) 3228 pa = MIPS_CACHED_TO_PHYS(va); 3229#endif 3230 else if (va >= MIPS_KSEG2_START && va < VM_MAX_KERNEL_ADDRESS) { 3231 pt_entry_t *ptep; 3232 |
3275 if (kernel_pmap) { | 3233 /* Is the kernel pmap initialized? */ 3234 if (kernel_pmap->pm_active) { |
3276 if (va >= (vm_offset_t)virtual_sys_start) { 3277 /* Its inside the virtual address range */ 3278 ptep = pmap_pte(kernel_pmap, va); 3279 if (ptep) 3280 pa = mips_tlbpfn_to_paddr(*ptep) | 3281 (va & PAGE_MASK); 3282 } else { 3283 int i; --- 24 unchanged lines hidden --- | 3235 if (va >= (vm_offset_t)virtual_sys_start) { 3236 /* Its inside the virtual address range */ 3237 ptep = pmap_pte(kernel_pmap, va); 3238 if (ptep) 3239 pa = mips_tlbpfn_to_paddr(*ptep) | 3240 (va & PAGE_MASK); 3241 } else { 3242 int i; --- 24 unchanged lines hidden --- |