/// <summary> /// Initializes paging /// </summary> public static void Init() { // Flags PageFlags kernelFlags = PageFlags.Present | PageFlags.Writable; PageFlags usercodeFlags = PageFlags.Present | PageFlags.UserMode; PageFlags userFlags = PageFlags.Present | PageFlags.Writable | PageFlags.UserMode; // Bit array to store which frames are free bitmap = new BitArray(4096 * 1024 / 4); // Create a new page directory for the kernel // Note: At this point, virtual address == physical address due to identity mapping KernelDirectory = CreateNewDirectoryPhysically(userFlags); SetPageDirectory(KernelDirectory, KernelDirectory); // Identity map int end = (int)PhysicalMemoryManager.FirstFree(); for (int address = 0; address < end; address += 0x1000) { MapPage(KernelDirectory, address, address, kernelFlags); bitmap.SetBit(address / 0x1000); } // Usercode is a section that is code in the kernel available to usermode int usercode = (int)getUsercodeAddress(); MapPage(KernelDirectory, usercode, usercode, usercodeFlags); // Enable paging Enable(); }
/// <summary> /// Creates a new page directory using only physical memory (used in Init) /// </summary> /// <param name="flags">The flags</param> /// <returns>The page directory</returns> public static PageDirectory *CreateNewDirectoryPhysically(PageFlags flags) { // Allocate a new block of physical memory to store our physical page in PageDirectory *directory = (PageDirectory *)Heap.AlignedAlloc(0x1000, sizeof(PageDirectory)); directory->PhysicalDirectory = directory; if (directory == null) { Panic.DoPanic("directory == null"); } // Allocate the tables for (int i = 0; i < 1024; i++) { PageTable *table = (PageTable *)PhysicalMemoryManager.Alloc(); if (table == null) { Panic.DoPanic("table == null"); } Memory.Memclear(table, sizeof(PageTable)); // Note: At this point, virtual address == physical address due to identity mapping directory->PhysicalTables[i] = (int)table | (int)flags; directory->VirtualTables[i] = (int)table; } return(directory); }
/// <summary> /// Maps a physical address (range) to a free virtual address (range) /// </summary> /// <param name="directory">The page directory</param> /// <param name="phys">The physical address</param> /// <param name="size">The size of the range</param> /// <param name="flags">The flags</param> /// <returns>The virtual address</returns> public static void *MapToVirtual(PageDirectory *directory, int phys, int size, PageFlags flags) { int sizeAligned = (int)AlignUp((uint)size) / 0x1000; int free = bitmap.FindFirstFreeRange(sizeAligned, true); int virt = free * 0x1000; for (int i = 0; i < sizeAligned; i++) { int offset = i * 0x1000; MapPage(directory, phys + offset, virt + offset, flags); PhysicalMemoryManager.Set(phys + offset); } Paging.setDirectoryInternal(Paging.CurrentDirectoryPhysical); return((void *)virt); }
/// <summary> /// Frees an allocate virtual address range and marks the corresponding physical addresses as free /// </summary> /// <param name="address">The starting address</param> /// <param name="size">The size</param> public static void UnMap(void *address, int size) { // Page align size uint sizeAligned = AlignUp((uint)size); int start = (int)AlignDown((uint)address) / 0x1000; int addressStart = (int)AlignDown((uint)address); int addressEnd = addressStart + (int)sizeAligned; // Free physical memory for (int i = addressStart; i < addressEnd; i += 0x1000) { void *phys = GetPhysicalFromVirtual((void *)i); PhysicalMemoryManager.Free(phys); } // Free virtual memory bitmap.ClearRange(start, (int)(sizeAligned / 0x1000)); }
/// <summary> /// Initializes the specific x86 stuff /// </summary> public static void Init() { GDT.Init(); PIC.Remap(); IDT.Init(); IRQ.Init(); PhysicalMemoryManager.Init(); Paging.Init(); Heap.InitRealHeap(); IOApicManager.Init(); Acpi.Init(); LocalApic.InitLocalAPIC(); IOApicManager.InitIOApics(); CMOS.UpdateTime(); Time.FullTicks = Time.CalculateEpochTime(); }
/// <summary> /// Allocates a virtual address range /// </summary> /// <param name="size">The size</param> /// <returns>The pointer to the block</returns> public static void *AllocateVirtual(int size) { // Page align size uint sizeAligned = AlignUp((uint)size); // Allocate int free = bitmap.FindFirstFreeRange((int)(sizeAligned / 0x1000), true); int start = free * 0x1000; int end = (int)(start + sizeAligned); PageFlags flags = PageFlags.Present | PageFlags.Writable | PageFlags.UserMode; for (int address = start; address < end; address += 0x1000) { int phys = (int)PhysicalMemoryManager.Alloc(); MapPage(KernelDirectory, phys, address, flags); MapPage(CurrentDirectory, phys, address, flags); } // Clear the data before returning it for safety Memory.Memclear((void *)start, size); return((void *)start); }