[BUG] Problem with stack during paging init

This commit is contained in:
Adrien Bourmault 2020-01-16 00:08:04 +01:00
parent 25b5eb6c78
commit de43801a48
3 changed files with 67 additions and 103 deletions

View File

@ -42,8 +42,9 @@ typedef struct AllocatedPage_t{
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
ulong MmAllocPageFrame(void ***frameListPtr, size_t *pageNumber, size_t size, bool contiguous); ulong MmAllocPageFrameEx(void ***frameListPtr, size_t *pageNumber, size_t size, bool contiguous);
void MmFreePageFrame(ulong id); ulong MmAllocPageFrame(size_t size, bool contiguous);
void MmFreePageFrame(ulong id);
error_t MmTestBusyPage(void); error_t MmTestBusyPage(void);

View File

@ -60,7 +60,7 @@ void MmInitPaging(void)
pdpe_t *MmPDP = NULL; pdpe_t *MmPDP = NULL;
pde_t *MmPD = NULL; pde_t *MmPD = NULL;
pte_t *MmPT = NULL; pte_t *MmPT = NULL;
ulong index, xedni; register ulong index, xedni;
ulong firstDirectoryAddr = 0; ulong firstDirectoryAddr = 0;
ulong lastDirectoryAddr = 0; ulong lastDirectoryAddr = 0;
ulong phDirSize = 0; ulong phDirSize = 0;
@ -74,19 +74,18 @@ void MmInitPaging(void)
MmPhysLastKernAddress = (ulong)(_heap_start + _heap_max); MmPhysLastKernAddress = (ulong)(_heap_start + _heap_max);
ulong diffKernUsr = (ulong)USERSPACE - MmPhysLastKernAddress - KPAGESIZE; ulong diffKernUsr = (ulong)USERSPACE - MmPhysLastKernAddress - KPAGESIZE;
// Size of physical table
phDirSize = (((phRamSize + KPAGESIZE) / KPAGESIZE)*sizeof(ulong));
// Maximum VIRTUAL address in memory // Maximum VIRTUAL address in memory
MmVirtLastAddress = phRamSize + diffKernUsr; MmVirtLastAddress = phRamSize + diffKernUsr;
//DebugLog("\tPaging gap : %u MB (%p)\n\tLast virtual address %p\n", diffKernUsr / MB, diffKernUsr, MmVirtLastAddress); // Alloc structures
memzero((void *)&MmPageMapLevel4[0], 512*sizeof(ulong));
KalAllocMemoryEx(&MmPhysicalPageTable, phDirSize, M_ZEROED, KPAGESIZE);
memzero((void *)&MmPageMapLevel4[0], sizeof(MmPageMapLevel4)); for (register ulong curAddrPML4 = 0;
phDirSize = ((phRamSize / KPAGESIZE)*sizeof(ulong) + KPAGESIZE) & ( ~((KPAGESIZE - 1) | NX)); curAddrPML4 < phRamSize;
MmPhysicalPageTable = (ulong*)malloc(phDirSize);
//DebugLog("\t\tRam %u MB, pagesize %u KB, size %u MB\n", phRamSize / MB, KPAGESIZE / KB, phDirSize / MB);
for (ulong curAddrPML4 = 0;
curAddrPML4 < MmVirtLastAddress;
curAddrPML4 += ((ulong)KPAGESIZE * 0x8000000)) { curAddrPML4 += ((ulong)KPAGESIZE * 0x8000000)) {
// Create an entry in PML4 each 512GB // Create an entry in PML4 each 512GB
// 0x8000000 = 512 ^ 3 // 0x8000000 = 512 ^ 3
@ -102,9 +101,9 @@ void MmInitPaging(void)
//DebugLog("\t\t\t\tPDP %d : %p\n", index, MmPDP); //DebugLog("\t\t\t\tPDP %d : %p\n", index, MmPDP);
MmPageMapLevel4[index] = (pdpe_t *)((ulong)MmPDP | PRESENT | READWRITE); MmPageMapLevel4[index] = (pdpe_t *)((ulong)MmPDP | PRESENT | READWRITE);
for (ulong curAddrPDP = curAddrPML4; for (register ulong curAddrPDP = curAddrPML4;
curAddrPDP < (curAddrPML4 + ((ulong)KPAGESIZE * 0x8000000)) && curAddrPDP < (curAddrPML4 + ((ulong)KPAGESIZE * 0x8000000)) &&
curAddrPDP < MmVirtLastAddress; curAddrPDP < phRamSize;
curAddrPDP += ((ulong)KPAGESIZE * 0x40000)) { curAddrPDP += ((ulong)KPAGESIZE * 0x40000)) {
// Create an intry in PDP each 1GB // Create an intry in PDP each 1GB
// 0x40000 = 512 ^ 2 // 0x40000 = 512 ^ 2
@ -116,9 +115,9 @@ void MmInitPaging(void)
//DebugLog("\t\t\t\tPD %d : %p\n", index, MmPD); //DebugLog("\t\t\t\tPD %d : %p\n", index, MmPD);
MmPDP[index] = (pde_t *)((ulong)MmPD | PRESENT | READWRITE); MmPDP[index] = (pde_t *)((ulong)MmPD | PRESENT | READWRITE);
for (ulong curAddrPD = curAddrPDP; for (register ulong curAddrPD = curAddrPDP;
curAddrPD < (curAddrPDP + ((ulong)KPAGESIZE * 0x40000)) && curAddrPD < (curAddrPDP + ((ulong)KPAGESIZE * 0x40000)) &&
curAddrPD < MmVirtLastAddress; curAddrPD < phRamSize;
curAddrPD += ((ulong)KPAGESIZE * 0x200)) { curAddrPD += ((ulong)KPAGESIZE * 0x200)) {
// Create an intry in PD each 2MB // Create an intry in PD each 2MB
// 0x200 = 512 // 0x200 = 512
@ -130,16 +129,17 @@ void MmInitPaging(void)
//DebugLog("\t\t\t\tPT %d : %p\n", index, MmPT); //DebugLog("\t\t\t\tPT %d : %p\n", index, MmPT);
MmPD[index] = (pte_t *)((ulong)MmPT | PRESENT | READWRITE); MmPD[index] = (pte_t *)((ulong)MmPT | PRESENT | READWRITE);
for (ulong curAddrPT = curAddrPD; for (register ulong curAddrPT = curAddrPD;
curAddrPT < (curAddrPD + ((ulong)KPAGESIZE * 0x200)) && curAddrPT < (curAddrPD + ((ulong)KPAGESIZE * 0x200)) &&
curAddrPT < MmVirtLastAddress; curAddrPT < phRamSize;
curAddrPT += (ulong)KPAGESIZE) { curAddrPT += (ulong)KPAGESIZE) {
// Create an entry in PT each page of 4KB // Create an entry in PT each page of 4KB
index = (curAddrPT / ((ulong)KPAGESIZE)) % 512; index = (curAddrPT / ((ulong)KPAGESIZE)) % 512;
xedni = (curAddrPT / ((ulong)KPAGESIZE)); xedni = (curAddrPT / ((ulong)KPAGESIZE));
//DebugLog("\t\t\t\tPage %d : %p\n", index, curAddrPT); if (curAddrPT == 0x973db000)
DebugLog("\t\t\t\tPage %d : %p\n", index, curAddrPT);
// STACK GUARD PAGE */ // STACK GUARD PAGE */
if ((ulong)curAddrPT == (ulong)BtLoaderInfo.stackEndAddr) { if ((ulong)curAddrPT == (ulong)BtLoaderInfo.stackEndAddr) {
@ -181,21 +181,13 @@ void MmInitPaging(void)
//DebugLog("\tLast page of kernel at %p\n", curAddrPT); //DebugLog("\tLast page of kernel at %p\n", curAddrPT);
} }
} }
/* // While we're inside the userspace pages */
/* else if ((ulong)curAddrPT >= USERSPACE) { */
/* MmPT[index] = ((ulong)curAddrPT - diffKernUsr) | PRESENT; // Not present for instance */
/* xedni = (((ulong)curAddrPT - diffKernUsr) / ((ulong)KPAGESIZE)); */
/* //MmPhysicalPageTable[xedni] = (ulong)curAddrPT; */
/* if ((ulong)curAddrPT == USERSPACE) { */
/* DebugLog("\tUserspace at %p:%p\n", curAddrPT, curAddrPT - diffKernUsr); */
/* } */
/* } */
else { else {
MmPT[index] = 0; MmPT[index] = 0;
MmPhysicalPageTable[xedni] = 0;
} }
KeFlushTlbSingle(curAddrPT); KeFlushTlbSingle(curAddrPT);
asm ("");
} }
} }
} }
@ -294,6 +286,9 @@ void MmMapPage(void* virtualAddr, void* physicalAddr, ulong flags)
] = (ulong)virtualAddr; ] = (ulong)virtualAddr;
KeFlushTlbSingle(*page); KeFlushTlbSingle(*page);
if (virtualAddr > MmVirtLastAddress)
MmVirtLastAddress = virtualAddr;
} }
// //

View File

@ -29,6 +29,7 @@
#include <mm/palloc.h> #include <mm/palloc.h>
#include <mm/map.h> #include <mm/map.h>
#include <io/vga.h> #include <io/vga.h>
#include <ke/time.h>
//--------- //---------
@ -42,6 +43,9 @@ static AllocatedPage_t busyPagesList = { (void*)0, 0, (AllocatedPage_t*)0 };
extern MemoryMap_t memoryMap; extern MemoryMap_t memoryMap;
extern ulong MmPhysLastKernAddress; extern ulong MmPhysLastKernAddress;
static ulong NSuccessfulAlloc = 0;
static ulong NSuccessfulFree = 0;
//--------- //---------
static bool isPageBusy(void *phyPageAddr) static bool isPageBusy(void *phyPageAddr)
@ -120,7 +124,7 @@ static void removePageFromBusyList(void *phyPageAddr)
// //
// Returns an id to identify a page frame allocated (kernel) // Returns an id to identify a page frame allocated (kernel)
// //
ulong MmAllocPageFrame(void ***frameListPtr, size_t *pageNumber, size_t size, bool contiguous) ulong MmAllocPageFrameEx(void ***frameListPtr, size_t *pageNumber, size_t size, bool contiguous)
{ {
static ulong id = 0; static ulong id = 0;
*pageNumber = (((ulong)size - 1) / KPAGESIZE) + 1; *pageNumber = (((ulong)size - 1) / KPAGESIZE) + 1;
@ -135,7 +139,7 @@ ulong MmAllocPageFrame(void ***frameListPtr, size_t *pageNumber, size_t size, bo
// Maximum PHYSICAL address in memory // Maximum PHYSICAL address in memory
ulong phRamSize = memoryMap.freeRamSize + memoryMap.nonfreeRamSize; ulong phRamSize = memoryMap.freeRamSize + memoryMap.nonfreeRamSize;
DebugLog("Allocating %d pages...\n", *pageNumber); //DebugLog("Allocating %d pages...\n", *pageNumber);
for (void *curPage = (void*)(MmPhysLastKernAddress + KPAGESIZE); curPage < (void*)phRamSize; curPage += KPAGESIZE) { for (void *curPage = (void*)(MmPhysLastKernAddress + KPAGESIZE); curPage < (void*)phRamSize; curPage += KPAGESIZE) {
if (!isPageBusy(curPage)) { if (!isPageBusy(curPage)) {
@ -153,28 +157,47 @@ ulong MmAllocPageFrame(void ***frameListPtr, size_t *pageNumber, size_t size, bo
curNumber = 0; curNumber = 0;
} }
if (curNumber != *pageNumber) {
KeStartPanic("MmAllocPageFrameEx() : No more free pages to allocate");
}
for (size_t i = 0; i < *pageNumber; i++) { for (size_t i = 0; i < *pageNumber; i++) {
addPageToBusyList((*frameListPtr)[i], id); addPageToBusyList((*frameListPtr)[i], id);
//DebugLog("Allocating page : %p\n", *frameListPtr[i]); //DebugLog("Allocating page : %p\n", *frameListPtr[i]);
} }
NSuccessfulAlloc++;
return id; return id;
} }
ulong MmAllocPageFrame(size_t size, bool contiguous)
{
void **ptr = NULL;
ulong d = 0;
return MmAllocPageFrameEx(&ptr, &d, size, contiguous);
}
// //
// Frees a page frame by its id // Frees a page frame by its id
// //
void MmFreePageFrame(ulong id) void MmFreePageFrame(ulong id)
{ {
AllocatedPage_t *busyPage = &busyPagesList; AllocatedPage_t *busyPage = &busyPagesList;
bool success = false;
while(busyPage->next) { while(busyPage->next) {
busyPage = busyPage->next; busyPage = busyPage->next;
if (id == busyPage->id) { if (id == busyPage->id) {
removePageFromBusyList(busyPage->phyAddress); removePageFromBusyList(busyPage->phyAddress);
success = true;
} }
} }
if (success)
NSuccessfulFree++;
} }
// //
@ -196,7 +219,7 @@ error_t MmMapPageFrame(ulong id, void *virtAddr, ulong flags)
if (id == busyPage->id) { if (id == busyPage->id) {
MmMapPage((void*)((ulong)virtAddr + offset), busyPage->phyAddress, flags); MmMapPage((void*)((ulong)virtAddr + offset), busyPage->phyAddress, flags);
DebugLog("Map %p at %p\n", busyPage->phyAddress, virtAddr + offset); //DebugLog("Map %p at %p\n", busyPage->phyAddress, virtAddr + offset);
offset += KPAGESIZE; offset += KPAGESIZE;
} }
} }
@ -216,7 +239,7 @@ error_t MmUnmapPageFrame(ulong id)
//DebugLog("Physical : %p is %p\n", busyPage->phyAddress, actualPhys); //DebugLog("Physical : %p is %p\n", busyPage->phyAddress, actualPhys);
if (actualPhys && id == busyPage->id) { if (actualPhys && id == busyPage->id) {
DebugLog("Unmap %p from %p\n", busyPage->phyAddress, MmTransPhyToVirtAddr(busyPage->phyAddress)); //DebugLog("Unmap %p from %p\n", busyPage->phyAddress, MmTransPhyToVirtAddr(busyPage->phyAddress));
MmUnmapPage(MmTransPhyToVirtAddr(busyPage->phyAddress)); MmUnmapPage(MmTransPhyToVirtAddr(busyPage->phyAddress));
} }
} }
@ -226,79 +249,24 @@ error_t MmUnmapPageFrame(ulong id)
error_t MmTestBusyPage(void) error_t MmTestBusyPage(void)
{ {
DebugLog("\nBusy pages\n"); ulong tab[2000] = {0};
printBusyPages(); int j = 0;
for (int i = 0; i < 2000; i++) {
if (rand() %2) {
if (rand() %2) {
tab[j++] = MmAllocPageFrame(rand()%65536, NORMAL);
} else {
tab[j++] = MmAllocPageFrame(rand()%65536, CONTIGUOUS);
}
} else {
MmFreePageFrame(tab[rand() % (j+1)]);
}
}
void **ptr = NULL; //printBusyPages();
size_t n = 0;
ulong id1 = MmAllocPageFrame(&ptr, &n, 6677, NORMAL);
DebugLog("Alloc 6677 bytes : %p, %d pages, first at %p\n", ptr, n, ptr[0]);
void **ptr2 = NULL; DebugLog("Alloc : %d; Free : %d\n", NSuccessfulAlloc, NSuccessfulFree);
size_t n2 = 0;
ulong id2 = MmAllocPageFrame(&ptr2, &n2, 9045, NORMAL);
DebugLog("Alloc 9045 bytes: %p, %d pages, first at %p\n", ptr2, n2, ptr2[0]);
void **ptr3 = NULL;
size_t n3 = 0;
ulong id3 = MmAllocPageFrame(&ptr3, &n3, 1200, NORMAL);
DebugLog("Alloc 1200 bytes: %p, %d pages, first at %p\n", ptr3, n3, ptr3[0]);
void **ptr4 = NULL;
size_t n4 = 0;
ulong id4 = MmAllocPageFrame(&ptr4, &n4, 4096, NORMAL);
DebugLog("Alloc 4096 bytes: %p, %d pages, first at %p\n", ptr4, n4, ptr4[0]);
void **ptr5 = NULL;
size_t n5 = 0;
ulong id5 = MmAllocPageFrame(&ptr5, &n5, 4097, NORMAL);
DebugLog("Alloc 4097 bytes: %p, %d pages, first at %p\n", ptr5, n5, ptr5[0]);
printBusyPages();
MmFreePageFrame(id1);
MmFreePageFrame(id3);
DebugLog("Free 6677 and 1200 bytes\n");
void **ptr6 = NULL;
size_t n6 = 0;
ulong id6 = MmAllocPageFrame(&ptr6, &n6, 10000, NORMAL);
DebugLog("Alloc 10000 bytes: %p, %d pages, first at %p\n", ptr6, n6, ptr6[0]);
printBusyPages();
MmFreePageFrame(id6);
DebugLog("Free 10000 bytes\n");
printBusyPages();
void **ptr7 = NULL;
size_t n7 = 0;
ulong id7 = MmAllocPageFrame(&ptr7, &n7, 10000, CONTIGUOUS);
DebugLog("Alloc 10000 bytes contiguous: %p, %d pages, first at %p\n", ptr7, n7, ptr7[0]);
printBusyPages();
MmFreePageFrame(id1);
MmFreePageFrame(id2);
MmFreePageFrame(id3);
MmFreePageFrame(id4);
MmFreePageFrame(id5);
MmFreePageFrame(id6);
MmFreePageFrame(id7);
DebugLog("Free all bytes\n");
printBusyPages();
id1 = MmAllocPageFrame(&ptr, &n, 1*MB, NORMAL);
error_t err = MmMapPageFrame(id1, (void*)USERSPACE, PRESENT | USERMODE | READWRITE);
if (err == EOK)
DebugLog("Map status : OK\n");
if (err == EADDRINUSE)
DebugLog("Map status : NOK\n");
MmUnmapPageFrame(id1);
return EOK; return EOK;
} }