From 7de4a80489273f75fa208eedd57cac539f64f4bb Mon Sep 17 00:00:00 2001 From: Mikhail Date: Sat, 13 Jul 2024 17:10:53 -0400 Subject: [PATCH 1/2] push changes --- source/Cosmos.Core/Bootstrap.cs | 1 + source/Cosmos.Core/Paging.cs | 105 ++++++++++++++++++++++ source/Cosmos.Core_Asm/EnablePagingAsm.cs | 94 +++++++++++++++++++ 3 files changed, 200 insertions(+) create mode 100644 source/Cosmos.Core/Paging.cs create mode 100644 source/Cosmos.Core_Asm/EnablePagingAsm.cs diff --git a/source/Cosmos.Core/Bootstrap.cs b/source/Cosmos.Core/Bootstrap.cs index f2d3591fa0..728e779e3a 100644 --- a/source/Cosmos.Core/Bootstrap.cs +++ b/source/Cosmos.Core/Bootstrap.cs @@ -31,6 +31,7 @@ public static void Init() // Drag this stuff in to the compiler manually until we add the always include attrib Multiboot2.Init(); INTs.Dummy(); + Paging.Init(); PIC = new PIC(); CPU.UpdateIDT(true); diff --git a/source/Cosmos.Core/Paging.cs b/source/Cosmos.Core/Paging.cs new file mode 100644 index 0000000000..5eb2468a5d --- /dev/null +++ b/source/Cosmos.Core/Paging.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using IL2CPU.API.Attribs; + +namespace Cosmos.Core +{ + public unsafe class Paging + { + internal static uint* PageDirectory; + private static bool IsEnabled = false; + public static void Init() + { + if (IsEnabled) + { + return; + } + IsEnabled = true; + + var video = (byte*)0xB8000; + + // Setup page tables + video[0] = (byte)'A'; + video[1] = 0x0f; + + PageDirectory = (uint*)new ManagedMemoryBlock(4096, 0x400000, true).Offset; + + // identity map kernel + for (ulong i = 0x2000000; i < 0x2500000; i += 0x400000) + { + Map(i, i, PageSize._4MB, PageFlags.ReadWrite); + } + + // identity map console + Map(0xB8000, 0xB8000, PageSize._4KB, PageFlags.ReadWrite); + + // Enable paging + video[0] = (byte)'B'; + video[1] = 0x0f; + + DoEnable((uint)PageDirectory); + + // Print C for now as memory manager would need rework + video[0] = (byte)'C'; + video[1] = 0x0f; + while (true) { } + } + private static uint* GetNextLevel(uint* topLevel, ulong index, bool allocate) + { + if ((topLevel[index] & 1) != 0) + { + return (uint*)((topLevel[index] & ~((uint)0xFFF))); + } + + if (!allocate) + { + return null; + } + + var nextLevel = (uint*)new ManagedMemoryBlock(4096, 0x400000, true).Offset; + topLevel[index] = (uint)nextLevel | 3; + return nextLevel; + } + public static void Map(ulong PhysicalAddress, ulong VirtualAddress, PageSize size, PageFlags flags) + { + var pml2Entry = VirtualAddress >> 22; + var pml1Entry = (VirtualAddress >> 12) & 0x03FF; + + if (size == PageSize._4MB) + { + PageDirectory[pml2Entry] = (uint)(PhysicalAddress | ((uint)PageFlags.Present | (uint)flags | (1 << 7))); + } + else if (size == PageSize._4KB) + { + var pd = GetNextLevel(PageDirectory, pml2Entry, true); + //var pt = GetNextLevel(pd, pml1Entry, true); + pd[pml1Entry] = (uint)(PhysicalAddress | (uint)(PageFlags.Present | flags)); + } + } + + //plugged + internal static void DoEnable(uint addr) + { + throw new NotImplementedException(); + } + + internal static void RefreshPages() + { + throw new NotImplementedException(); + } + } + + public enum PageSize + { + _4MB, + _4KB, + } + [Flags] + public enum PageFlags { + Present = 1, + ReadWrite = 2, + } +} \ No newline at end of file diff --git a/source/Cosmos.Core_Asm/EnablePagingAsm.cs b/source/Cosmos.Core_Asm/EnablePagingAsm.cs new file mode 100644 index 0000000000..322142dc78 --- /dev/null +++ b/source/Cosmos.Core_Asm/EnablePagingAsm.cs @@ -0,0 +1,94 @@ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using IL2CPU.API.Attribs; +using XSharp; +using XSharp.Assembler; +using XSharp.Assembler.x86; + +namespace Cosmos.Core_Asm.Memory +{ + class EnablePagingAsm : AssemblerMethod + { + //static void DoEnable(uint addr) + //addr: EBP+8 + public override void AssembleNew(Assembler aAssembler, object aMethodInfo) + { + //EAX: adddr + XS.Set(XSRegisters.EAX, XSRegisters.EBP, sourceDisplacement: 8); + XS.Set(XSRegisters.CR3, XSRegisters.EAX); + + // Enable PSE + new Mov + { + DestinationReg = RegistersEnum.EAX, + SourceReg = RegistersEnum.CR4 + }; + + new Or() + { + DestinationReg = RegistersEnum.EAX, + SourceValue = 0x00000010 + }; + + new Mov + { + DestinationReg = RegistersEnum.CR4, + SourceReg = RegistersEnum.EAX + }; + + //Set the paging bit + new Mov + { + DestinationReg = RegistersEnum.EAX, + SourceReg = RegistersEnum.CR0 + }; + + new Or() + { + DestinationReg = RegistersEnum.EAX, + SourceValue = 0x80000001 + }; + + new Mov + { + DestinationReg = RegistersEnum.CR0, + SourceReg = RegistersEnum.EAX + }; + } + } + class RefreshPagesAsm : AssemblerMethod + { + public override void AssembleNew(Assembler aAssembler, object aMethodInfo) + { + //reload CR3 + new Mov + { + DestinationReg = RegistersEnum.EAX, + SourceReg = RegistersEnum.CR3 + }; + new Mov + { + DestinationReg = RegistersEnum.CR3, + SourceReg = RegistersEnum.EAX + }; + } + } + [Plug(Target = typeof(Core.Paging))] + public class PagingImpl + { + [PlugMethod(Assembler = typeof(EnablePagingAsm))] + public static void DoEnable(uint addr) + { + throw new NotImplementedException(); + } + [PlugMethod(Assembler = typeof(RefreshPagesAsm))] + public static void RefreshPages() + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file From 6581456dcbe38702a295a459d279c31256c484c0 Mon Sep 17 00:00:00 2001 From: Mikhail Date: Sun, 14 Jul 2024 20:40:19 -0400 Subject: [PATCH 2/2] push broken PAE enable code --- source/Cosmos.Core/Bootstrap.cs | 1 - source/Cosmos.Core/GCImplementation.cs | 1 + source/Cosmos.Core/Paging.cs | 64 ++++++++++++++--------- source/Cosmos.Core_Asm/EnablePagingAsm.cs | 8 ++- 4 files changed, 42 insertions(+), 32 deletions(-) diff --git a/source/Cosmos.Core/Bootstrap.cs b/source/Cosmos.Core/Bootstrap.cs index 728e779e3a..f2d3591fa0 100644 --- a/source/Cosmos.Core/Bootstrap.cs +++ b/source/Cosmos.Core/Bootstrap.cs @@ -31,7 +31,6 @@ public static void Init() // Drag this stuff in to the compiler manually until we add the always include attrib Multiboot2.Init(); INTs.Dummy(); - Paging.Init(); PIC = new PIC(); CPU.UpdateIDT(true); diff --git a/source/Cosmos.Core/GCImplementation.cs b/source/Cosmos.Core/GCImplementation.cs index 66b4ef5c05..f57ec7353a 100644 --- a/source/Cosmos.Core/GCImplementation.cs +++ b/source/Cosmos.Core/GCImplementation.cs @@ -99,6 +99,7 @@ public static unsafe void Init() memLength = 128 * 1024 * 1024; } RAT.Init(memPtr, (uint)memLength); + Paging.Init(); } /// /// Get the Pointer of any object needed for Free() diff --git a/source/Cosmos.Core/Paging.cs b/source/Cosmos.Core/Paging.cs index 5eb2468a5d..65b359bf95 100644 --- a/source/Cosmos.Core/Paging.cs +++ b/source/Cosmos.Core/Paging.cs @@ -3,13 +3,14 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using Cosmos.Core.Memory; using IL2CPU.API.Attribs; namespace Cosmos.Core { public unsafe class Paging { - internal static uint* PageDirectory; + internal static ulong* PageDirectoryPointerTable; private static bool IsEnabled = false; public static void Init() { @@ -20,38 +21,45 @@ public static void Init() IsEnabled = true; var video = (byte*)0xB8000; - + // Setup page tables - video[0] = (byte)'A'; + video[0] = (byte)'!'; video[1] = 0x0f; - PageDirectory = (uint*)new ManagedMemoryBlock(4096, 0x400000, true).Offset; + PageDirectoryPointerTable = (ulong*)new ManagedMemoryBlock(4 * sizeof(long), 0x20, true).Offset; // identity map kernel - for (ulong i = 0x2000000; i < 0x2500000; i += 0x400000) + for (ulong i = 0x2000000; i < 0x2500000; i += 0x200000) { - Map(i, i, PageSize._4MB, PageFlags.ReadWrite); + Map(i, i, PageSize._2MB, PageFlags.ReadWrite); + } + + // identity map RAT + for (ulong i = (ulong)RAT.mRAT; i < (ulong)RAT.HeapEnd; i += 0x200000) + { + Map(i, i, PageSize._2MB, PageFlags.ReadWrite); } // identity map console - Map(0xB8000, 0xB8000, PageSize._4KB, PageFlags.ReadWrite); + Map(0xB8000, 0xB8000, PageSize._2MB, PageFlags.ReadWrite); // Enable paging - video[0] = (byte)'B'; + video[0] = (byte)'E'; video[1] = 0x0f; - DoEnable((uint)PageDirectory); + DoEnable((uint)PageDirectoryPointerTable); // Print C for now as memory manager would need rework - video[0] = (byte)'C'; + video[0] = (byte)':'; video[1] = 0x0f; - while (true) { } + video[1] = (byte)')'; + video[2] = 0x0f; } - private static uint* GetNextLevel(uint* topLevel, ulong index, bool allocate) + private static ulong* GetNextLevel(ulong* topLevel, ulong index, bool allocate, ulong flags = 3) { if ((topLevel[index] & 1) != 0) { - return (uint*)((topLevel[index] & ~((uint)0xFFF))); + return (ulong*)((topLevel[index] & ~((ulong)0xFFF))); } if (!allocate) @@ -59,24 +67,26 @@ public static void Init() return null; } - var nextLevel = (uint*)new ManagedMemoryBlock(4096, 0x400000, true).Offset; - topLevel[index] = (uint)nextLevel | 3; + var nextLevel = (ulong*)new ManagedMemoryBlock(512 * sizeof(ulong), 0x1000, true).Offset; + topLevel[index] = (ulong)nextLevel | flags; return nextLevel; } public static void Map(ulong PhysicalAddress, ulong VirtualAddress, PageSize size, PageFlags flags) { - var pml2Entry = VirtualAddress >> 22; - var pml1Entry = (VirtualAddress >> 12) & 0x03FF; + var pdpteIndex = (VirtualAddress >> 30) & 0x03; // 2 bits for PDPT + var pdeIndex = (VirtualAddress >> 21) & 0x1FF; // 9 bits for PD + var pteIndex = (VirtualAddress >> 12) & 0x1FF; // 9 bits for PT - if (size == PageSize._4MB) + var pdpte = GetNextLevel(PageDirectoryPointerTable, pdpteIndex, true, 1); + if (size == PageSize._2MB) { - PageDirectory[pml2Entry] = (uint)(PhysicalAddress | ((uint)PageFlags.Present | (uint)flags | (1 << 7))); + pdpte[pdeIndex] = (ulong)(PhysicalAddress | ((ulong)3 | (1 << 7))); } else if (size == PageSize._4KB) { - var pd = GetNextLevel(PageDirectory, pml2Entry, true); - //var pt = GetNextLevel(pd, pml1Entry, true); - pd[pml1Entry] = (uint)(PhysicalAddress | (uint)(PageFlags.Present | flags)); + var pde = GetNextLevel(pdpte, pdeIndex, true); + var pt = GetNextLevel(pde, pteIndex, true); + pt[pteIndex] = (ulong)(PhysicalAddress | (ulong)(3)); } } @@ -94,12 +104,14 @@ internal static void RefreshPages() public enum PageSize { - _4MB, + _2MB, _4KB, } [Flags] - public enum PageFlags { - Present = 1, - ReadWrite = 2, + public enum PageFlags + { + Present = 1 << 0, + ReadWrite = 1 << 1, + Supervisor = 1 << 2 } } \ No newline at end of file diff --git a/source/Cosmos.Core_Asm/EnablePagingAsm.cs b/source/Cosmos.Core_Asm/EnablePagingAsm.cs index 322142dc78..5b492a2f79 100644 --- a/source/Cosmos.Core_Asm/EnablePagingAsm.cs +++ b/source/Cosmos.Core_Asm/EnablePagingAsm.cs @@ -13,15 +13,13 @@ namespace Cosmos.Core_Asm.Memory { class EnablePagingAsm : AssemblerMethod { - //static void DoEnable(uint addr) - //addr: EBP+8 public override void AssembleNew(Assembler aAssembler, object aMethodInfo) { - //EAX: adddr + // Set PDPTR address to cr3 from addr argument XS.Set(XSRegisters.EAX, XSRegisters.EBP, sourceDisplacement: 8); XS.Set(XSRegisters.CR3, XSRegisters.EAX); - // Enable PSE + // Enable PAE and PSE new Mov { DestinationReg = RegistersEnum.EAX, @@ -31,7 +29,7 @@ public override void AssembleNew(Assembler aAssembler, object aMethodInfo) new Or() { DestinationReg = RegistersEnum.EAX, - SourceValue = 0x00000010 + SourceValue = (1 << 5) | (1 << 4) }; new Mov