Free pages in PMap_Destroy and add extra assertions to catch errors in PAlloc.
This commit is contained in:
parent
3e5eeacf09
commit
e991129de9
@ -12,6 +12,8 @@
|
||||
* Page Tables
|
||||
*/
|
||||
|
||||
#define PGNUMMASK 0xFFFFFFFFFFFFF000ULL
|
||||
|
||||
#define PGIDXSHIFT 9
|
||||
#define PGIDXMASK (512 - 1)
|
||||
|
||||
|
128
sys/amd64/pmap.c
128
sys/amd64/pmap.c
@ -76,7 +76,7 @@ PMap_NewAS()
|
||||
AS *as = PAlloc_AllocPage();
|
||||
|
||||
if (!as)
|
||||
return 0;
|
||||
return NULL;
|
||||
|
||||
as->root = PAlloc_AllocPage();
|
||||
as->tables = 1;
|
||||
@ -84,7 +84,7 @@ PMap_NewAS()
|
||||
|
||||
if (!as->root) {
|
||||
PAlloc_Release(as);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < PAGETABLE_ENTRIES / 2; i++)
|
||||
@ -101,15 +101,46 @@ PMap_NewAS()
|
||||
void
|
||||
PMap_DestroyAS(AS *space)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < PAGETABLE_ENTRIES / 2; i++)
|
||||
// Only free the userspace portion (bottom half)
|
||||
for (int i = 0; i < PAGETABLE_ENTRIES / 2; i++)
|
||||
{
|
||||
if (space->root->entries[i] != 0) {
|
||||
// Remove subpages
|
||||
PAlloc_Release((void *)DMPA2VA(space->root->entries[i]));
|
||||
PageEntry pte = space->root->entries[i];
|
||||
if (pte & PTE_P) {
|
||||
// Remove sub-pages
|
||||
PageTable *tbl2 = (PageTable *)DMPA2VA(pte & PGNUMMASK);
|
||||
for (int j = 0; j < PAGETABLE_ENTRIES; j++) {
|
||||
PageEntry pte2 = tbl2->entries[j];
|
||||
if (pte2 & PTE_P) {
|
||||
PageTable *tbl3 = (PageTable *)DMPA2VA(pte2 & PGNUMMASK);
|
||||
for (int k = 0; k < PAGETABLE_ENTRIES; k++) {
|
||||
PageEntry pte3 = tbl3->entries[k];
|
||||
if (pte3 & PTE_P) {
|
||||
ASSERT((pte3 & PTE_PS) == 0); // XXX: Large pages not supported
|
||||
PageTable *tbl4 = (PageTable *)DMPA2VA(pte3 & PGNUMMASK);
|
||||
for (int l = 0; l < PAGETABLE_ENTRIES; l++) {
|
||||
PageEntry pte4 = tbl4->entries[l];
|
||||
if (pte4 & PTE_P) {
|
||||
// Free userspace page
|
||||
PAlloc_Release((void *)DMPA2VA(pte4 & PGNUMMASK));
|
||||
}
|
||||
}
|
||||
|
||||
// Free 3rd level page table page
|
||||
PAlloc_Release((void *)DMPA2VA(pte3 & PGNUMMASK));
|
||||
}
|
||||
}
|
||||
|
||||
// Free 2nd level page table page
|
||||
PAlloc_Release((void *)DMPA2VA(pte2 & PGNUMMASK));
|
||||
}
|
||||
}
|
||||
|
||||
// Free page table page
|
||||
PAlloc_Release((void *)DMPA2VA(pte & PGNUMMASK));
|
||||
}
|
||||
}
|
||||
|
||||
PAlloc_Release(space);
|
||||
}
|
||||
|
||||
AS *
|
||||
@ -159,7 +190,7 @@ PMap_Translate(AS *space, uintptr_t va)
|
||||
ASSERT(pte);
|
||||
return 0;
|
||||
}
|
||||
table = (PageTable *)DMPA2VA(pte & 0xFFFFFFFFFFFFF000);
|
||||
table = (PageTable *)DMPA2VA(pte & PGNUMMASK);
|
||||
|
||||
pte = table->entries[j];
|
||||
// XXX: Support 1GB pages
|
||||
@ -167,7 +198,7 @@ PMap_Translate(AS *space, uintptr_t va)
|
||||
ASSERT(pte);
|
||||
return 0;
|
||||
}
|
||||
table = (PageTable *)DMPA2VA(pte & 0xFFFFFFFFFFFFF000);
|
||||
table = (PageTable *)DMPA2VA(pte & PGNUMMASK);
|
||||
|
||||
pte = table->entries[k];
|
||||
if ((pte & PTE_PS) == PTE_PS) {
|
||||
@ -179,7 +210,7 @@ PMap_Translate(AS *space, uintptr_t va)
|
||||
ASSERT(pte);
|
||||
return 0;
|
||||
}
|
||||
table = (PageTable *)DMPA2VA(pte & 0xFFFFFFFFFFFFF000);
|
||||
table = (PageTable *)DMPA2VA(pte & PGNUMMASK);
|
||||
|
||||
// Handle 4KB pages
|
||||
entry = &table->entries[l];
|
||||
@ -210,7 +241,7 @@ PMapLookupEntry(AS *space, uint64_t va, PageEntry **entry, int size)
|
||||
pte = DMVA2PA((uint64_t)newtable) | PTE_P | PTE_W | PTE_U;
|
||||
table->entries[i] = pte;
|
||||
}
|
||||
table = (PageTable *)DMPA2VA(pte & 0xFFFFFFFFFFFFF000);
|
||||
table = (PageTable *)DMPA2VA(pte & PGNUMMASK);
|
||||
|
||||
pte = table->entries[j];
|
||||
if (size == HUGE_PGSIZE) {
|
||||
@ -226,7 +257,7 @@ PMapLookupEntry(AS *space, uint64_t va, PageEntry **entry, int size)
|
||||
pte = DMVA2PA((uint64_t)newtable) | PTE_P | PTE_W | PTE_U;
|
||||
table->entries[j] = pte;
|
||||
}
|
||||
table = (PageTable *)DMPA2VA(pte & 0xFFFFFFFFFFFFF000);
|
||||
table = (PageTable *)DMPA2VA(pte & PGNUMMASK);
|
||||
|
||||
pte = table->entries[k];
|
||||
if (size == LARGE_PGSIZE) {
|
||||
@ -242,7 +273,7 @@ PMapLookupEntry(AS *space, uint64_t va, PageEntry **entry, int size)
|
||||
pte = DMVA2PA((uint64_t)newtable) | PTE_P | PTE_W | PTE_U;
|
||||
table->entries[k] = pte;
|
||||
}
|
||||
table = (PageTable *)DMPA2VA(pte & 0xFFFFFFFFFFFFF000);
|
||||
table = (PageTable *)DMPA2VA(pte & PGNUMMASK);
|
||||
|
||||
// Handle 4KB pages
|
||||
ASSERT(size == PGSIZE);
|
||||
@ -284,6 +315,8 @@ PMap_Unmap(AS *as, uint64_t va, uint64_t pages)
|
||||
return false;
|
||||
}
|
||||
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
*entry = 0;
|
||||
}
|
||||
|
||||
@ -388,7 +421,7 @@ PMap_Dump(AS *space)
|
||||
|
||||
for (i = 0; i < PAGETABLE_ENTRIES; i++) {
|
||||
PageEntry pte = root->entries[i];
|
||||
PageTable *l1 = (PageTable *)DMPA2VA(pte & 0xFFFFFFFFFFFFF000);
|
||||
PageTable *l1 = (PageTable *)DMPA2VA(pte & PGNUMMASK);
|
||||
|
||||
if (!(pte & PTE_P))
|
||||
continue;
|
||||
@ -397,7 +430,7 @@ PMap_Dump(AS *space)
|
||||
|
||||
for (j = 0; j < PAGETABLE_ENTRIES; j++) {
|
||||
PageEntry pte2 = l1->entries[j];
|
||||
PageTable *l2 = (PageTable *)DMPA2VA(pte2 & 0xFFFFFFFFFFFFF000);
|
||||
PageTable *l2 = (PageTable *)DMPA2VA(pte2 & PGNUMMASK);
|
||||
|
||||
if (!(pte2 & PTE_P))
|
||||
continue;
|
||||
@ -406,7 +439,7 @@ PMap_Dump(AS *space)
|
||||
|
||||
for (k = 0; k < PAGETABLE_ENTRIES; k++) {
|
||||
PageEntry pte3 = l2->entries[k];
|
||||
PageTable *l3 = (PageTable *)DMPA2VA(pte3 & 0xFFFFFFFFFFFFF000);
|
||||
PageTable *l3 = (PageTable *)DMPA2VA(pte3 & PGNUMMASK);
|
||||
|
||||
if (!(pte3 & PTE_P))
|
||||
continue;
|
||||
@ -439,3 +472,64 @@ Debug_PMapDump(int argc, const char *argv[])
|
||||
|
||||
REGISTER_DBGCMD(pmapdump, "Dump memory mappings", Debug_PMapDump);
|
||||
|
||||
void
|
||||
PMap_DumpConcise(AS *space)
|
||||
{
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int k = 0;
|
||||
int l = 0;
|
||||
PageTable *root = space->root;
|
||||
|
||||
for (i = 0; i < PAGETABLE_ENTRIES/2; i++) {
|
||||
PageEntry pte = root->entries[i];
|
||||
PageTable *l1 = (PageTable *)DMPA2VA(pte & PGNUMMASK);
|
||||
|
||||
if (!(pte & PTE_P))
|
||||
continue;
|
||||
|
||||
for (j = 0; j < PAGETABLE_ENTRIES; j++) {
|
||||
PageEntry pte2 = l1->entries[j];
|
||||
PageTable *l2 = (PageTable *)DMPA2VA(pte2 & PGNUMMASK);
|
||||
|
||||
if (!(pte2 & PTE_P))
|
||||
continue;
|
||||
|
||||
for (k = 0; k < PAGETABLE_ENTRIES; k++) {
|
||||
PageEntry pte3 = l2->entries[k];
|
||||
PageTable *l3 = (PageTable *)DMPA2VA(pte3 & PGNUMMASK);
|
||||
|
||||
if (!(pte3 & PTE_P))
|
||||
continue;
|
||||
|
||||
if ((pte3 & PTE_PS) == 0) {
|
||||
for (l = 0; l < PAGETABLE_ENTRIES; l++) {
|
||||
PageEntry pte4 = l3->entries[l];
|
||||
|
||||
if (pte4 & PTE_P)
|
||||
kprintf("%016llx: %016llx P%c%c%c%c%c\n",
|
||||
AddrFromIJKL(i, j, k, l),
|
||||
(uint64_t)pte4,
|
||||
(pte4 & PTE_W) ? 'W' : ' ',
|
||||
(pte4 & PTE_NX) ? ' ' : 'X',
|
||||
(pte4 & PTE_U) ? 'U' : ' ',
|
||||
(pte4 & PTE_A) ? 'A' : ' ',
|
||||
(pte4 & PTE_D) ? 'D' : ' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
Debug_PMapDumpConcise(int argc, const char *argv[])
|
||||
{
|
||||
PMap_DumpConcise(currentAS[THISCPU()]);
|
||||
}
|
||||
|
||||
REGISTER_DBGCMD(pmapdumpconcise, "Dump concise memory mappings", Debug_PMapDumpConcise);
|
||||
|
||||
|
||||
|
@ -186,6 +186,8 @@ PAlloc_AllocPage()
|
||||
freePages--;
|
||||
Spinlock_Unlock(&pallocLock);
|
||||
|
||||
memset(pg, 0, PGSIZE);
|
||||
|
||||
return (void *)pg;
|
||||
}
|
||||
|
||||
@ -194,6 +196,8 @@ PAllocFreePage(void *region)
|
||||
{
|
||||
FreePage *pg = (FreePage *)region;
|
||||
|
||||
ASSERT(((uintptr_t)region % PGSIZE) == 0);
|
||||
|
||||
LIST_INSERT_HEAD(&freeList, pg, entries);
|
||||
|
||||
#ifndef NDEBUG
|
||||
@ -204,6 +208,7 @@ PAllocFreePage(void *region)
|
||||
PageInfo *info = PAllocGetInfo(pg);
|
||||
ASSERT(info->refCount == 0);
|
||||
#endif
|
||||
|
||||
pg->magic = FREEPAGE_MAGIC_FREE;
|
||||
freePages++;
|
||||
}
|
||||
@ -225,6 +230,7 @@ PAlloc_Release(void *pg)
|
||||
PageInfo *info = PAllocGetInfo(pg);
|
||||
|
||||
Spinlock_Lock(&pallocLock);
|
||||
ASSERT(info->refCount != 0);
|
||||
info->refCount--;
|
||||
if (info->refCount == 0)
|
||||
PAllocFreePage(pg);
|
||||
|
Loading…
Reference in New Issue
Block a user