From hp300 pmap: use mycroft's pv_entry allocator (from i386 port).

This commit is contained in:
thorpej 1997-09-03 19:07:32 +00:00
parent 702b60b0c1
commit 032358ab33
2 changed files with 161 additions and 10 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: pmap.old.c,v 1.21 1997/09/03 00:58:14 thorpej Exp $ */
/* $NetBSD: pmap.old.c,v 1.22 1997/09/03 19:07:32 thorpej Exp $ */
/*
* Copyright (c) 1991, 1993
@ -98,7 +98,7 @@
#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
__KERNEL_RCSID(0, "$NetBSD: pmap.old.c,v 1.21 1997/09/03 00:58:14 thorpej Exp $");
__KERNEL_RCSID(0, "$NetBSD: pmap.old.c,v 1.22 1997/09/03 19:07:32 thorpej Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -256,8 +256,13 @@ vm_offset_t virtual_avail; /* VA of first avail page (after kernel bss)*/
vm_offset_t virtual_end; /* VA of last avail page (end of kernel AS) */
vm_offset_t vm_first_phys; /* PA of first managed page */
vm_offset_t vm_last_phys; /* PA just past last managed page */
int pv_table_npages;
boolean_t pmap_initialized = FALSE; /* Has pmap_init completed? */
struct pv_entry *pv_table;
char *pmap_attributes; /* reference and modify bits */
TAILQ_HEAD(pv_page_list, pv_page) pv_page_freelist;
int pv_nfree;
/*
* Internal routines
@ -271,6 +276,10 @@ void pmap_pvdump __P((vm_offset_t));
void pmap_check_wiring __P((char *, vm_offset_t));
#endif
struct pv_entry *pmap_alloc_pv __P((void));
void pmap_free_pv __P((struct pv_entry *));
void pmap_collect_pv __P((void));
#define PAGE_IS_MANAGED(pa) ((pa) >= vm_first_phys && (pa) < vm_last_phys)
/* pmap_remove_mapping flags */
@ -379,8 +388,9 @@ pmap_bootstrap(firstaddr, ptaddr)
* phys_start and phys_end but its better to use kseg0 addresses
* rather than kernel virtual addresses mapped through the TLB.
*/
i = 1 + lastusablepage - alpha_btop(ALPHA_K0SEG_TO_PHYS(firstaddr));
valloc(pv_table, struct pv_entry, i);
pv_table_npages = 1 + lastusablepage -
alpha_btop(ALPHA_K0SEG_TO_PHYS(firstaddr));
valloc(pv_table, struct pv_entry, pv_table_npages);
/*
* Clear allocated memory.
@ -548,7 +558,13 @@ pmap_init(phys_start, phys_end)
*/
s = maxproc * ALPHA_MAX_PTSIZE; /* XXX limit it */
pt_map = kmem_suballoc(kernel_map, &addr, &addr2, s, TRUE);
/*
* The pv_table has already been allocated. Initialize
* the pv_page free list.
*/
TAILQ_INIT(&pv_page_freelist);
/*
* Now it is safe to enable pv_table recording.
*/
@ -1088,8 +1104,7 @@ pmap_enter(pmap, va, pa, prot, wired)
if (pmap == npv->pv_pmap && va == npv->pv_va)
panic("pmap_enter: already in pv_tab");
#endif
npv = (pv_entry_t)
malloc(sizeof *npv, M_VMPVENT, M_NOWAIT);
npv = pmap_alloc_pv();
npv->pv_va = va;
npv->pv_pmap = pmap;
npv->pv_next = pv->pv_next;
@ -1406,6 +1421,11 @@ ok:
#endif
}
splx(s);
#ifdef notyet
/* Go compact and garbage-collect the pv_table. */
pmap_collect_pv();
#endif
}
/*
@ -1800,7 +1820,7 @@ pmap_remove_mapping(pmap, va, pte, flags)
if (npv) {
npv->pv_flags = pv->pv_flags;
*pv = *npv;
free((caddr_t)npv, M_VMPVENT);
pmap_free_pv(npv);
} else
pv->pv_pmap = NULL;
#ifdef PMAPSTATS
@ -1822,7 +1842,7 @@ pmap_remove_mapping(pmap, va, pte, flags)
ste = npv->pv_ptpte;
ptpmap = npv->pv_ptpmap;
pv->pv_next = npv->pv_next;
free((caddr_t)npv, M_VMPVENT);
pmap_free_pv(npv);
pv = pa_to_pvh(pa);
}
/*
@ -2320,3 +2340,119 @@ vtophys(vaddr)
return (paddr);
}
/******************** pv_entry management ********************/
struct pv_entry *
pmap_alloc_pv()
{
struct pv_page *pvp;
struct pv_entry *pv;
int i;
if (pv_nfree == 0) {
pvp = (struct pv_page *)kmem_alloc(kernel_map, NBPG);
if (pvp == 0)
panic("pmap_alloc_pv: kmem_alloc() failed");
pvp->pvp_pgi.pgi_freelist = pv = &pvp->pvp_pv[1];
for (i = NPVPPG - 2; i; i--, pv++)
pv->pv_next = pv + 1;
pv->pv_next = 0;
pv_nfree += pvp->pvp_pgi.pgi_nfree = NPVPPG - 1;
TAILQ_INSERT_HEAD(&pv_page_freelist, pvp, pvp_pgi.pgi_list);
pv = &pvp->pvp_pv[0];
} else {
--pv_nfree;
pvp = pv_page_freelist.tqh_first;
if (--pvp->pvp_pgi.pgi_nfree == 0) {
TAILQ_REMOVE(&pv_page_freelist, pvp, pvp_pgi.pgi_list);
}
pv = pvp->pvp_pgi.pgi_freelist;
#ifdef DIAGNOSTIC
if (pv == 0)
panic("pmap_alloc_pv: pgi_nfree inconsistent");
#endif
pvp->pvp_pgi.pgi_freelist = pv->pv_next;
}
return pv;
}
void
pmap_free_pv(pv)
struct pv_entry *pv;
{
register struct pv_page *pvp;
pvp = (struct pv_page *) trunc_page(pv);
switch (++pvp->pvp_pgi.pgi_nfree) {
case 1:
TAILQ_INSERT_TAIL(&pv_page_freelist, pvp, pvp_pgi.pgi_list);
default:
pv->pv_next = pvp->pvp_pgi.pgi_freelist;
pvp->pvp_pgi.pgi_freelist = pv;
++pv_nfree;
break;
case NPVPPG:
pv_nfree -= NPVPPG - 1;
TAILQ_REMOVE(&pv_page_freelist, pvp, pvp_pgi.pgi_list);
kmem_free(kernel_map, (vm_offset_t)pvp, NBPG);
break;
}
}
void
pmap_collect_pv()
{
struct pv_page_list pv_page_collectlist;
struct pv_page *pvp, *npvp;
struct pv_entry *ph, *ppv, *pv, *npv;
int s;
TAILQ_INIT(&pv_page_collectlist);
for (pvp = pv_page_freelist.tqh_first; pvp; pvp = npvp) {
if (pv_nfree < NPVPPG)
break;
npvp = pvp->pvp_pgi.pgi_list.tqe_next;
if (pvp->pvp_pgi.pgi_nfree > NPVPPG / 3) {
TAILQ_REMOVE(&pv_page_freelist, pvp, pvp_pgi.pgi_list);
TAILQ_INSERT_TAIL(&pv_page_collectlist, pvp, pvp_pgi.pgi_list);
pv_nfree -= pvp->pvp_pgi.pgi_nfree;
pvp->pvp_pgi.pgi_nfree = -1;
}
}
if (pv_page_collectlist.tqh_first == 0)
return;
for (ph = &pv_table[pv_table_npages - 1]; ph >= &pv_table[0]; ph--) {
if (ph->pv_pmap == 0)
continue;
s = splimp();
for (ppv = ph; (pv = ppv->pv_next) != 0; ) {
pvp = (struct pv_page *) trunc_page(pv);
if (pvp->pvp_pgi.pgi_nfree == -1) {
pvp = pv_page_freelist.tqh_first;
if (--pvp->pvp_pgi.pgi_nfree == 0) {
TAILQ_REMOVE(&pv_page_freelist, pvp, pvp_pgi.pgi_list);
}
npv = pvp->pvp_pgi.pgi_freelist;
#ifdef DIAGNOSTIC
if (npv == 0)
panic("pmap_collect_pv: pgi_nfree inconsistent");
#endif
pvp->pvp_pgi.pgi_freelist = npv->pv_next;
*npv = *pv;
ppv->pv_next = npv;
ppv = npv;
} else
ppv = pv;
}
splx(s);
}
for (pvp = pv_page_collectlist.tqh_first; pvp; pvp = npvp) {
npvp = pvp->pvp_pgi.pgi_list.tqe_next;
kmem_free(kernel_map, (vm_offset_t)pvp, NBPG);
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: pmap.old.h,v 1.10 1997/09/03 00:58:13 thorpej Exp $ */
/* $NetBSD: pmap.old.h,v 1.11 1997/09/03 19:07:34 thorpej Exp $ */
/*
* Copyright (c) 1987 Carnegie-Mellon University
@ -93,6 +93,21 @@ typedef struct pv_entry {
#define PV_PTPAGE 0x01 /* header: entry maps a page table page */
struct pv_page;
struct pv_page_info {
TAILQ_ENTRY(pv_page) pgi_list;
struct pv_entry *pgi_freelist;
int pgi_nfree;
};
#define NPVPPG ((NBPG - sizeof(struct pv_page_info)) / sizeof(struct pv_entry))
struct pv_page {
struct pv_page_info pvp_pgi;
struct pv_entry pvp_pv[NPVPPG];
};
/*
* bits of pmap_attributes[]
*/