#include <mm/vmm.h>
#include <sys/io.h>
#include <ubixos/kpanic.h>
#include <lib/kprintf.h>
#include <lib/kmalloc.h>
#include <ubixos/vitals.h>
#include <ubixos/spinlock.h>
#include <assert.h>
int numPages = 0;
mMap *mmUsedPages;
uInt32 freePages = 0, usedPages = 0;
uInt32 z = 0, memStart = 0;
uInt32 countMemory();
void
mmFreeTaskPages(kTask_t *task)
{
/* just move the list to tail of the free page list */
if(task->FirstPage != NULL)
{
mmFreePages->Last->Next = task->FirstPage;
task->FirstPage->Previous = mmFreePages->Last;
mmFreePages->Last = task->LastPage;
kprintf("mmFreeTaskPages: Memory has been wiped\n");
}
else
kprintf("mmFreeTaskPages: Nothing to free!\n");
return;
}
void
mmFreeVirtualPage(kTask_t *task, uInt32 memAddr)
{
mMap *tmp, *tmp2;
for(tmp = task->FirstPage ; tmp != NULL ; tmp = tmp->Next)
{
if(tmp->pageAddr == memAddr)
{
freePages++;
/* remove the page from the task's used list */
if(tmp == task->FirstPage)
{
task->FirstPage = task->FirstPage->Next;
}
else
{
tmp->Previous->Next = tmp->Next;
tmp->Next->Previous = tmp->Previous;
tmp->Next = NULL;
tmp->Previous = NULL;
}
/* add the page to the end free pages list */
mmFreePages->Last->Next = tmp;
tmp->Previous = mmFreePages->Last;
mmFreePages->Last = tmp;
/* free contiguous blocks */
if(tmp->Link != NULL)
{
kprintf("Freeing contiguous memory\n");
for(tmp2 = tmp->Link ; tmp2 != NULL ; tmp2 = tmp2->Link)
{
mmFreePages->Last->Next = tmp2;
tmp2->Previous = mmFreePages->Last;
mmFreePages->Last = tmp2;
}
}
kprintf("mmFreeVirtualPage: %d has been freed\n", memAddr);
return;
}
}
kpanic("mmFreeVirtualPage: attempted to free non-existant page\n");
return;
}
void *
mmGetFreeVirtualPage(kTask_t *task)
{
mMap *tmp, *tmpMap;
z++;
freePages--;
kprintf("%d:%d - [%x]\n", z, numPages, tmpMap->pageAddr);
if(mmFreePages == NULL)
{
mmFreePages = (mMap *)(z * 4096);
mmFreePages->First = mmFreePages;
mmFreePages->Last = mmFreePages;
mmFreePages->Next = NULL;
mmFreePages->Previous = NULL;
mmFreePages->pageAddr = z * 4096;
mmFreePages->physicalAddr = z * 4096;
}
else
{
tmpMap = (mMap *)(z * 4096);
mmFreePages->Last->Next = tmpMap;
tmpMap->Previous = mmFreePages->Last;
mmFreePages->Last = tmpMap;
tmpMap->pageAddr = z * 4096;
tmpMap->physicalAddr = z * 4096;
}
// remove the first page from the list and return it //
tmp = mmFreePages->First;
mmFreePages->First = mmFreePages->First->Next;
mmFreePages->First->Previous = NULL;
return tmp;
}
int
vmmMemMapInit()
{
uInt32 memStart;
mMap *tmpMap;
/* Count System Memory */
numPages = countMemory();
freePages = numPages;
/* calculate the start of memory */
memStart = 0x101;
memStart += (((sizeof(mMap) * numPages) + (sizeof(mMap) - 1)) / 0x1000);
/* initialize free pages */
kprintf("Initializing memory memStart = [%x]\n", memStart);
/* initialize used pages (kernel space) */
for(z = 0 ; z < memStart; z++)
{
if(mmUsedPages == NULL)
{
mmUsedPages = (mMap *)(z * 4096);
mmUsedPages->First = mmUsedPages;
mmUsedPages->Last = mmUsedPages;
mmUsedPages->Next = NULL;
mmUsedPages->Previous = NULL;
mmUsedPages->pageAddr = z * 4096;
mmUsedPages->physicalAddr = z * 4096;
}
else
{
mmUsedPages = (mMap *)(z * 4096);
mmUsedPages->Last->Next = tmpMap;
tmpMap->Previous = mmUsedPages->Last;
mmUsedPages->Last = tmpMap;
tmpMap->pageAddr = z * 4096;
tmpMap->physicalAddr = z * 4096;
}
freePages--;
usedPages++;
}
z++;
/* Print Out Memory Information */
kprintf("Real Memory: %iMB\n", ((numPages * 4096) / 1024) / 1024 );
kprintf("Available Memory: %iMB\n", ((freePages * 4096) / 1024) / 1024 );
kprintf("Used Memory: %iMB\n", ((usedPages * 4096) / 1024) / 1024 );
/* Return */
return (0);
}
uInt32 countMemory()
{
register uInt32 *mem = 0x0;
unsigned long memCount = -1, tempMemory = 0x0;
unsigned short memKb = 0;
uInt8 irq1State, irq2State;
unsigned long cr0 = 0x0;
/*
* Save The States Of Both IRQ 1 And 2 So We Can Turn Them Off And Restore
* Them Later
*/
irq1State = inportByte(0x21);
irq2State = inportByte(0xA1);
/* Turn Off IRQ 1 And 2 To Prevent Chances Of Faults While Examining Memory */
outportByte(0x21, 0xFF);
outportByte(0xA1, 0xFF);
/* Save The State Of Register CR0 */
asm volatile (
"movl %%cr0, %%ebx\n"
: "=a" (cr0)
:
: "ebx"
);
asm volatile ("wbinvd");
asm volatile (
"movl %%ebx, %%cr0\n"
:
: "a" (cr0 | 0x00000001 | 0x40000000 | 0x20000000)
: "ebx"
);
while (memKb < 4096 && memCount != 0)
{
memKb++;
if (memCount == -1)
memCount = 0;
memCount += 1024 * 1024;
mem = (uInt32 *)memCount;
tempMemory = *mem;
*mem = 0x55AA55AA;
asm("": : :"memory");
if (*mem != 0x55AA55AA)
memCount = 0;
else
{
*mem = 0xAA55AA55;
asm("": : :"memory");
if (*mem != 0xAA55AA55)
memCount = 0;
}
asm("": : :"memory");
*mem = tempMemory;
}
asm volatile (
"movl %%ebx, %%cr0\n"
:
: "a" (cr0)
: "ebx"
);
/* Restore States For Both IRQ 1 And 2 */
outportByte(0x21, irq1State);
outportByte(0xA1, irq2State);
/* Return Amount Of Memory In Pages */
return ((memKb * 1024 * 1024) / 4096);
}