diff --git a/Test.sln b/Test.sln index 11b29781f..f5490f973 100644 --- a/Test.sln +++ b/Test.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29102.190 +# Visual Studio 15 +VisualStudioVersion = 15.0.27130.2010 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{DAEF99B5-22F0-4885-B45B-9B600B857E1C}" EndProject @@ -162,10 +162,6 @@ 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 @@ -174,6 +170,14 @@ 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 @@ -535,6 +539,14 @@ 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 @@ -623,27 +635,12 @@ 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} @@ -705,6 +702,7 @@ 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} @@ -716,8 +714,6 @@ 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 f13330ca8..420536e31 100644 --- a/Tests/Cosmos.TestRunner.Full/Cosmos.TestRunner.Full.csproj +++ b/Tests/Cosmos.TestRunner.Full/Cosmos.TestRunner.Full.csproj @@ -29,9 +29,7 @@ - - diff --git a/Tests/Cosmos.TestRunner.Full/TestKernelSets.cs b/Tests/Cosmos.TestRunner.Full/TestKernelSets.cs index 7a44580ba..83ab5528e 100644 --- a/Tests/Cosmos.TestRunner.Full/TestKernelSets.cs +++ b/Tests/Cosmos.TestRunner.Full/TestKernelSets.cs @@ -15,27 +15,25 @@ 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(ProcessorTests.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); } } } diff --git a/Tests/Kernels/ProcessorTests/Kernel.cs b/Tests/Kernels/ProcessorTests/Kernel.cs deleted file mode 100644 index 93233e7b1..000000000 --- a/Tests/Kernels/ProcessorTests/Kernel.cs +++ /dev/null @@ -1,60 +0,0 @@ -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 deleted file mode 100644 index d6e0d7a18..000000000 --- a/Tests/Kernels/ProcessorTests/ProcessorTests.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - netcoreapp2.0 - True - - - - - - - - - diff --git a/source/Cosmos.Core/CPU.cs b/source/Cosmos.Core/CPU.cs index 344885d17..13a1c1a88 100644 --- a/source/Cosmos.Core/CPU.cs +++ b/source/Cosmos.Core/CPU.cs @@ -1,4 +1,3 @@ -using System; using IL2CPU.API.Attribs; namespace Cosmos.Core @@ -69,35 +68,5 @@ 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 new file mode 100644 index 000000000..28716c37d --- /dev/null +++ b/source/Cosmos.Core/ProcessorInformation.cs @@ -0,0 +1,53 @@ +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 deleted file mode 100644 index 7939f03d4..000000000 --- a/source/Cosmos.Core_Asm/CPU/CPUCanReadCPUIDAsm.cs +++ /dev/null @@ -1,33 +0,0 @@ -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 deleted file mode 100644 index 1042d2a14..000000000 --- a/source/Cosmos.Core_Asm/CPU/CPUReadCPUIDAsm.cs +++ /dev/null @@ -1,18 +0,0 @@ -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 deleted file mode 100644 index 3331d95c8..000000000 --- a/source/Cosmos.Core_Asm/CPU/CPUReadModelSpecificRegisterAsm.cs +++ /dev/null @@ -1,40 +0,0 @@ -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 deleted file mode 100644 index 9905048f7..000000000 --- a/source/Cosmos.Core_Asm/CPU/CPUReadTimestampCounterAsm.cs +++ /dev/null @@ -1,36 +0,0 @@ -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 a6f1cd993..f796e0233 100644 --- a/source/Cosmos.Core_Asm/CPUImpl.cs +++ b/source/Cosmos.Core_Asm/CPUImpl.cs @@ -1,4 +1,3 @@ -using System; using Cosmos.Core; using IL2CPU.API.Attribs; @@ -35,17 +34,5 @@ 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 new file mode 100644 index 000000000..2bd7d4c4a --- /dev/null +++ b/source/Cosmos.Core_Asm/ProcessorInformationImpl.cs @@ -0,0 +1,212 @@ +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 + } + } +}