From d6c421d0bd2e9a271b168fa98fcf5086fe29c643 Mon Sep 17 00:00:00 2001 From: Charles Betros Date: Tue, 27 Aug 2019 12:35:50 -0500 Subject: [PATCH] In progress branch for cpuid plugs and tests --- Test.sln | 44 ++-- .../Cosmos.TestRunner.Full.csproj | 2 + .../Cosmos.TestRunner.Full/TestKernelSets.cs | 36 +-- Tests/Kernels/ProcessorTests/Kernel.cs | 60 +++++ .../ProcessorTests/ProcessorTests.csproj | 14 ++ source/Cosmos.Core/CPU.cs | 31 +++ source/Cosmos.Core/ProcessorInformation.cs | 53 ----- .../Cosmos.Core_Asm/CPU/CPUCanReadCPUIDAsm.cs | 33 +++ source/Cosmos.Core_Asm/CPU/CPUReadCPUIDAsm.cs | 18 ++ .../CPU/CPUReadModelSpecificRegisterAsm.cs | 40 ++++ .../CPU/CPUReadTimestampCounterAsm.cs | 36 +++ source/Cosmos.Core_Asm/CPUImpl.cs | 13 ++ .../ProcessorInformationImpl.cs | 212 ------------------ 13 files changed, 290 insertions(+), 302 deletions(-) create mode 100644 Tests/Kernels/ProcessorTests/Kernel.cs create mode 100644 Tests/Kernels/ProcessorTests/ProcessorTests.csproj delete mode 100644 source/Cosmos.Core/ProcessorInformation.cs create mode 100644 source/Cosmos.Core_Asm/CPU/CPUCanReadCPUIDAsm.cs create mode 100644 source/Cosmos.Core_Asm/CPU/CPUReadCPUIDAsm.cs create mode 100644 source/Cosmos.Core_Asm/CPU/CPUReadModelSpecificRegisterAsm.cs create mode 100644 source/Cosmos.Core_Asm/CPU/CPUReadTimestampCounterAsm.cs delete mode 100644 source/Cosmos.Core_Asm/ProcessorInformationImpl.cs diff --git a/Test.sln b/Test.sln index f5490f973..11b29781f 100644 --- a/Test.sln +++ b/Test.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27130.2010 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29102.190 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{DAEF99B5-22F0-4885-B45B-9B600B857E1C}" EndProject @@ -162,6 +162,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cosmos.System.Tests", "Test EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cosmos.Kernel.Tests.DiskManager", "Tests\Kernels\Cosmos.Kernel.Tests.DiskManager\Cosmos.Kernel.Tests.DiskManager.csproj", "{BB6A5306-4C7A-4973-A48E-9FE3E683EAEC}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GuiCsKernel", "Tests\Kernels\GuiCsKernel\GuiCsKernel.csproj", "{E2F0CB6D-C054-4CCC-923B-E41690945A68}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProcessorTests", "Tests\Kernels\ProcessorTests\ProcessorTests.csproj", "{61BC9C74-10E9-407A-8A2D-6A5E282FBDE4}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -170,14 +174,6 @@ Global Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {0CDB3F6E-7971-426B-81F8-38B966A54C2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0CDB3F6E-7971-426B-81F8-38B966A54C2B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0CDB3F6E-7971-426B-81F8-38B966A54C2B}.Debug|x86.ActiveCfg = Debug|Any CPU - {0CDB3F6E-7971-426B-81F8-38B966A54C2B}.Debug|x86.Build.0 = Debug|Any CPU - {0CDB3F6E-7971-426B-81F8-38B966A54C2B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0CDB3F6E-7971-426B-81F8-38B966A54C2B}.Release|Any CPU.Build.0 = Release|Any CPU - {0CDB3F6E-7971-426B-81F8-38B966A54C2B}.Release|x86.ActiveCfg = Release|Any CPU - {0CDB3F6E-7971-426B-81F8-38B966A54C2B}.Release|x86.Build.0 = Release|Any CPU {F74A4B2B-02DA-455A-89FB-803A442B5B2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F74A4B2B-02DA-455A-89FB-803A442B5B2C}.Debug|Any CPU.Build.0 = Debug|Any CPU {F74A4B2B-02DA-455A-89FB-803A442B5B2C}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -539,14 +535,6 @@ Global {FF46829E-B612-4D36-80BE-ED04521AD91A}.Release|Any CPU.Build.0 = Release|Any CPU {FF46829E-B612-4D36-80BE-ED04521AD91A}.Release|x86.ActiveCfg = Release|Any CPU {FF46829E-B612-4D36-80BE-ED04521AD91A}.Release|x86.Build.0 = Release|Any CPU - {D0EABA08-88C9-4F7C-BCA9-361B58B20D67}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D0EABA08-88C9-4F7C-BCA9-361B58B20D67}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D0EABA08-88C9-4F7C-BCA9-361B58B20D67}.Debug|x86.ActiveCfg = Debug|Any CPU - {D0EABA08-88C9-4F7C-BCA9-361B58B20D67}.Debug|x86.Build.0 = Debug|Any CPU - {D0EABA08-88C9-4F7C-BCA9-361B58B20D67}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D0EABA08-88C9-4F7C-BCA9-361B58B20D67}.Release|Any CPU.Build.0 = Release|Any CPU - {D0EABA08-88C9-4F7C-BCA9-361B58B20D67}.Release|x86.ActiveCfg = Release|Any CPU - {D0EABA08-88C9-4F7C-BCA9-361B58B20D67}.Release|x86.Build.0 = Release|Any CPU {D21A7C6C-A696-4EC3-84EB-70700C1E3B34}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D21A7C6C-A696-4EC3-84EB-70700C1E3B34}.Debug|Any CPU.Build.0 = Debug|Any CPU {D21A7C6C-A696-4EC3-84EB-70700C1E3B34}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -635,12 +623,27 @@ Global {BB6A5306-4C7A-4973-A48E-9FE3E683EAEC}.Release|Any CPU.Build.0 = Release|Any CPU {BB6A5306-4C7A-4973-A48E-9FE3E683EAEC}.Release|x86.ActiveCfg = Release|Any CPU {BB6A5306-4C7A-4973-A48E-9FE3E683EAEC}.Release|x86.Build.0 = Release|Any CPU + {E2F0CB6D-C054-4CCC-923B-E41690945A68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E2F0CB6D-C054-4CCC-923B-E41690945A68}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E2F0CB6D-C054-4CCC-923B-E41690945A68}.Debug|x86.ActiveCfg = Debug|Any CPU + {E2F0CB6D-C054-4CCC-923B-E41690945A68}.Debug|x86.Build.0 = Debug|Any CPU + {E2F0CB6D-C054-4CCC-923B-E41690945A68}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E2F0CB6D-C054-4CCC-923B-E41690945A68}.Release|Any CPU.Build.0 = Release|Any CPU + {E2F0CB6D-C054-4CCC-923B-E41690945A68}.Release|x86.ActiveCfg = Release|Any CPU + {E2F0CB6D-C054-4CCC-923B-E41690945A68}.Release|x86.Build.0 = Release|Any CPU + {61BC9C74-10E9-407A-8A2D-6A5E282FBDE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {61BC9C74-10E9-407A-8A2D-6A5E282FBDE4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {61BC9C74-10E9-407A-8A2D-6A5E282FBDE4}.Debug|x86.ActiveCfg = Debug|Any CPU + {61BC9C74-10E9-407A-8A2D-6A5E282FBDE4}.Debug|x86.Build.0 = Debug|Any CPU + {61BC9C74-10E9-407A-8A2D-6A5E282FBDE4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {61BC9C74-10E9-407A-8A2D-6A5E282FBDE4}.Release|Any CPU.Build.0 = Release|Any CPU + {61BC9C74-10E9-407A-8A2D-6A5E282FBDE4}.Release|x86.ActiveCfg = Release|Any CPU + {61BC9C74-10E9-407A-8A2D-6A5E282FBDE4}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {0CDB3F6E-7971-426B-81F8-38B966A54C2B} = {E9CD521E-C386-466D-B5F7-A5EB19A61625} {F74A4B2B-02DA-455A-89FB-803A442B5B2C} = {DAEF99B5-22F0-4885-B45B-9B600B857E1C} {4F903492-CCA6-4FD9-A1B6-5E4CC0CE7767} = {C286932C-3F6D-47F0-BEEF-26843D1BB11B} {34AEEB7C-FD5D-4B15-A830-B429681844BD} = {C286932C-3F6D-47F0-BEEF-26843D1BB11B} @@ -702,7 +705,6 @@ Global {3DD192AF-2D72-449F-936C-ED8734225B18} = {C286932C-3F6D-47F0-BEEF-26843D1BB11B} {929EE8ED-6AD3-4442-A0C1-EC70665F2DCF} = {99192440-2DD7-4E71-B730-D44A73F46533} {FF46829E-B612-4D36-80BE-ED04521AD91A} = {E9CD521E-C386-466D-B5F7-A5EB19A61625} - {D0EABA08-88C9-4F7C-BCA9-361B58B20D67} = {E9CD521E-C386-466D-B5F7-A5EB19A61625} {D21A7C6C-A696-4EC3-84EB-70700C1E3B34} = {ECEA7778-E786-4317-90B9-A2D4427CB91C} {0DF97CAC-220B-4DAD-B397-42E394255763} = {ECEA7778-E786-4317-90B9-A2D4427CB91C} {2992AA07-E126-4EE0-B31C-D0B2ADE3393A} = {0E67EFE8-5944-4F6C-8B47-C5E06D4C79F5} @@ -714,6 +716,8 @@ Global {99E24E61-0743-47FF-AB0A-55A36C5E184C} = {52D81759-C7CC-427F-8C96-89CA10C914B5} {970C5E07-5D09-4882-949C-A8E876B22732} = {52D81759-C7CC-427F-8C96-89CA10C914B5} {BB6A5306-4C7A-4973-A48E-9FE3E683EAEC} = {29EEC029-6A2B-478A-B6E5-D63A91388ABA} + {E2F0CB6D-C054-4CCC-923B-E41690945A68} = {29EEC029-6A2B-478A-B6E5-D63A91388ABA} + {61BC9C74-10E9-407A-8A2D-6A5E282FBDE4} = {29EEC029-6A2B-478A-B6E5-D63A91388ABA} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {4418C803-277E-448F-A0A0-52788FA215AD} diff --git a/Tests/Cosmos.TestRunner.Full/Cosmos.TestRunner.Full.csproj b/Tests/Cosmos.TestRunner.Full/Cosmos.TestRunner.Full.csproj index 420536e31..f13330ca8 100644 --- a/Tests/Cosmos.TestRunner.Full/Cosmos.TestRunner.Full.csproj +++ b/Tests/Cosmos.TestRunner.Full/Cosmos.TestRunner.Full.csproj @@ -29,7 +29,9 @@ + + diff --git a/Tests/Cosmos.TestRunner.Full/TestKernelSets.cs b/Tests/Cosmos.TestRunner.Full/TestKernelSets.cs index 83ab5528e..7a44580ba 100644 --- a/Tests/Cosmos.TestRunner.Full/TestKernelSets.cs +++ b/Tests/Cosmos.TestRunner.Full/TestKernelSets.cs @@ -15,25 +15,27 @@ namespace Cosmos.TestRunner.Full // Stable kernel types: the ones that are stable and will run in AppVeyor public static IEnumerable GetStableKernelTypes() { - yield return typeof(BoxingTests.Kernel); - yield return typeof(Cosmos.Compiler.Tests.TypeSystem.Kernel); - yield return typeof(Cosmos.Compiler.Tests.Bcl.Kernel); - //yield return typeof(Cosmos.Compiler.Tests.Encryption.Kernel); - yield return typeof(Cosmos.Compiler.Tests.Exceptions.Kernel); - yield return typeof(Cosmos.Compiler.Tests.MethodTests.Kernel); - yield return typeof(Cosmos.Compiler.Tests.SingleEchoTest.Kernel); - yield return typeof(Cosmos.Kernel.Tests.Fat.Kernel); - yield return typeof(Cosmos.Kernel.Tests.IO.Kernel); - yield return typeof(SimpleStructsAndArraysTest.Kernel); - yield return typeof(Cosmos.Kernel.Tests.DiskManager.Kernel); + //yield return typeof(BoxingTests.Kernel); + //yield return typeof(Cosmos.Compiler.Tests.TypeSystem.Kernel); + //yield return typeof(Cosmos.Compiler.Tests.Bcl.Kernel); + ////yield return typeof(Cosmos.Compiler.Tests.Encryption.Kernel); + //yield return typeof(Cosmos.Compiler.Tests.Exceptions.Kernel); + //yield return typeof(Cosmos.Compiler.Tests.MethodTests.Kernel); + //yield return typeof(Cosmos.Compiler.Tests.SingleEchoTest.Kernel); + //yield return typeof(Cosmos.Kernel.Tests.Fat.Kernel); + //yield return typeof(Cosmos.Kernel.Tests.IO.Kernel); + //yield return typeof(SimpleStructsAndArraysTest.Kernel); + //yield return typeof(Cosmos.Kernel.Tests.DiskManager.Kernel); - //yield return typeof(KernelGen3.Boot); + ////yield return typeof(KernelGen3.Boot); - yield return typeof(GraphicTest.Kernel); - /* Please see the notes on the kernel itself before enabling it */ - //yield return typeof(ConsoleTest.Kernel); - /* This is a bit slow and works only because ring check is disabled to decide if leave it enabled */ - yield return typeof(MemoryOperationsTest.Kernel); + //yield return typeof(GraphicTest.Kernel); + ///* Please see the notes on the kernel itself before enabling it */ + ////yield return typeof(ConsoleTest.Kernel); + ///* This is a bit slow and works only because ring check is disabled to decide if leave it enabled */ + //yield return typeof(MemoryOperationsTest.Kernel); + + yield return typeof(ProcessorTests.Kernel); } } } diff --git a/Tests/Kernels/ProcessorTests/Kernel.cs b/Tests/Kernels/ProcessorTests/Kernel.cs new file mode 100644 index 000000000..93233e7b1 --- /dev/null +++ b/Tests/Kernels/ProcessorTests/Kernel.cs @@ -0,0 +1,60 @@ +using System; +using Sys = Cosmos.System; +using Cosmos.TestRunner; +using Cosmos.System.Graphics; +using System.Text; +using Cosmos.System.ExtendedASCII; +using Cosmos.System.ScanMaps; +using Cosmos.Core; +using System.Runtime.InteropServices; +using Cosmos.HAL; + +namespace ProcessorTests +{ + public class Kernel : Sys.Kernel + { + protected override void BeforeRun() + { + Console.WriteLine("Cosmos booted successfully. Starting Tests"); + } + + protected override void Run() + { + try + { + TestVendorNameIsNotBlank(); + TestCycleCountIsNotZero(); + TestCycleRateIsNotZero(); + + TestController.Completed(); + } + catch (Exception e) + { + mDebugger.Send("Exception occurred: " + e.Message); + mDebugger.Send(e.Message); + TestController.Failed(); + } + } + + public void TestVendorNameIsNotBlank() + { + //string vendorName = CPU.GetCPUVendorName(); + //bool isVendorNameBlank = string.IsNullOrWhiteSpace(vendorName); + //Assert.IsFalse(isVendorNameBlank, "Processor vendor name is blank."); + } + + public void TestCycleCountIsNotZero() + { + long cycleCount = CPU.GetCPUUptime(); + bool isCycleCountZero = cycleCount == 0; + Assert.IsFalse(isCycleCountZero, "Processor cycle count is zero."); + } + + public void TestCycleRateIsNotZero() + { + //long cycleRate = CPU.GetCPUCycleSpeed(); + //bool isCycleRateZero = cycleRate == 0; + //Assert.IsFalse(isCycleRateZero, "Processor cycle rate is zero."); + } + } +} diff --git a/Tests/Kernels/ProcessorTests/ProcessorTests.csproj b/Tests/Kernels/ProcessorTests/ProcessorTests.csproj new file mode 100644 index 000000000..d6e0d7a18 --- /dev/null +++ b/Tests/Kernels/ProcessorTests/ProcessorTests.csproj @@ -0,0 +1,14 @@ + + + + netcoreapp2.0 + True + + + + + + + + + diff --git a/source/Cosmos.Core/CPU.cs b/source/Cosmos.Core/CPU.cs index 13a1c1a88..344885d17 100644 --- a/source/Cosmos.Core/CPU.cs +++ b/source/Cosmos.Core/CPU.cs @@ -1,3 +1,4 @@ +using System; using IL2CPU.API.Attribs; namespace Cosmos.Core @@ -68,5 +69,35 @@ namespace Cosmos.Core mInterruptsEnabled = false; return xResult; } + + public static string GetCPUVendorName() + { + // TODO Call cpuid and parse response + int[] value = ReadCPUID(0); // 0 is vendor name + return ""; + } + + public static long GetCPUUptime() + { + // TODO Call read timestamp counter and parse response + int[] value = ReadTimestampCounter(); + // ((long)val[0] << 32) | (uint)val[1]; + return 0; + } + + public static long GetCPUCycleSpeed() + { + // TODO read cpuid response and do a bitwise and 0x0000ffff + int[] value = ReadCPUID(16); // 16 is max cycle rate + return 0; + } + + internal static int CarReadCPUID() => throw new NotImplementedException(); + + internal static int[] ReadCPUID(int type) => throw new NotImplementedException(); + + internal static int[] ReadTimestampCounter() => throw new NotImplementedException(); + + internal static int[] ReadFromModelSpecificRegister() => throw new NotImplementedException(); } } diff --git a/source/Cosmos.Core/ProcessorInformation.cs b/source/Cosmos.Core/ProcessorInformation.cs deleted file mode 100644 index 28716c37d..000000000 --- a/source/Cosmos.Core/ProcessorInformation.cs +++ /dev/null @@ -1,53 +0,0 @@ -namespace Cosmos.Core -{ - public unsafe class ProcessorInformation - { - /// - /// Returns the Processor's vendor name - /// - /// CPU Vendor name - public static string GetVendorName() - { - if (CanReadCPUID() > 0) - { - int[] raw = new int[3]; - - fixed (int* ptr = raw) - FetchCPUVendor(ptr); - - return new string(new char[] { - (char)(raw[0] >> 24), - (char)((raw[0] >> 16) & 0xff), - (char)((raw[0] >> 8) & 0xff), - (char)(raw[0] & 0xff), - (char)(raw[1] >> 24), - (char)((raw[1] >> 16) & 0xff), - (char)((raw[1] >> 8) & 0xff), - (char)(raw[1] & 0xff), - (char)(raw[2] >> 24), - (char)((raw[2] >> 16) & 0xff), - (char)((raw[2] >> 8) & 0xff), - (char)(raw[2] & 0xff), - }); - } - else - return "\0"; - } - - internal static int CanReadCPUID() => 0; //plugged - - internal static void FetchCPUVendor(int* target) { } //plugged - - /// - /// Returns the number of CPU cycles since startup of the current CPU core - /// - /// Number of CPU cycles since startup - public static long GetCycleCount() => 0; //plugged - - /// - /// Returns the number of CPU cycles per seconds - /// - /// Number of CPU cycles per seconds - public static long GetCycleRate() => 0; //plugged - } -} diff --git a/source/Cosmos.Core_Asm/CPU/CPUCanReadCPUIDAsm.cs b/source/Cosmos.Core_Asm/CPU/CPUCanReadCPUIDAsm.cs new file mode 100644 index 000000000..7939f03d4 --- /dev/null +++ b/source/Cosmos.Core_Asm/CPU/CPUCanReadCPUIDAsm.cs @@ -0,0 +1,33 @@ +using XSharp.Assembler; + +namespace Cosmos.Core_Asm +{ + public class CPUCanReadCPUIDAsm : AssemblerMethod + { + public override void AssembleNew(Assembler aAssembler, object aMethodInfo) + { + // TODO Need to move the result from EAX to the return value + /* + * pushfd + * pushfd + * xor dword [esp], 00200000h + * popfd + * pushfd + * pop eax + * xor eax, [esp] + * and eax, 00200000h + * ret + */ + //XS.Pushfd(); + //XS.Pushfd(); + //XS.Xor(XSRegisters.ESP, 0x00200000, destinationIsIndirect: true); + //XS.Popfd(); + //XS.Pushfd(); + //XS.Pop(XSRegisters.EAX); + //XS.Xor(XSRegisters.EAX, XSRegisters.ESP, destinationIsIndirect: true); + //XS.Popfd(); + //XS.And(XSRegisters.EAX, 0x00200000); + //XS.Return(); + } + } +} diff --git a/source/Cosmos.Core_Asm/CPU/CPUReadCPUIDAsm.cs b/source/Cosmos.Core_Asm/CPU/CPUReadCPUIDAsm.cs new file mode 100644 index 000000000..1042d2a14 --- /dev/null +++ b/source/Cosmos.Core_Asm/CPU/CPUReadCPUIDAsm.cs @@ -0,0 +1,18 @@ +using XSharp.Assembler; + +namespace Cosmos.Core_Asm +{ + public class CPUReadCPUIDAsm : AssemblerMethod + { + public override void AssembleNew(Assembler aAssembler, object aMethodInfo) + { + // TODO Get the type parameter from EBP+8 and move it to EAX + /* + * mov eax, 16h + * cpuid + */ + // TODO The result of cpuid will be in EDX:EAX so it will need to be moved to the return value + // Set ESI to EBP+8? + } + } +} diff --git a/source/Cosmos.Core_Asm/CPU/CPUReadModelSpecificRegisterAsm.cs b/source/Cosmos.Core_Asm/CPU/CPUReadModelSpecificRegisterAsm.cs new file mode 100644 index 000000000..3331d95c8 --- /dev/null +++ b/source/Cosmos.Core_Asm/CPU/CPUReadModelSpecificRegisterAsm.cs @@ -0,0 +1,40 @@ +using XSharp.Assembler; + +namespace Cosmos.Core_Asm +{ + public class CPUReadModelSpecificRegisterAsm : AssemblerMethod + { + public override void AssembleNew(Assembler aAssembler, object aMethodInfo) + { + /* + * ; esi register layout: (mperf_hi, mperf_lo, aperf_hi, aperf_lo) + * ; + * ; int* ptr = new int[4]; + * ; + * lea esi, ptr ;equivalent with `mov esi, &ptr` + * mov ecx, e7h + * rdmsr + * mov [esi + 4], eax + * mov [esi], edx + * mov ecx, e8h + * rdmsr + * mov [esi + 12], eax + * mov [esi + 8], edx + * xor eax, eax + * ret + */ + + //XS.Lea(XSRegisters.ESI, intname); + //XS.Set(XSRegisters.ECX, 0xe7); + //XS.Rdmsr(); + //XS.Set(XSRegisters.EAX, XSRegisters.ESI, destinationIsIndirect: true, destinationDisplacement: 4); + //XS.Set(XSRegisters.EDX, XSRegisters.ESI, destinationIsIndirect: true, destinationDisplacement: 0); + //XS.Set(XSRegisters.ECX, 0xe8); + //XS.Rdmsr(); + //XS.Set(XSRegisters.EAX, XSRegisters.ESI, destinationIsIndirect: true, destinationDisplacement: 12); + //XS.Set(XSRegisters.EDX, XSRegisters.ESI, destinationIsIndirect: true, destinationDisplacement: 8); + //XS.Xor(XSRegisters.EAX, XSRegisters.EAX); + //XS.Return(); + } + } +} \ No newline at end of file diff --git a/source/Cosmos.Core_Asm/CPU/CPUReadTimestampCounterAsm.cs b/source/Cosmos.Core_Asm/CPU/CPUReadTimestampCounterAsm.cs new file mode 100644 index 000000000..9905048f7 --- /dev/null +++ b/source/Cosmos.Core_Asm/CPU/CPUReadTimestampCounterAsm.cs @@ -0,0 +1,36 @@ +using System; +using XSharp.Assembler; + +namespace Cosmos.Core_Asm +{ + public class CPUReadTimestampCounterAsm : AssemblerMethod + { + public override void AssembleNew(Assembler aAssembler, object aMethodInfo) + { + // TODO need to move result from EDX:EAX to return value. Set ESI to EBP+8? + /* + * push eax + * push ecx + * push edx + * rdtsc + * mov [esi+4], eax + * mov [esi], edx + * pop edx + * pop ecx + * pop eax + * ret + */ + + //XS.Push(XSRegisters.EAX); + //XS.Push(XSRegisters.ECX); + //XS.Push(XSRegisters.EDX); + //XS.Rdtsc(); + //XS.Set(XSRegisters.ESI, XSRegisters.EAX, destinationIsIndirect: true, destinationDisplacement: 4); + //XS.Set(XSRegisters.ESI, XSRegisters.EDX, destinationIsIndirect: true); + //XS.Pop(XSRegisters.EDX); + //XS.Pop(XSRegisters.ECX); + //XS.Pop(XSRegisters.EAX); + //XS.Return(); + } + } +} diff --git a/source/Cosmos.Core_Asm/CPUImpl.cs b/source/Cosmos.Core_Asm/CPUImpl.cs index f796e0233..a6f1cd993 100644 --- a/source/Cosmos.Core_Asm/CPUImpl.cs +++ b/source/Cosmos.Core_Asm/CPUImpl.cs @@ -1,3 +1,4 @@ +using System; using Cosmos.Core; using IL2CPU.API.Attribs; @@ -34,5 +35,17 @@ namespace Cosmos.Core_Asm [PlugMethod(Assembler = typeof(CPUEnableINTsAsm))] public static void DoEnableInterrupts() => throw null; + + [PlugMethod(Assembler = typeof(CPUCanReadCPUIDAsm))] + public static int CanReadCPUID() => throw new NotImplementedException(); + + [PlugMethod(Assembler = typeof(CPUReadCPUIDAsm))] + public static int[] ReadCPUID(int type) => throw new NotImplementedException(); + + [PlugMethod(Assembler = typeof(CPUReadTimestampCounterAsm))] + public static int[] ReadTimestampCounter() => throw new NotImplementedException(); + + [PlugMethod(Assembler = typeof(CPUReadModelSpecificRegisterAsm))] + public static int[] ReadFromModelSpecificRegister() => throw new NotImplementedException(); } } diff --git a/source/Cosmos.Core_Asm/ProcessorInformationImpl.cs b/source/Cosmos.Core_Asm/ProcessorInformationImpl.cs deleted file mode 100644 index 2bd7d4c4a..000000000 --- a/source/Cosmos.Core_Asm/ProcessorInformationImpl.cs +++ /dev/null @@ -1,212 +0,0 @@ -using Cosmos.Core; - -using IL2CPU.API; -using IL2CPU.API.Attribs; - -using XSharp; - -namespace Cosmos.Core_Asm -{ - [Plug(Target = typeof(ProcessorInformation))] - public unsafe class ProcessorInformationImpl - { - /* The following three int*-pointers are needed for the lea instruction due to the following reason: - * When comiling, the IL-code will be translated into x86-ASM, which has specific and unique names for local variables. - * To access these local variables, I have to pass their excat name to the instruction in question. This is rather - * difficult with reflection, if these variables reside in the local function scope. For this reason, I move the - * pointer to class scope to access them quicker and more easily - */ - private static int* __cyclesrdtscptr, __raterdmsrptr, __vendortargetptr; - private static long __ticktate = -1; - - /// - /// Returns the number of CPU cycles since startup - /// - /// Number of CPU cycles - public static long GetCycleCount() - { - int[] val = new int[2]; - - fixed (int* ptr = val) - { - __cyclesrdtsc(ptr); - } - - return ((long)val[0] << 32) | (uint)val[1]; - } - - /// - /// Returns the CPU cycle rate (in cycles/µs) - /// - /// CPU cycle rate - public static long GetCycleRate() - { - if (__ticktate == -1) - { - int[] raw = new int[4]; - - fixed (int* ptr = raw) - { - __raterdmsr(ptr); - } - - ulong l1 = (ulong)__maxrate(); - ulong l2 = ((ulong)raw[0] << 32) | (uint)raw[1]; - ulong l3 = ((ulong)raw[2] << 32) | (uint)raw[3]; - - __ticktate = (long)l2; // (long)((double)l1 * l3 / l2); - } - - return __ticktate; - } - - /// - /// Copies the maximum cpu rate set by the bios at startup to the given int pointer - /// - [Inline] - private static int __maxrate() - { - /* - * mov eax, 16h - * cpuid - * and eax, ffffh - * ret - */ - - XS.Set(XSRegisters.EAX, 0x00000016); - XS.Cpuid(); - XS.And(XSRegisters.EAX, 0x0000ffff); - XS.Return(); - - return 0; - } - - /// - /// Copies the cycle count to the given int pointer - /// - [Inline] - private static void __cyclesrdtsc(int* target) - { - /* - * push eax - * push ecx - * push edx - * lea esi, target - * rdtsc - * mov [esi+4], eax - * mov [esi], edx - * pop edx - * pop ecx - * pop eax - * ret - */ - __cyclesrdtscptr = target; - - string intname = LabelName.GetStaticFieldName(typeof(CPUImpl).GetField(nameof(__cyclesrdtscptr))); - - XS.Push(XSRegisters.EAX); - XS.Push(XSRegisters.ECX); - XS.Push(XSRegisters.EDX); - XS.Lea(XSRegisters.ESI, intname); - XS.Rdtsc(); - XS.Set(XSRegisters.ESI, XSRegisters.EAX, destinationIsIndirect: true, destinationDisplacement: 4); - XS.Set(XSRegisters.ESI, XSRegisters.EDX, destinationIsIndirect: true); - XS.Push(XSRegisters.EDX); - XS.Push(XSRegisters.ECX); - XS.Push(XSRegisters.EAX); - XS.Return(); - } - - /// - /// Copies the cycle rate to the given int pointer - /// - [Inline] - private static void __raterdmsr(int* target) - { - /* - * ; esi register layout: (mperf_hi, mperf_lo, aperf_hi, aperf_lo) - * ; - * ; int* ptr = new int[4]; - * ; - * lea esi, ptr ;equivalent with `mov esi, &ptr` - * mov ecx, e7h - * rdmsr - * mov [esi + 4], eax - * mov [esi], edx - * mov ecx, e8h - * rdmsr - * mov [esi + 12], eax - * mov [esi + 8], edx - * xor eax, eax - * ret - */ - __raterdmsrptr = target; - - string intname = LabelName.GetStaticFieldName(typeof(CPUImpl).GetField(nameof(__raterdmsrptr))); - - XS.Lea(XSRegisters.ESI, intname); - XS.Set(XSRegisters.ECX, 0xe7); - XS.Rdmsr(); - XS.Set(XSRegisters.EAX, XSRegisters.ESI, destinationIsIndirect: true, destinationDisplacement: 4); - XS.Set(XSRegisters.EDX, XSRegisters.ESI, destinationIsIndirect: true, destinationDisplacement: 0); - XS.Set(XSRegisters.ECX, 0xe8); - XS.Rdmsr(); - XS.Set(XSRegisters.EAX, XSRegisters.ESI, destinationIsIndirect: true, destinationDisplacement: 12); - XS.Set(XSRegisters.EDX, XSRegisters.ESI, destinationIsIndirect: true, destinationDisplacement: 8); - XS.Xor(XSRegisters.EAX, XSRegisters.EAX); // XS.Set(XSRegisters.EAX, 0); - XS.Return(); - } - - [Inline] - internal static void FetchCPUVendor(int* target) - { - /* - * lea esi, target - * xor eax, eax - * cpuid - * mov [esi], ebx - * mov [esi + 4], edx - * mov [esi + 8], ecx - * ret - */ - __vendortargetptr = target; - - string intname = LabelName.GetStaticFieldName(typeof(CPUImpl).GetField(nameof(__vendortargetptr))); - - XS.Lea(XSRegisters.ESI, intname); // new Lea { DestinationReg = RegistersEnum.ESI, SourceRef = ElementReference.New(intname) }; - XS.Cpuid(); - XS.Set(XSRegisters.ESI, XSRegisters.EBX, destinationIsIndirect: true); - XS.Set(XSRegisters.ESI, XSRegisters.EDX, destinationIsIndirect: true, destinationDisplacement: 4); - XS.Set(XSRegisters.ESI, XSRegisters.ECX, destinationIsIndirect: true, destinationDisplacement: 8); - XS.Return(); - } - - [Inline] - internal static int CanReadCPUID() - { - /* - * pushfd - * pushfd - * xor dword [esp], 00200000h - * popfd - * pushfd - * pop eax - * xor eax, [esp] - * and eax, 00200000h - * ret - */ - XS.Pushfd(); - XS.Pushfd(); - XS.Xor(XSRegisters.ESP, 0x00200000, destinationIsIndirect: true); - XS.Popfd(); - XS.Pushfd(); - XS.Pop(XSRegisters.EAX); - XS.Xor(XSRegisters.EAX, XSRegisters.ESP, destinationIsIndirect: true); - XS.Popfd(); - XS.And(XSRegisters.EAX, 0x00200000); - XS.Return(); - - return 0; // should be ignored by the compiler - } - } -}