138 lines
3.4 KiB
C
138 lines
3.4 KiB
C
/*
|
|
* memory-vi.c
|
|
*
|
|
* Created on: Aug 23, 2011
|
|
* Author: Tiberiu
|
|
*/
|
|
#include <memory-add.h>
|
|
#include <stdio.h>
|
|
/*******************************
|
|
* Data *
|
|
*******************************/
|
|
PageDirectory* CurrentDirectory;
|
|
PageDirectory* KernelDirectory;
|
|
|
|
/*******************************
|
|
* Useful routines *
|
|
*******************************/
|
|
void PagingInitialize(volatile uint32* kernel_used)
|
|
{
|
|
Log("Mem", "Virtual memory manager initialization started. End of kernel = 0x%x\n", kernel_used);
|
|
|
|
PageDirectory* kernelPd = (PageDirectory*) kmalloc_a(sizeof(PageDirectory));
|
|
memset(kernelPd, 0, sizeof(PageDirectory));
|
|
|
|
kernelPd->PhysicalAddr = (uint32)kernelPd->TablesPhysical;
|
|
KernelDirectory = kernelPd;
|
|
|
|
uint32 i;
|
|
|
|
// Map some kernel space
|
|
for (i = KERNEL_HEAP_START; i < KERNEL_HEAP_END; i+=0x1000)
|
|
PagingGetPage(i, 1, kernelPd);
|
|
|
|
// Identity map
|
|
for (i = 0; i < (volatile uint32) kernel_used + 0x1000; i+=0x1000)
|
|
MemPhAllocFrame(PagingGetPage(i, 1, kernelPd), 0, 0);
|
|
|
|
// Allocate kernel space
|
|
for (i = KERNEL_HEAP_START; i < KERNEL_HEAP_END; i+=0x1000)
|
|
MemPhAllocFrame (PagingGetPage(i, 1, kernelPd), 0, 0);
|
|
|
|
PagingSwitchPageDirectory (kernelPd);
|
|
PageDirectory* temp = PagingCloneDirectory(kernelPd);
|
|
PagingSwitchPageDirectory (temp);
|
|
}
|
|
|
|
void PagingSwitchPageDirectory (PageDirectory* dir)
|
|
{
|
|
CurrentDirectory = dir;
|
|
asm volatile ("mov %0, %%cr3":: "r"(dir->PhysicalAddr));
|
|
|
|
// Enable paging
|
|
uint32 cr0;
|
|
asm volatile ("mov %%cr0, %0": "=r"(cr0));
|
|
cr0 |= 0x80000000;
|
|
asm volatile ("mov %0, %%cr0":: "r"(cr0));
|
|
|
|
Log("Mem", "Enabled paging.\n");
|
|
}
|
|
|
|
Page* PagingGetPage(uint32 addr, uint8 make, PageDirectory* dir)
|
|
{
|
|
addr >>= 12;
|
|
|
|
uint32 tableIndex = addr >> 10;
|
|
|
|
if (dir->Tables[tableIndex])
|
|
return &dir->Tables[tableIndex]->Pages[addr&0x3ff];
|
|
|
|
else if (make)
|
|
{
|
|
uint32 temp;
|
|
dir->Tables[tableIndex] = (PageTable*)kmalloc_ap(sizeof(PageTable), &temp);
|
|
memset (dir->Tables[tableIndex], 0, 0x1000);
|
|
dir->TablesPhysical[tableIndex] = temp | 0x7;
|
|
return &dir->Tables[tableIndex]->Pages[addr&0x3ff];
|
|
}
|
|
|
|
else return 0;
|
|
}
|
|
|
|
|
|
PageTable* PagingCloneTable (PageTable* src, uint32* physAddr)
|
|
{
|
|
PageTable* tab = (PageTable*) kmalloc_ap(sizeof(PageTable), physAddr);
|
|
memset (tab, 0, sizeof(PageTable));
|
|
|
|
uint32 i;
|
|
for (i=0; i<1024; i++)
|
|
{
|
|
if (!(src->Pages[i] & PageFrame)) continue;
|
|
MemPhAllocFrame(&tab->Pages[i], 1, 0);
|
|
|
|
if (src->Pages[i] & PagePresent) tab->Pages[i] |= PagePresent;
|
|
if (src->Pages[i] & PageWriteable) tab->Pages[i] |= PageWriteable;
|
|
if (src->Pages[i] & PageUser) tab->Pages[i] |= PageUser;
|
|
if (src->Pages[i] & PageAccessed) tab->Pages[i] |= PageAccessed;
|
|
if (src->Pages[i] & PageDirty) tab->Pages[i] |= PageDirty;
|
|
|
|
PagingCopyPagePhysical (src->Pages[i] & PageFrame, tab->Pages[i] & PageFrame);
|
|
}
|
|
|
|
return tab;
|
|
}
|
|
|
|
PageDirectory* PagingCloneDirectory (PageDirectory* src)
|
|
{
|
|
uint32 phys;
|
|
PageDirectory* dir = (PageDirectory*)kmalloc_ap(sizeof(PageDirectory), &phys);
|
|
|
|
memset(dir, 0, sizeof(PageDirectory));
|
|
|
|
uint32 offset = (uint32)dir->TablesPhysical - (uint32)dir;
|
|
dir->PhysicalAddr = phys + offset;
|
|
|
|
uint32 i;
|
|
for (i = 0; i < 1024; i++)
|
|
{
|
|
if (!src->Tables[i]) continue;
|
|
|
|
if (KernelDirectory->Tables[i] == src->Tables[i])
|
|
{
|
|
// It is in the kernel, link it
|
|
dir->Tables[i] = src->Tables[i];
|
|
dir->TablesPhysical[i] = src->TablesPhysical[i];
|
|
}
|
|
else
|
|
{
|
|
// Copy the table
|
|
uint32 ph;
|
|
dir->Tables[i] = PagingCloneTable (src->Tables[i], &ph);
|
|
dir->TablesPhysical[i] = ph | 0x7;
|
|
}
|
|
}
|
|
|
|
return dir;
|
|
}
|