2021-09-14 15:48:57 +00:00
|
|
|
/*
|
|
|
|
* memory-vi.c
|
|
|
|
*
|
|
|
|
* Created on: Aug 23, 2011
|
|
|
|
* Author: Tiberiu
|
|
|
|
*/
|
|
|
|
#include <memory-add.h>
|
|
|
|
#include <stdio.h>
|
2021-09-14 15:54:59 +00:00
|
|
|
|
2021-09-14 15:48:57 +00:00
|
|
|
/*******************************
|
|
|
|
* Data *
|
|
|
|
*******************************/
|
|
|
|
PageDirectory* CurrentDirectory;
|
|
|
|
PageDirectory* KernelDirectory;
|
|
|
|
|
2021-09-14 15:54:59 +00:00
|
|
|
void PagingEnable()
|
2021-09-14 15:48:57 +00:00
|
|
|
{
|
2021-09-14 15:54:59 +00:00
|
|
|
uint32 tmp;
|
|
|
|
asm volatile ("mov %%cr0, %0" : "=r"(tmp));
|
|
|
|
tmp |= 0x80000000;
|
|
|
|
asm volatile ("mov %0, %%cr0" : : "r"(tmp));
|
|
|
|
}
|
2021-09-14 15:48:57 +00:00
|
|
|
|
2021-09-14 15:54:59 +00:00
|
|
|
void PagingDisable()
|
|
|
|
{
|
|
|
|
uint32 tmp;
|
|
|
|
asm volatile ("mov %%cr0, %0" : "=r"(tmp));
|
|
|
|
tmp &= 0x7FFFFFFF;
|
|
|
|
asm volatile ("mov %0, %%cr0" : : "r"(tmp));
|
|
|
|
}
|
2021-09-14 15:48:57 +00:00
|
|
|
|
2021-09-14 15:54:59 +00:00
|
|
|
void PagingSwitchDirectory(PageDirectory* dir)
|
|
|
|
{
|
|
|
|
CurrentDirectory = dir;
|
|
|
|
asm volatile ("mov %0, %%cr3" : : "r"(dir->PhysicalAddr));
|
|
|
|
}
|
2021-09-14 15:48:57 +00:00
|
|
|
|
2021-09-14 15:54:59 +00:00
|
|
|
void PagingFlushTlb ()
|
|
|
|
{
|
|
|
|
uint32 tmp;
|
|
|
|
asm volatile ("mov %%cr3, %0" : "=r"(tmp));
|
|
|
|
asm volatile ("mov %0, %%cr3" : : "r" (tmp));
|
|
|
|
}
|
2021-09-14 15:48:57 +00:00
|
|
|
|
2021-09-14 15:54:59 +00:00
|
|
|
void PagingInitialize(uint32* kernelEnd)
|
|
|
|
{
|
|
|
|
// Create the kernel page directory
|
|
|
|
PageDirectory* kdir = kmalloc_a(sizeof(PageDirectory));
|
|
|
|
memset(kdir, 0, sizeof(PageDirectory));
|
2021-09-14 15:48:57 +00:00
|
|
|
|
2021-09-14 15:54:59 +00:00
|
|
|
KernelDirectory = kdir;
|
2021-09-14 15:48:57 +00:00
|
|
|
|
2021-09-14 15:54:59 +00:00
|
|
|
// Set up physical address of PDEs.
|
|
|
|
kdir->PhysicalAddr = (uint32) kdir->TablesPhysical;
|
|
|
|
|
|
|
|
// Identity map the kernel
|
|
|
|
uint32 i = 0;
|
|
|
|
while (i <= *kernelEnd + 1024)
|
|
|
|
{
|
|
|
|
PagingMapPage(i, i, PageWriteable, kdir);
|
|
|
|
i += 0x1000;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reserve the identity mapped blocks
|
|
|
|
MemPhReserveBlocks(0x0, *kernelEnd);
|
|
|
|
|
|
|
|
PagingSwitchDirectory(kdir);
|
|
|
|
PagingEnable();
|
2021-09-14 15:48:57 +00:00
|
|
|
}
|
|
|
|
|
2021-09-14 15:54:59 +00:00
|
|
|
void PagingMapPage (uint32 phys, uint32 virt, uint32 flags, PageDirectory* pd)
|
2021-09-14 15:48:57 +00:00
|
|
|
{
|
2021-09-14 15:54:59 +00:00
|
|
|
// Calculate pde and pte
|
|
|
|
uint32 pde = virt >> 22;
|
|
|
|
uint32 pte = (virt >> 12) & 0x3ff;
|
|
|
|
|
|
|
|
phys &= 0xFFFFF000; // Make sure address is page aligned
|
|
|
|
flags &= 0xFFF; // Make sure flags don't overflow
|
|
|
|
|
|
|
|
// See if page table exists
|
|
|
|
if (!pd->Tables[pde])
|
|
|
|
{
|
|
|
|
// No? allocate it
|
|
|
|
uint32 ph;
|
|
|
|
PageTable* pt = kmalloc_ap(sizeof(PageTable), &ph);
|
|
|
|
memset(pt, 0, sizeof(PageTable));
|
|
|
|
|
|
|
|
pd->Tables[pde] = pt;
|
|
|
|
pd->TablesPhysical[pde] = ph | 0x7;
|
|
|
|
}
|
2021-09-14 15:48:57 +00:00
|
|
|
|
2021-09-14 15:54:59 +00:00
|
|
|
// Set up the page
|
|
|
|
pd->Tables[pde]->Pages[pte] = phys | flags | 0x1; // Present, and flags
|
2021-09-14 15:48:57 +00:00
|
|
|
|
2021-09-14 15:54:59 +00:00
|
|
|
// If it is the current directory, flush the tlb to notice the change
|
|
|
|
if (pd == CurrentDirectory) PagingFlushTlb();
|
2021-09-14 15:48:57 +00:00
|
|
|
}
|
|
|
|
|
2021-09-14 15:54:59 +00:00
|
|
|
void PagingUnmapPage (uint32 virt, PageDirectory* pd)
|
2021-09-14 15:48:57 +00:00
|
|
|
{
|
2021-09-14 15:54:59 +00:00
|
|
|
// Calculate pde and pte
|
|
|
|
uint32 pde = virt >> 22;
|
|
|
|
uint32 pte = (virt >> 12) & 0x3ff;
|
2021-09-14 15:48:57 +00:00
|
|
|
|
2021-09-14 15:54:59 +00:00
|
|
|
if (!pd->Tables[pde] || !pd->Tables[pde]->Pages[pte]) return;
|
2021-09-14 15:48:57 +00:00
|
|
|
|
2021-09-14 15:54:59 +00:00
|
|
|
// Get physical address
|
|
|
|
uint32 phys = pd->Tables[pde]->Pages[pte] & PageFrame;
|
2021-09-14 15:48:57 +00:00
|
|
|
|
2021-09-14 15:54:59 +00:00
|
|
|
// Free page
|
|
|
|
pd->Tables[pde]->Pages[pte] = 0;
|
|
|
|
MemPhFreeBlock(phys);
|
2021-09-14 15:48:57 +00:00
|
|
|
|
2021-09-14 15:54:59 +00:00
|
|
|
// If it is the current directory, flush the tlb to notice the change
|
|
|
|
if (pd == CurrentDirectory) PagingFlushTlb();
|
2021-09-14 15:48:57 +00:00
|
|
|
}
|
|
|
|
|
2021-09-14 15:54:59 +00:00
|
|
|
uint32 PagingGetPhysical (uint32 virt, PageDirectory* pd)
|
|
|
|
{
|
|
|
|
// Calculate pde and pte
|
|
|
|
uint32 pde = virt >> 22;
|
|
|
|
uint32 pte = (virt >> 12) & 0x3ff;
|
|
|
|
|
|
|
|
// Not mapped
|
|
|
|
if (!pd->Tables[pde] || !pd->Tables[pde]->Pages[pte]) return NULL;
|
|
|
|
|
|
|
|
return (pd->Tables[pde]->Pages[pte] & PageFrame);
|
|
|
|
}
|