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
|
* Page Tables
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define PGNUMMASK 0xFFFFFFFFFFFFF000ULL
|
||||||
|
|
||||||
#define PGIDXSHIFT 9
|
#define PGIDXSHIFT 9
|
||||||
#define PGIDXMASK (512 - 1)
|
#define PGIDXMASK (512 - 1)
|
||||||
|
|
||||||
|
128
sys/amd64/pmap.c
128
sys/amd64/pmap.c
@ -76,7 +76,7 @@ PMap_NewAS()
|
|||||||
AS *as = PAlloc_AllocPage();
|
AS *as = PAlloc_AllocPage();
|
||||||
|
|
||||||
if (!as)
|
if (!as)
|
||||||
return 0;
|
return NULL;
|
||||||
|
|
||||||
as->root = PAlloc_AllocPage();
|
as->root = PAlloc_AllocPage();
|
||||||
as->tables = 1;
|
as->tables = 1;
|
||||||
@ -84,7 +84,7 @@ PMap_NewAS()
|
|||||||
|
|
||||||
if (!as->root) {
|
if (!as->root) {
|
||||||
PAlloc_Release(as);
|
PAlloc_Release(as);
|
||||||
return 0;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < PAGETABLE_ENTRIES / 2; i++)
|
for (i = 0; i < PAGETABLE_ENTRIES / 2; i++)
|
||||||
@ -101,15 +101,46 @@ PMap_NewAS()
|
|||||||
void
|
void
|
||||||
PMap_DestroyAS(AS *space)
|
PMap_DestroyAS(AS *space)
|
||||||
{
|
{
|
||||||
int i;
|
// Only free the userspace portion (bottom half)
|
||||||
|
for (int i = 0; i < PAGETABLE_ENTRIES / 2; i++)
|
||||||
for (i = 0; i < PAGETABLE_ENTRIES / 2; i++)
|
|
||||||
{
|
{
|
||||||
if (space->root->entries[i] != 0) {
|
PageEntry pte = space->root->entries[i];
|
||||||
// Remove subpages
|
if (pte & PTE_P) {
|
||||||
PAlloc_Release((void *)DMPA2VA(space->root->entries[i]));
|
// 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 *
|
AS *
|
||||||
@ -159,7 +190,7 @@ PMap_Translate(AS *space, uintptr_t va)
|
|||||||
ASSERT(pte);
|
ASSERT(pte);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
table = (PageTable *)DMPA2VA(pte & 0xFFFFFFFFFFFFF000);
|
table = (PageTable *)DMPA2VA(pte & PGNUMMASK);
|
||||||
|
|
||||||
pte = table->entries[j];
|
pte = table->entries[j];
|
||||||
// XXX: Support 1GB pages
|
// XXX: Support 1GB pages
|
||||||
@ -167,7 +198,7 @@ PMap_Translate(AS *space, uintptr_t va)
|
|||||||
ASSERT(pte);
|
ASSERT(pte);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
table = (PageTable *)DMPA2VA(pte & 0xFFFFFFFFFFFFF000);
|
table = (PageTable *)DMPA2VA(pte & PGNUMMASK);
|
||||||
|
|
||||||
pte = table->entries[k];
|
pte = table->entries[k];
|
||||||
if ((pte & PTE_PS) == PTE_PS) {
|
if ((pte & PTE_PS) == PTE_PS) {
|
||||||
@ -179,7 +210,7 @@ PMap_Translate(AS *space, uintptr_t va)
|
|||||||
ASSERT(pte);
|
ASSERT(pte);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
table = (PageTable *)DMPA2VA(pte & 0xFFFFFFFFFFFFF000);
|
table = (PageTable *)DMPA2VA(pte & PGNUMMASK);
|
||||||
|
|
||||||
// Handle 4KB pages
|
// Handle 4KB pages
|
||||||
entry = &table->entries[l];
|
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;
|
pte = DMVA2PA((uint64_t)newtable) | PTE_P | PTE_W | PTE_U;
|
||||||
table->entries[i] = pte;
|
table->entries[i] = pte;
|
||||||
}
|
}
|
||||||
table = (PageTable *)DMPA2VA(pte & 0xFFFFFFFFFFFFF000);
|
table = (PageTable *)DMPA2VA(pte & PGNUMMASK);
|
||||||
|
|
||||||
pte = table->entries[j];
|
pte = table->entries[j];
|
||||||
if (size == HUGE_PGSIZE) {
|
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;
|
pte = DMVA2PA((uint64_t)newtable) | PTE_P | PTE_W | PTE_U;
|
||||||
table->entries[j] = pte;
|
table->entries[j] = pte;
|
||||||
}
|
}
|
||||||
table = (PageTable *)DMPA2VA(pte & 0xFFFFFFFFFFFFF000);
|
table = (PageTable *)DMPA2VA(pte & PGNUMMASK);
|
||||||
|
|
||||||
pte = table->entries[k];
|
pte = table->entries[k];
|
||||||
if (size == LARGE_PGSIZE) {
|
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;
|
pte = DMVA2PA((uint64_t)newtable) | PTE_P | PTE_W | PTE_U;
|
||||||
table->entries[k] = pte;
|
table->entries[k] = pte;
|
||||||
}
|
}
|
||||||
table = (PageTable *)DMPA2VA(pte & 0xFFFFFFFFFFFFF000);
|
table = (PageTable *)DMPA2VA(pte & PGNUMMASK);
|
||||||
|
|
||||||
// Handle 4KB pages
|
// Handle 4KB pages
|
||||||
ASSERT(size == PGSIZE);
|
ASSERT(size == PGSIZE);
|
||||||
@ -284,6 +315,8 @@ PMap_Unmap(AS *as, uint64_t va, uint64_t pages)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NOT_IMPLEMENTED();
|
||||||
|
|
||||||
*entry = 0;
|
*entry = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -388,7 +421,7 @@ PMap_Dump(AS *space)
|
|||||||
|
|
||||||
for (i = 0; i < PAGETABLE_ENTRIES; i++) {
|
for (i = 0; i < PAGETABLE_ENTRIES; i++) {
|
||||||
PageEntry pte = root->entries[i];
|
PageEntry pte = root->entries[i];
|
||||||
PageTable *l1 = (PageTable *)DMPA2VA(pte & 0xFFFFFFFFFFFFF000);
|
PageTable *l1 = (PageTable *)DMPA2VA(pte & PGNUMMASK);
|
||||||
|
|
||||||
if (!(pte & PTE_P))
|
if (!(pte & PTE_P))
|
||||||
continue;
|
continue;
|
||||||
@ -397,7 +430,7 @@ PMap_Dump(AS *space)
|
|||||||
|
|
||||||
for (j = 0; j < PAGETABLE_ENTRIES; j++) {
|
for (j = 0; j < PAGETABLE_ENTRIES; j++) {
|
||||||
PageEntry pte2 = l1->entries[j];
|
PageEntry pte2 = l1->entries[j];
|
||||||
PageTable *l2 = (PageTable *)DMPA2VA(pte2 & 0xFFFFFFFFFFFFF000);
|
PageTable *l2 = (PageTable *)DMPA2VA(pte2 & PGNUMMASK);
|
||||||
|
|
||||||
if (!(pte2 & PTE_P))
|
if (!(pte2 & PTE_P))
|
||||||
continue;
|
continue;
|
||||||
@ -406,7 +439,7 @@ PMap_Dump(AS *space)
|
|||||||
|
|
||||||
for (k = 0; k < PAGETABLE_ENTRIES; k++) {
|
for (k = 0; k < PAGETABLE_ENTRIES; k++) {
|
||||||
PageEntry pte3 = l2->entries[k];
|
PageEntry pte3 = l2->entries[k];
|
||||||
PageTable *l3 = (PageTable *)DMPA2VA(pte3 & 0xFFFFFFFFFFFFF000);
|
PageTable *l3 = (PageTable *)DMPA2VA(pte3 & PGNUMMASK);
|
||||||
|
|
||||||
if (!(pte3 & PTE_P))
|
if (!(pte3 & PTE_P))
|
||||||
continue;
|
continue;
|
||||||
@ -439,3 +472,64 @@ Debug_PMapDump(int argc, const char *argv[])
|
|||||||
|
|
||||||
REGISTER_DBGCMD(pmapdump, "Dump memory mappings", Debug_PMapDump);
|
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--;
|
freePages--;
|
||||||
Spinlock_Unlock(&pallocLock);
|
Spinlock_Unlock(&pallocLock);
|
||||||
|
|
||||||
|
memset(pg, 0, PGSIZE);
|
||||||
|
|
||||||
return (void *)pg;
|
return (void *)pg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,6 +196,8 @@ PAllocFreePage(void *region)
|
|||||||
{
|
{
|
||||||
FreePage *pg = (FreePage *)region;
|
FreePage *pg = (FreePage *)region;
|
||||||
|
|
||||||
|
ASSERT(((uintptr_t)region % PGSIZE) == 0);
|
||||||
|
|
||||||
LIST_INSERT_HEAD(&freeList, pg, entries);
|
LIST_INSERT_HEAD(&freeList, pg, entries);
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
@ -204,6 +208,7 @@ PAllocFreePage(void *region)
|
|||||||
PageInfo *info = PAllocGetInfo(pg);
|
PageInfo *info = PAllocGetInfo(pg);
|
||||||
ASSERT(info->refCount == 0);
|
ASSERT(info->refCount == 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
pg->magic = FREEPAGE_MAGIC_FREE;
|
pg->magic = FREEPAGE_MAGIC_FREE;
|
||||||
freePages++;
|
freePages++;
|
||||||
}
|
}
|
||||||
@ -225,6 +230,7 @@ PAlloc_Release(void *pg)
|
|||||||
PageInfo *info = PAllocGetInfo(pg);
|
PageInfo *info = PAllocGetInfo(pg);
|
||||||
|
|
||||||
Spinlock_Lock(&pallocLock);
|
Spinlock_Lock(&pallocLock);
|
||||||
|
ASSERT(info->refCount != 0);
|
||||||
info->refCount--;
|
info->refCount--;
|
||||||
if (info->refCount == 0)
|
if (info->refCount == 0)
|
||||||
PAllocFreePage(pg);
|
PAllocFreePage(pg);
|
||||||
|
Loading…
Reference in New Issue
Block a user