/* * memory-vi.c * * Created on: Aug 23, 2011 * Author: Tiberiu */ #include #include /******************************* * Data * *******************************/ PageDirectory* CurrentDirectory; PageDirectory* KernelDirectory; void PagingEnable() { uint32 tmp; asm volatile ("mov %%cr0, %0" : "=r"(tmp)); tmp |= 0x80000000; asm volatile ("mov %0, %%cr0" : : "r"(tmp)); } void PagingDisable() { uint32 tmp; asm volatile ("mov %%cr0, %0" : "=r"(tmp)); tmp &= 0x7FFFFFFF; asm volatile ("mov %0, %%cr0" : : "r"(tmp)); } void PagingSwitchDirectory(PageDirectory* dir) { CurrentDirectory = dir; asm volatile ("mov %0, %%cr3" : : "r"(dir->PhysicalAddr)); } void PagingFlushTlb () { uint32 tmp; asm volatile ("mov %%cr3, %0" : "=r"(tmp)); asm volatile ("mov %0, %%cr3" : : "r" (tmp)); } void PagingInitialize(uint32* kernelEnd) { // Create the kernel page directory PageDirectory* kdir = kmalloc_a(sizeof(PageDirectory)); memset(kdir, 0, sizeof(PageDirectory)); KernelDirectory = kdir; // 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(); } void PagingMapPage (uint32 phys, uint32 virt, uint32 flags, PageDirectory* pd) { // 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; } // Set up the page pd->Tables[pde]->Pages[pte] = phys | flags | 0x1; // Present, and flags // If it is the current directory, flush the tlb to notice the change if (pd == CurrentDirectory) PagingFlushTlb(); } void PagingUnmapPage (uint32 virt, PageDirectory* pd) { // Calculate pde and pte uint32 pde = virt >> 22; uint32 pte = (virt >> 12) & 0x3ff; if (!pd->Tables[pde] || !pd->Tables[pde]->Pages[pte]) return; // Get physical address uint32 phys = pd->Tables[pde]->Pages[pte] & PageFrame; // Free page pd->Tables[pde]->Pages[pte] = 0; MemPhFreeBlock(phys); // If it is the current directory, flush the tlb to notice the change if (pd == CurrentDirectory) PagingFlushTlb(); } 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); }