diff --git a/sys/amd64/include/amd64.h b/sys/amd64/include/amd64.h index 0bd5c7a..d317ca0 100644 --- a/sys/amd64/include/amd64.h +++ b/sys/amd64/include/amd64.h @@ -12,6 +12,8 @@ * Page Tables */ +#define PGNUMMASK 0xFFFFFFFFFFFFF000ULL + #define PGIDXSHIFT 9 #define PGIDXMASK (512 - 1) diff --git a/sys/amd64/pmap.c b/sys/amd64/pmap.c index 37dc38d..f782a7b 100644 --- a/sys/amd64/pmap.c +++ b/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); + + diff --git a/sys/kern/palloc.c b/sys/kern/palloc.c index e958f6c..1944184 100644 --- a/sys/kern/palloc.c +++ b/sys/kern/palloc.c @@ -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);