/* * memory-vi.c * * Created on: Aug 23, 2011 * Author: Tiberiu */ #include #include /******************************* * 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; }