luxos/Kernel/memory/mem-paging.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;
}