PERFORCE change 32460 for review
Juli Mallett
jmallett at FreeBSD.org
Tue Jun 3 00:04:08 PDT 2003
http://perforce.freebsd.org/chv.cgi?CH=32460
Change 32460 by jmallett at jmallett_dalek on 2003/06/03 00:03:33
Simplify into a single level page table, which would really
like to be in tlb.c and have clean hooks here. Remove a lot
of stuff related to pagetables being done like on the Alpha.
Catch up with the PTE / TLB format for MIPS. Put in a function
which, again, belongs in tlb.c, for servicing a TLBMod exception.
This would work but for TLBUpdate being seemingly broken. Marking
newly entered pages as dirty gets a bit further. Various hooks
into ASID stuff.
Affected files ...
.. //depot/projects/mips/sys/mips/mips/pmap.c#15 edit
Differences ...
==== //depot/projects/mips/sys/mips/mips/pmap.c#15 (text+ko) ====
@@ -74,81 +74,14 @@
*/
/*
- * Notes for alpha pmap.
- *
- * On alpha, pm_pdeobj will hold lev1, lev2 and lev3 page tables.
- * Indices from 0 to NUSERLEV3MAPS-1 will map user lev3 page tables,
- * indices from NUSERLEV3MAPS to NUSERLEV3MAPS+NUSERLEV2MAPS-1 will
- * map user lev2 page tables and index NUSERLEV3MAPS+NUSERLEV2MAPS
- * will map the lev1 page table. The lev1 table will self map at
- * address VADDR(PTLEV1I,0,0).
- *
- * The vm_object kptobj holds the kernel page tables on i386 (62 or 63
- * of them, depending on whether the system is SMP). On alpha, kptobj
- * will hold the lev3 and lev2 page tables for K1SEG. Indices 0 to
- * NKLEV3MAPS-1 will map kernel lev3 page tables and indices
- * NKLEV3MAPS to NKLEV3MAPS+NKLEV2MAPS will map lev2 page tables. (XXX
- * should the kernel Lev1map be inserted into this object?).
- *
- * pvtmmap is not needed for alpha since K0SEG maps all of physical
- * memory.
- *
- *
- * alpha virtual memory map:
- *
- *
- * Address Lev1 index
- *
- * ---------------------------------
- * 0000000000000000 | | 0
- * | |
- * | |
- * | |
- * | |
- * --- ---
- * User space (USEG)
- * --- ---
- * | |
- * | |
- * | |
- * | |
- * 000003ffffffffff | | 511=UMAXLEV1I
- * ---------------------------------
- * fffffc0000000000 | | 512=K0SEGLEV1I
- * | Kernel code/data/bss |
- * | |
- * | |
- * | |
- * --- ---
- * K0SEG
- * --- ---
- * | |
- * | 1-1 physical/virtual |
- * | |
- * | |
- * fffffdffffffffff | |
- * ---------------------------------
- * fffffe0000000000 | | 768=K1SEGLEV1I
- * | Kernel dynamic data |
- * | |
- * | |
- * | |
- * --- ---
- * K1SEG
- * --- ---
- * | |
- * | mapped by ptes |
- * | |
- * | |
- * fffffff7ffffffff | |
- * ---------------------------------
- * fffffffe00000000 | | 1023=PTLEV1I
- * | PTmap (pte self map) |
- * ffffffffffffffff | |
- * ---------------------------------
- *
- * On the MIPS, K0SEG here is KSEG0, and K1SEG is XKSEG.
- *
+ * Notes on MIPS pmap:
+ * o) Unlike the Alpha, we don't put pages directly into the TLB.
+ * We use a PFN (which can be hidden by using PTE_TO_PA or
+ * PA_TO_PTE) which is the TLB's idea of a page, more or less.
+ * Don't be confused by PageMask, though, that just defines
+ * how big of an area each mapping masks. The addresses we
+ * take and put into the TLB are physical addresses, converted
+ * to a PFN.
* XXX Should we use XKPHYS instead of KSEG0 ?
*/
@@ -182,22 +115,12 @@
#include <machine/md_var.h>
/*
- * Map MIPS_PG definitions to PG ones.
+ * The joy of indexing.
+ *
+ * User addresses don't have the bits set that XKSEG has, best way to
+ * index the page table is to remove those bits, and get a page number.
*/
-#define PG_D MIPS3_PG_D
-#define PG_G MIPS3_PG_G
-#define PG_V MIPS3_PG_V
-/* SW bits. */
-#define PG_W MIPS3_PG_WIRED
-#define PG_MANAGED MIPS3_PG_M
-#define PG_RO MIPS3_PG_RO
-#define PG_PROT (PG_D | PG_RO)
-
-/*
- * Handy macros for PTE<->PFN.
- */
-#define MIPS_PTE_TO_PFN(pte) ((pte) >> 32)
-#define MIPS_PTE_FROM_PFN(pfn) ((pfn) << 32)
+#define pmap_index(va) (((va) & ~VM_MIN_KERNEL_ADDRESS) >> PAGE_SHIFT)
#ifndef PMAP_SHPGPERPROC
#define PMAP_SHPGPERPROC 200
@@ -221,21 +144,13 @@
#endif
/*
- * Some macros for manipulating virtual addresses
- */
-#define MIPS_L1SIZE (1L << MIPS_L1SHIFT)
-#define MIPS_L2SIZE (1L << MIPS_L2SHIFT)
-
-#define mips_l1trunc(va) ((va) & ~(MIPS_L1SIZE-1))
-#define mips_l2trunc(va) ((va) & ~(MIPS_L2SIZE-1))
-
-/*
* Get PDEs and PTEs for user/kernel address space
*/
+#define pmap_pte_ro(pte) ((*(pte) & PG_RO) != 0)
#define pmap_pte_w(pte) ((*(pte) & PG_W) != 0)
-#define pmap_pte_managed(pte) ((*(pte) & PG_MANAGED) != 0)
+#define pmap_pte_managed(pte) ((*(pte) & PG_M) != 0)
#define pmap_pte_v(pte) ((*(pte) & PG_V) != 0)
-#define pmap_pte_pa(pte) ptob(MIPS_PTE_TO_PFN(*(pte)))
+#define pmap_pte_pa(pte) MIPS_PTE_TO_PA(*(pte))
#define pmap_pte_prot(pte) (*(pte) & PG_PROT)
#define pmap_pte_set_w(pte, v) ((v)?(*pte |= PG_W):(*pte &= ~PG_W))
@@ -259,14 +174,10 @@
*/
#define PTMASK ((1 << MIPS_PTSHIFT) - 1)
-#define pmap_lev1_index(va) (((va) >> MIPS_L1SHIFT) & PTMASK)
-#define pmap_lev2_index(va) (((va) >> MIPS_L2SHIFT) & PTMASK)
-#define pmap_lev3_index(va) (((va) >> MIPS_L3SHIFT) & PTMASK)
-
/*
* Given a physical address, construct a pte
*/
-#define pmap_phys_to_pte(pa) MIPS_PTE_FROM_PFN(btop(pa))
+#define pmap_phys_to_pte(pa) MIPS_PA_TO_PFN(pa)
/*
* Given a page frame number, construct a k0seg va
@@ -276,46 +187,10 @@
/*
* Given a pte, construct a k0seg va
*/
-#define pmap_k0seg_to_pte(va) MIPS_PTE_FROM_PFN(pmap_k0seg_to_pfn(va))
+#define pmap_k0seg_to_pte(va) MIPS_PA_TO_PFN(pmap_k0seg_to_pfn(va))
-/*
- * Lev1map:
- *
- * Kernel level 1 page table. This maps all kernel level 2
- * page table pages, and is used as a template for all user
- * pmap level 1 page tables. When a new user level 1 page
- * table is allocated, all Lev1map PTEs for kernel addresses
- * are copied to the new map.
- *
- * Lev2map:
- *
- * Initial set of kernel level 2 page table pages. These
- * map the kernel level 3 page table pages. As kernel
- * level 3 page table pages are added, more level 2 page
- * table pages may be added to map them. These pages are
- * never freed.
- *
- * Lev3map:
- *
- * Initial set of kernel level 3 page table pages. These
- * map pages in K1SEG. More level 3 page table pages may
- * be added at run-time if additional K1SEG address space
- * is required. These pages are never freed.
- *
- * Lev2mapsize:
- *
- * Number of entries in the initial Lev2map.
- *
- * Lev3mapsize:
- *
- * Number of entries in the initial Lev3map.
- *
- * NOTE: When mappings are inserted into the kernel pmap, all
- * level 2 and level 3 page table pages must already be allocated
- * and mapped into the parent page table.
- */
-pt_entry_t *Lev1map, *Lev2map, *Lev3map;
-vm_size_t Lev2mapsize, Lev3mapsize;
+pt_entry_t *kptmap;
+vm_size_t kptsize;
/*
* Statically allocated kernel pmap
@@ -330,7 +205,6 @@
vm_offset_t virtual_end; /* VA of last avail page (end of kernel AS) */
static boolean_t pmap_initialized = FALSE; /* Has pmap_init completed? */
-static int nklev3, nklev2;
vm_offset_t kernel_vm_end;
struct msgbuf *msgbufp;
@@ -353,80 +227,37 @@
static PMAP_INLINE void free_pv_entry(pv_entry_t pv);
static pv_entry_t get_pv_entry(void);
-static vm_page_t pmap_enter_quick(pmap_t pmap, vm_offset_t va,
- vm_page_t m, vm_page_t mpte);
static int pmap_remove_pte(pmap_t pmap, pt_entry_t* ptq, vm_offset_t sva);
static void pmap_remove_page(struct pmap *pmap, vm_offset_t va);
static int pmap_remove_entry(struct pmap *pmap, vm_page_t m, vm_offset_t va);
static void pmap_insert_entry(pmap_t pmap, vm_offset_t va,
vm_page_t mpte, vm_page_t m);
-static vm_page_t pmap_allocpte(pmap_t pmap, vm_offset_t va);
-static int pmap_release_free_page(pmap_t pmap, vm_page_t p);
-static vm_page_t _pmap_allocpte(pmap_t pmap, unsigned ptepindex);
-static vm_page_t pmap_page_lookup(vm_object_t object, vm_pindex_t pindex);
-static int pmap_unuse_pt(pmap_t, vm_offset_t, vm_page_t);
-#ifdef SMP
-static void pmap_invalidate_page_action(void *arg);
-static void pmap_invalidate_all_action(void *arg);
-#endif
-
-
/*
- * Routine: pmap_lev1pte
- * Function:
- * Extract the level 1 page table entry associated
- * with the given map/virtual_address pair.
+ * Routine: pmap_pte
+ * Function:
+ * Extract the page table entry associated with
+ * the given map/virtual addresss pair.
*/
static PMAP_INLINE pt_entry_t*
-pmap_lev1pte(pmap_t pmap, vm_offset_t va)
+pmap_pte(pmap_t pmap, vm_offset_t va)
{
- if (!pmap)
- return 0;
- return &pmap->pm_lev1[pmap_lev1_index(va)];
+ if (pmap == NULL || pmap->pm_lev1 == NULL)
+ return NULL;
+ return &pmap->pm_lev1[pmap_index(va)];
}
-/*
- * Routine: pmap_lev2pte
- * Function:
- * Extract the level 2 page table entry associated
- * with the given map/virtual_address pair.
- */
-static PMAP_INLINE pt_entry_t*
-pmap_lev2pte(pmap_t pmap, vm_offset_t va)
-{
- pt_entry_t* l1pte;
- pt_entry_t* l2map;
-
- l1pte = pmap_lev1pte(pmap, va);
- if (!pmap_pte_v(l1pte))
- return 0;
- l2map = (pt_entry_t*) MIPS_PHYS_TO_KSEG0(pmap_pte_pa(l1pte));
- return &l2map[pmap_lev2_index(va)];
-}
-
/*
- * Routine: pmap_lev3pte
- * Function:
- * Extract the level 3 page table entry associated
- * with the given map/virtual_address pair.
+ * Routine: pmap_steal_memory
+ * Function:
+ * Steal memory from the phys_avail[] array, early
+ * in the bootup process. It returns zeroed memory
+ * and looks around for a contiguous segment big
+ * enough to fill the request, mapped into direct
+ * memory.
*/
-static PMAP_INLINE pt_entry_t*
-pmap_lev3pte(pmap_t pmap, vm_offset_t va)
-{
- pt_entry_t* l2pte;
- pt_entry_t* l3map;
-
- l2pte = pmap_lev2pte(pmap, va);
- if (!l2pte || !pmap_pte_v(l2pte))
- return 0;
-
- l3map = (pt_entry_t*) MIPS_PHYS_TO_KSEG0(pmap_pte_pa(l2pte));
- return &l3map[pmap_lev3_index(va)];
-}
-
vm_offset_t
pmap_steal_memory(vm_size_t size)
{
@@ -459,95 +290,81 @@
/*
* Bootstrap the system enough to run with virtual memory.
+ *
+ * This sets up the ASID generator, message buffer, and page
+ * table. XXX Probably want to move page table and related to
+ * a TLB-specific file. It also sets up some very important
+ * values for MI VM code to run.
*/
void
pmap_bootstrap(void)
{
- pt_entry_t newpte;
+ pt_entry_t *pte;
int i;
/*
* Setup ASIDs. PCPU_GET(next_asid) and PCPU_GET(current_asidgen) are set
* up already.
*/
- pmap_maxasid = ASID_BITS * 8;
+ pmap_maxasid = MIPS3_TLB_NUM_ASIDS;
/*
* Steal the message buffer from the beginning of memory.
*/
msgbufp = (struct msgbuf *) pmap_steal_memory(MSGBUF_SIZE);
+ msgbufinit(msgbufp, MSGBUF_SIZE);
/*
- * Allocate a level 1 map for the kernel.
+ * Set up kernel page table.
*/
- Lev1map = (pt_entry_t*) pmap_steal_memory(PAGE_SIZE);
-
- /*
- * Allocate a level 2 map for the kernel
- */
- Lev2map = (pt_entry_t*) pmap_steal_memory(PAGE_SIZE);
- Lev2mapsize = PAGE_SIZE;
+ kptsize = physsz >> PAGE_SHIFT;
+ printf("Kernel page table indexes %ld %dK pages.\n",
+ kptsize, PAGE_SIZE / 1024);
+ kptmap = (pt_entry_t *)
+ pmap_steal_memory(kptsize * sizeof (pt_entry_t));
- /*
- * Allocate some level 3 maps for the kernel
- */
- Lev3map = (pt_entry_t*) pmap_steal_memory(PAGE_SIZE*NKPT);
- Lev3mapsize = NKPT * PAGE_SIZE;
-
- /* Map all of the level 2 maps */
- for (i = 0; i < howmany(Lev2mapsize, PAGE_SIZE); i++) {
- unsigned long pfn =
- pmap_k0seg_to_pfn((vm_offset_t) Lev2map) + i;
- newpte = MIPS_PTE_FROM_PFN(pfn);
- newpte |= PG_V | PG_W;
- Lev1map[K1SEGLEV1I + i] = newpte;
- }
-
- /*
- * Level 1 self mapping.
- *
- * Don't use ASID since the self-mapping is different for each
- * address space.
- */
- newpte = pmap_k0seg_to_pte((vm_offset_t) Lev1map);
- newpte |= PG_V | PG_G;
- Lev1map[PTLEV1I] = newpte;
-
- /* Map all of the level 3 maps */
- for (i = 0; i < howmany(Lev3mapsize, PAGE_SIZE); i++) {
- unsigned long pfn =
- pmap_k0seg_to_pfn((vm_offset_t) Lev3map) + i;
- newpte = MIPS_PTE_FROM_PFN(pfn);
- newpte |= PG_V | PG_W;
- Lev2map[i] = newpte;
- }
-
avail_start = phys_avail[0];
for (i = 0; phys_avail[i+2]; i+= 2) ;
avail_end = phys_avail[i+1];
virtual_avail = VM_MIN_KERNEL_ADDRESS;
- virtual_end = VPTBASE;
+ virtual_end = virtual_avail + (avail_end - avail_start);
kernel_vm_end = virtual_end;
/*
* Initialize the kernel pmap (which is statically allocated).
*/
- kernel_pmap->pm_lev1 = Lev1map;
+ kernel_pmap->pm_lev1 = kptmap;
kernel_pmap->pm_active = ~0;
kernel_pmap->pm_asid = 0;
kernel_pmap->pm_asidgen = 1;
TAILQ_INIT(&kernel_pmap->pm_pvlist);
- nklev3 = NKPT;
- nklev2 = 1;
/*
* Initialize list of pmaps.
*/
LIST_INIT(&allpmaps);
LIST_INSERT_HEAD(&allpmaps, kernel_pmap, pm_list);
+
+ /*
+ * Lock in the current ASID, and set the global bit on each PTE.
+ */
+ mips_wr_entryhi(kernel_pmap->pm_asid);
+ for (i = 0; i < kptsize; i++) {
+ pte = &kptmap[i];
+ *pte = PG_G;
+ }
+
+ /*
+ * Clear the TLB.
+ */
+ MIPS_TBIAP();
}
+/*
+ * Perform a small allocation for UMA, used early in the boot process
+ * and possibly at other times.
+ */
void *
uma_small_alloc(uma_zone_t zone, int bytes, u_int8_t *flags, int wait)
{
@@ -583,6 +400,9 @@
return (va);
}
+/*
+ * A free function for the above.
+ */
void
uma_small_free(void *mem, int size, u_int8_t flags)
{
@@ -663,11 +483,6 @@
pmap->pm_asidgen = 0;
}
-struct pmap_invalidate_page_arg {
- pmap_t pmap;
- vm_offset_t va;
-};
-
static void
pmap_invalidate_page(pmap_t pmap, vm_offset_t va)
{
@@ -760,7 +575,10 @@
* Routine: pmap_kextract
* Function:
* Extract the physical page address associated
- * kernel virtual address.
+ * kernel virtual address. If this is a direct-
+ * mapped piece of memory, just decode that,
+ * otherwise call pmap_extract which is pretty
+ * fast.
*/
vm_offset_t
pmap_kextract(vm_offset_t va)
@@ -770,8 +588,7 @@
if (va >= MIPS_KSEG0_START && va <= MIPS_KSEG0_END)
pa = MIPS_KSEG0_TO_PHYS(va);
else
- pa = ptob(MIPS_PTE_TO_PFN(*vtopte(va)))
- | (va & PAGE_MASK);
+ pa = pmap_extract(kernel_pmap, va);
return pa;
}
@@ -786,9 +603,9 @@
register pmap_t pmap;
vm_offset_t va;
{
- pt_entry_t* pte = pmap_lev3pte(pmap, va);
+ pt_entry_t* pte = pmap_pte(pmap, va);
if (pte)
- return ptob(MIPS_PTE_TO_PFN(*pte));
+ return MIPS_PTE_TO_PA(*pte) | (va & PAGE_MASK);
else
return 0;
}
@@ -817,10 +634,10 @@
pt_entry_t npte = pmap_phys_to_pte(VM_PAGE_TO_PHYS(m[i]))
| PG_V;
pt_entry_t opte;
- pte = vtopte(tva);
+ pte = pmap_pte(kernel_pmap, tva);
opte = *pte;
*pte = npte;
- if (opte)
+ if (opte & PG_V)
pmap_invalidate_page(kernel_pmap, tva);
}
}
@@ -838,7 +655,7 @@
register pt_entry_t *pte;
for (i = 0; i < count; i++) {
- pte = vtopte(va);
+ pte = pmap_pte(kernel_pmap, va);
*pte = 0;
pmap_invalidate_page(kernel_pmap, va);
va += PAGE_SIZE;
@@ -857,11 +674,12 @@
pt_entry_t npte, opte;
npte = pmap_phys_to_pte(pa) | PG_V;
- pte = vtopte(va);
+ pte = pmap_pte(kernel_pmap, va);
opte = *pte;
*pte = npte;
- if (opte)
+ if (opte & PG_V)
pmap_invalidate_page(kernel_pmap, va);
+ MachTLBUpdate(va & ~PAGE_MASK, npte);
}
/*
@@ -872,7 +690,7 @@
{
register pt_entry_t *pte;
- pte = vtopte(va);
+ pte = pmap_pte(kernel_pmap, va);
*pte = 0;
pmap_invalidate_page(kernel_pmap, va);
}
@@ -895,22 +713,6 @@
return MIPS_PHYS_TO_KSEG0(start);
}
-
-static vm_page_t
-pmap_page_lookup(vm_object_t object, vm_pindex_t pindex)
-{
- vm_page_t m;
-retry:
- m = vm_page_lookup(object, pindex);
- if (m != NULL) {
- vm_page_lock_queues();
- if (vm_page_sleep_if_busy(m, FALSE, "pplookp"))
- goto retry;
- vm_page_unlock_queues();
- }
- return m;
-}
-
#ifndef KSTACK_MAX_PAGES
#define KSTACK_MAX_PAGES 32
#endif
@@ -947,10 +749,10 @@
panic("pmap_new_thread: kstack allocation failed");
/* Set the first page to be the unmapped guard page. */
- ptek = vtopte(ks);
+ ptek = pmap_pte(kernel_pmap, ks);
oldpte = *ptek;
*ptek = 0;
- if (oldpte)
+ if (oldpte & PG_V)
pmap_invalidate_page(kernel_pmap, ks);
/* move to the next page, which is where the real stack starts. */
ks += PAGE_SIZE;
@@ -962,7 +764,7 @@
if (ks == NULL)
panic("pmap_new_thread: kstack allocation failed");
td->td_kstack = ks;
- ptek = vtopte(ks);
+ ptek = pmap_pte(kernel_pmap, ks);
#endif
/*
* Knowing the number of pages allocated is useful when you
@@ -987,7 +789,7 @@
oldpte = ptek[i];
ptek[i] = pmap_phys_to_pte(VM_PAGE_TO_PHYS(m))
| PG_V;
- if (oldpte)
+ if (oldpte & PG_V)
pmap_invalidate_page(kernel_pmap, ks + i * PAGE_SIZE);
vm_page_lock_queues();
@@ -1016,7 +818,7 @@
pages = td->td_kstack_pages;
ksobj = td->td_kstack_obj;
ks = td->td_kstack;
- ptek = vtopte(ks);
+ ptek = pmap_pte(kernel_pmap, ks);
for (i = 0; i < pages; i++) {
m = vm_page_lookup(ksobj, i);
if (m == NULL)
@@ -1139,119 +941,12 @@
}
}
-/***************************************************
- * Page table page management routines.....
- ***************************************************/
-
-/*
- * This routine unholds page table pages, and if the hold count
- * drops to zero, then it decrements the wire count.
- */
-static int
-_pmap_unwire_pte_hold(pmap_t pmap, vm_offset_t va, vm_page_t m)
-{
-
- while (vm_page_sleep_if_busy(m, FALSE, "pmuwpt"))
- vm_page_lock_queues();
-
- if (m->hold_count == 0) {
- vm_offset_t pteva;
- pt_entry_t* pte;
-
- /*
- * unmap the page table page
- */
- if (m->pindex >= NUSERLEV3MAPS) {
- /* Level 2 page table */
- pte = pmap_lev1pte(pmap, va);
- pteva = (vm_offset_t) PTlev2 + ptob(m->pindex - NUSERLEV3MAPS);
- } else {
- /* Level 3 page table */
- pte = pmap_lev2pte(pmap, va);
- pteva = (vm_offset_t) PTmap + ptob(m->pindex);
- }
-
- *pte = 0;
-
- if (m->pindex < NUSERLEV3MAPS) {
- /* unhold the level 2 page table */
- vm_page_t lev2pg;
- lev2pg = vm_page_lookup(pmap->pm_pteobj,
- NUSERLEV3MAPS + pmap_lev1_index(va));
- while (vm_page_sleep_if_busy(lev2pg, FALSE, "pulook"))
- vm_page_lock_queues();
- vm_page_unhold(lev2pg);
- if (lev2pg->hold_count == 0)
- _pmap_unwire_pte_hold(pmap, va, lev2pg);
- }
-
- --pmap->pm_stats.resident_count;
- /*
- * Do a invltlb to make the invalidated mapping
- * take effect immediately.
- */
- pmap_invalidate_page(pmap, pteva);
-
- if (pmap->pm_ptphint == m)
- pmap->pm_ptphint = NULL;
-
- /*
- * If the page is finally unwired, simply free it.
- */
- --m->wire_count;
- if (m->wire_count == 0) {
- vm_page_busy(m);
- vm_page_free_zero(m);
- --cnt.v_wire_count;
- }
- return 1;
- }
- return 0;
-}
-
-static PMAP_INLINE int
-pmap_unwire_pte_hold(pmap_t pmap, vm_offset_t va, vm_page_t m)
-{
- vm_page_unhold(m);
- if (m->hold_count == 0)
- return _pmap_unwire_pte_hold(pmap, va, m);
- else
- return 0;
-}
-
-/*
- * After removing a page table entry, this routine is used to
- * conditionally free the page, and manage the hold/wire counts.
- */
-static int
-pmap_unuse_pt(pmap_t pmap, vm_offset_t va, vm_page_t mpte)
-{
- unsigned ptepindex;
- if (va >= VM_MAXUSER_ADDRESS)
- return 0;
-
- if (mpte == NULL) {
- ptepindex = (va >> MIPS_L2SHIFT);
- if (pmap->pm_ptphint &&
- (pmap->pm_ptphint->pindex == ptepindex)) {
- mpte = pmap->pm_ptphint;
- } else {
- while ((mpte = vm_page_lookup(pmap->pm_pteobj, ptepindex)) != NULL &&
- vm_page_sleep_if_busy(mpte, FALSE, "pulook"))
- vm_page_lock_queues();
- pmap->pm_ptphint = mpte;
- }
- }
-
- return pmap_unwire_pte_hold(pmap, va, mpte);
-}
-
void
pmap_pinit0(pmap)
struct pmap *pmap;
{
- pmap->pm_lev1 = Lev1map;
+ pmap->pm_lev1 = kptmap;
pmap->pm_ptphint = NULL;
pmap->pm_active = 0;
pmap->pm_asid = 0;
@@ -1319,194 +1014,8 @@
pmap_pinit2(pmap)
struct pmap *pmap;
{
- bcopy(PTlev1 + K1SEGLEV1I, pmap->pm_lev1 + K1SEGLEV1I, nklev2 * sizeof (pt_entry_t));
-}
-
-static int
-pmap_release_free_page(pmap_t pmap, vm_page_t p)
-{
- pt_entry_t* pte;
- pt_entry_t* l2map;
-
- if (p->pindex >= NUSERLEV3MAPS + NUSERLEV2MAPS)
- /* level 1 page table */
- pte = &pmap->pm_lev1[PTLEV1I];
- else if (p->pindex >= NUSERLEV3MAPS)
- /* level 2 page table */
- pte = &pmap->pm_lev1[p->pindex - NUSERLEV3MAPS];
- else {
- /* level 3 page table */
- pte = &pmap->pm_lev1[p->pindex >> MIPS_PTSHIFT];
- l2map = (pt_entry_t*) MIPS_PHYS_TO_KSEG0(pmap_pte_pa(pte));
- pte = &l2map[p->pindex & ((1 << MIPS_PTSHIFT) - 1)];
- }
-
- /*
- * This code optimizes the case of freeing non-busy
- * page-table pages. Those pages are zero now, and
- * might as well be placed directly into the zero queue.
- */
- vm_page_lock_queues();
- if (vm_page_sleep_if_busy(p, FALSE, "pmaprl"))
- return 0;
-
- vm_page_busy(p);
-
- /*
- * Remove the page table page from the processes address space.
- */
- *pte = 0;
- pmap->pm_stats.resident_count--;
-
-#ifdef PMAP_DEBUG
- if (p->hold_count) {
- panic("pmap_release: freeing held page table page");
- }
-#endif
- /*
- * Level1 pages need to have the kernel
- * stuff cleared, so they can go into the zero queue also.
- */
- if (p->pindex == NUSERLEV3MAPS + NUSERLEV2MAPS)
- bzero(pmap->pm_lev1 + K1SEGLEV1I, nklev2 * sizeof (pt_entry_t));
-
- if (pmap->pm_ptphint == p)
- pmap->pm_ptphint = NULL;
-
-#ifdef PMAP_DEBUG
- {
- u_long *lp = (u_long*) MIPS_PHYS_TO_KSEG0(VM_PAGE_TO_PHYS(p));
- u_long *ep = (u_long*) ((char*) lp + PAGE_SIZE);
- for (; lp < ep; lp++)
- if (*lp != 0)
- panic("pmap_release_free_page: page not zero");
- }
-#endif
-
- p->wire_count--;
- cnt.v_wire_count--;
- vm_page_free_zero(p);
- vm_page_unlock_queues();
- return 1;
-}
-
-/*
- * this routine is called if the page table page is not
- * mapped correctly.
- */
-static vm_page_t
-_pmap_allocpte(pmap, ptepindex)
- pmap_t pmap;
- unsigned ptepindex;
-{
- pt_entry_t* pte;
- vm_offset_t ptepa;
- vm_page_t m;
-
- /*
- * Find or fabricate a new pagetable page
- */
- m = vm_page_grab(pmap->pm_pteobj, ptepindex,
- VM_ALLOC_WIRED | VM_ALLOC_ZERO | VM_ALLOC_RETRY);
-
- KASSERT(m->queue == PQ_NONE,
- ("_pmap_allocpte: %p->queue != PQ_NONE", m));
-
- /*
- * Increment the hold count for the page table page
- * (denoting a new mapping.)
- */
- m->hold_count++;
-
- /*
- * Map the pagetable page into the process address space, if
- * it isn't already there.
- */
-
- pmap->pm_stats.resident_count++;
-
- ptepa = VM_PAGE_TO_PHYS(m);
-
- if (ptepindex >= NUSERLEV3MAPS) {
- pte = &pmap->pm_lev1[ptepindex - NUSERLEV3MAPS];
- } else {
- int l1index = ptepindex >> MIPS_PTSHIFT;
- pt_entry_t* l1pte = &pmap->pm_lev1[l1index];
- pt_entry_t* l2map;
- if (!pmap_pte_v(l1pte))
- _pmap_allocpte(pmap, NUSERLEV3MAPS + l1index);
- else {
- vm_page_t l2page =
- pmap_page_lookup(pmap->pm_pteobj,
- NUSERLEV3MAPS + l1index);
- l2page->hold_count++;
- }
- l2map = (pt_entry_t*) MIPS_PHYS_TO_KSEG0(pmap_pte_pa(l1pte));
- pte = &l2map[ptepindex & ((1 << MIPS_PTSHIFT) - 1)];
- }
-
- *pte = pmap_phys_to_pte(ptepa) | PG_V;
-
- /*
- * Set the page table hint
- */
- pmap->pm_ptphint = m;
-
- if ((m->flags & PG_ZERO) == 0)
- bzero((caddr_t) MIPS_PHYS_TO_KSEG0(ptepa), PAGE_SIZE);
-
- vm_page_lock_queues();
- m->valid = VM_PAGE_BITS_ALL;
- vm_page_flag_clear(m, PG_ZERO);
- vm_page_wakeup(m);
- vm_page_unlock_queues();
-
- return m;
-}
-
-static vm_page_t
-pmap_allocpte(pmap_t pmap, vm_offset_t va)
-{
- unsigned ptepindex;
- pt_entry_t* lev2pte;
- vm_page_t m;
-
- /*
- * Calculate pagetable page index
- */
- ptepindex = va >> (PAGE_SHIFT + MIPS_PTSHIFT);
-
- /*
- * Get the level2 entry
- */
- lev2pte = pmap_lev2pte(pmap, va);
-
- /*
- * If the page table page is mapped, we just increment the
- * hold count, and activate it.
- */
- if (lev2pte && pmap_pte_v(lev2pte)) {
- /*
- * In order to get the page table page, try the
- * hint first.
- */
- if (pmap->pm_ptphint &&
- (pmap->pm_ptphint->pindex == ptepindex)) {
- m = pmap->pm_ptphint;
- } else {
- m = pmap_page_lookup(pmap->pm_pteobj, ptepindex);
- pmap->pm_ptphint = m;
- }
- m->hold_count++;
- return m;
- }
- /*
- * Here if the pte page isn't mapped, or if it has been deallocated.
- */
- return _pmap_allocpte(pmap, ptepindex);
}
-
/***************************************************
* Pmap allocation/deallocation routines.
***************************************************/
@@ -1537,7 +1046,7 @@
continue;
}
while (1) {
- if (!pmap_release_free_page(pmap, p) &&
+ if (/*!pmap_release_free_page(pmap, p) &&*/
(object->generation != curgeneration))
goto retry;
}
@@ -1553,13 +1062,13 @@
continue;
}
while (1) {
- if (!pmap_release_free_page(pmap, p) &&
+ if (/*!pmap_release_free_page(pmap, p) &&*/
(object->generation != curgeneration))
goto retry;
}
}
- if (lev1pg && !pmap_release_free_page(pmap, lev1pg))
+ if (lev1pg/* && !pmap_release_free_page(pmap, lev1pg)*/)
goto retry;
mtx_lock_spin(&allpmaps_lock);
LIST_REMOVE(pmap, pm_list);
@@ -1572,93 +1081,7 @@
void
pmap_growkernel(vm_offset_t addr)
{
- /* XXX come back to this */
- struct pmap *pmap;
- pt_entry_t* pte;
- pt_entry_t newlev1, newlev2;
- vm_offset_t pa;
- vm_page_t nkpg;
-
- critical_enter();
- if (kernel_vm_end == 0) {
- kernel_vm_end = VM_MIN_KERNEL_ADDRESS;
-
- /* Count the level 2 page tables */
- nklev2 = 0;
- nklev3 = 0;
- while (pmap_pte_v(pmap_lev1pte(kernel_pmap, kernel_vm_end))) {
- nklev2++;
- nklev3 += (1L << MIPS_PTSHIFT);
- kernel_vm_end += MIPS_L1SIZE;
- }
-
- /* Count the level 3 page tables in the last level 2 page table */
- kernel_vm_end -= MIPS_L1SIZE;
- nklev3 -= (1 << MIPS_PTSHIFT);
- while (pmap_pte_v(pmap_lev2pte(kernel_pmap, kernel_vm_end))) {
- nklev3++;
- kernel_vm_end += MIPS_L2SIZE;
- }
- }
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list