mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-24 12:35:31 +00:00
Merge pull request #1527 from CosmosOS/feature/memory_map
Added CPU.GetMemoryMap
This commit is contained in:
commit
cff35bf877
6 changed files with 152 additions and 29 deletions
|
|
@ -22,6 +22,8 @@ namespace ProcessorTests
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
TestMultibootMemoryMap();
|
||||||
|
TestGetRam();
|
||||||
TestVendorNameIsNotBlank();
|
TestVendorNameIsNotBlank();
|
||||||
TestCycleCount();
|
TestCycleCount();
|
||||||
TestCycleRateIsNotZero();
|
TestCycleRateIsNotZero();
|
||||||
|
|
@ -37,6 +39,22 @@ namespace ProcessorTests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void TestGetRam()
|
||||||
|
{
|
||||||
|
Assert.IsTrue(CPU.GetAmountOfRAM() > 0, "CPU.GetAmountOfRAM() returns a positive value: " + CPU.GetAmountOfRAM());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TestMultibootMemoryMap()
|
||||||
|
{
|
||||||
|
var memoryMap = CPU.GetMemoryMap();
|
||||||
|
for (int i = 0; i < memoryMap.Length; i++)
|
||||||
|
{
|
||||||
|
mDebugger.Send($"Memory Map: {memoryMap[i].Address} " +
|
||||||
|
$"Length: {memoryMap[i].Length} Type: {memoryMap[i].Type}");
|
||||||
|
}
|
||||||
|
Assert.IsTrue(memoryMap.Length != 0, "Memory Map is not empty! Length " + memoryMap.Length);
|
||||||
|
}
|
||||||
|
|
||||||
public void TestMultiboot()
|
public void TestMultiboot()
|
||||||
{
|
{
|
||||||
Assert.IsTrue(Multiboot.GetMBIAddress() != 0, $"Multiboot.GetMBIAddress works {Multiboot.GetMBIAddress()}");
|
Assert.IsTrue(Multiboot.GetMBIAddress() != 0, $"Multiboot.GetMBIAddress works {Multiboot.GetMBIAddress()}");
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
namespace Cosmos.Core
|
using Cosmos.Debug.Kernel;
|
||||||
|
|
||||||
|
namespace Cosmos.Core
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Bootstrap class. Used to invoke pre-boot methods.
|
/// Bootstrap class. Used to invoke pre-boot methods.
|
||||||
|
|
@ -22,7 +24,7 @@
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Multiboot header pointer.
|
/// Multiboot header pointer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static Multiboot.Header* header;
|
public static Multiboot.Header* MultibootHeader;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// VBE mode info pointer.
|
/// VBE mode info pointer.
|
||||||
|
|
@ -59,13 +61,10 @@
|
||||||
*/
|
*/
|
||||||
CPU.InitFloat();
|
CPU.InitFloat();
|
||||||
|
|
||||||
header = (Multiboot.Header*)Multiboot.GetMBIAddress();
|
MultibootHeader = (Multiboot.Header*)Multiboot.GetMBIAddress();
|
||||||
|
|
||||||
modeinfo = (Core.VBE.ModeInfo*)header->vbeModeInfo;
|
modeinfo = (Core.VBE.ModeInfo*)MultibootHeader->vbeModeInfo;
|
||||||
controllerinfo = (Core.VBE.ControllerInfo*)header->vbeControlInfo;
|
controllerinfo = (Core.VBE.ControllerInfo*)MultibootHeader->vbeControlInfo;
|
||||||
|
|
||||||
// Managed_Memory_System.ManagedMemory.Initialize();
|
|
||||||
// Managed_Memory_System.ManagedMemory.SetUpMemoryArea();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
|
#define COSMOSDEBUG
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using IL2CPU.API.Attribs;
|
using IL2CPU.API.Attribs;
|
||||||
|
|
||||||
namespace Cosmos.Core
|
namespace Cosmos.Core
|
||||||
|
|
@ -110,8 +112,6 @@ namespace Cosmos.Core
|
||||||
return xResult;
|
return xResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get CPU vendor name.
|
/// Get CPU vendor name.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -300,7 +300,8 @@ namespace Cosmos.Core
|
||||||
if (!(rs == ""))
|
if (!(rs == ""))
|
||||||
{
|
{
|
||||||
return rs;
|
return rs;
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
}
|
}
|
||||||
|
|
@ -308,8 +309,6 @@ namespace Cosmos.Core
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check if can read CPU ID. Plugged.
|
/// Check if can read CPU ID. Plugged.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -341,5 +340,107 @@ namespace Cosmos.Core
|
||||||
/// <returns>ulong value.</returns>
|
/// <returns>ulong value.</returns>
|
||||||
/// <exception cref="NotImplementedException">Thrown on fatal error, contact support.</exception>
|
/// <exception cref="NotImplementedException">Thrown on fatal error, contact support.</exception>
|
||||||
internal static ulong ReadFromModelSpecificRegister() => throw new NotImplementedException();
|
internal static ulong ReadFromModelSpecificRegister() => throw new NotImplementedException();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if Multiboot returned a memory map
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static unsafe bool MemoryMapExists()
|
||||||
|
{
|
||||||
|
return (Bootstrap.MultibootHeader->Flags & 1 << 6) == 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the Memory Map Information from Multiboot
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns an array of MemoryMaps containing the Multiboot Memory Map information. The array may have empty values at the end.</returns>
|
||||||
|
public static unsafe MemoryMap[] GetMemoryMap()
|
||||||
|
{
|
||||||
|
if (!MemoryMapExists())
|
||||||
|
{
|
||||||
|
throw new Exception("No Memory Map was returned by Multiboot");
|
||||||
|
}
|
||||||
|
var rawMap = new RawMemoryMap[64];
|
||||||
|
var currentMap = (RawMemoryMap*)Bootstrap.MultibootHeader->memMapAddress;
|
||||||
|
int counter = 0;
|
||||||
|
while ((uint)currentMap < (Bootstrap.MultibootHeader->memMapAddress + Bootstrap.MultibootHeader->memMapLength) && counter < 64)
|
||||||
|
{
|
||||||
|
rawMap[counter++] = *currentMap;
|
||||||
|
currentMap = (RawMemoryMap*)((uint*)currentMap + ((currentMap->Size + 4 )>> 2)); //The size is in bits, not bytes
|
||||||
|
if (currentMap->Size == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (counter >= 64)
|
||||||
|
{
|
||||||
|
throw new Exception("Memory Map returned too many segments");
|
||||||
|
}
|
||||||
|
|
||||||
|
var entireMap = new MemoryMap[counter];
|
||||||
|
for (int i = 0; i < counter; i++)
|
||||||
|
{
|
||||||
|
var rawMemoryMap = rawMap[i];
|
||||||
|
entireMap[i] = new MemoryMap
|
||||||
|
{
|
||||||
|
Address = (ulong)rawMemoryMap.HighBaseAddr << 32 | rawMemoryMap.LowBaseAddr,
|
||||||
|
Length = (ulong)rawMemoryMap.HighLength << 32 | rawMemoryMap.LowLength,
|
||||||
|
Type = rawMemoryMap.Type
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return entireMap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MemoryMap
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Base Address of the memory region
|
||||||
|
/// </summary>
|
||||||
|
public ulong Address;
|
||||||
|
/// <summary>
|
||||||
|
/// Length in bytes of the region
|
||||||
|
/// </summary>
|
||||||
|
public ulong Length;
|
||||||
|
/// <summary>
|
||||||
|
/// Type of RAM in region. 1 is available. 3 is for ACPI. All other is unavailable
|
||||||
|
/// </summary>
|
||||||
|
public uint Type;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Explicit, Size = 24)]
|
||||||
|
public struct RawMemoryMap
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Size of this entry
|
||||||
|
/// </summary>
|
||||||
|
[FieldOffset(0)]
|
||||||
|
public uint Size;
|
||||||
|
/// <summary>
|
||||||
|
/// Low 32 bits of the base address
|
||||||
|
/// </summary>
|
||||||
|
[FieldOffset(4)]
|
||||||
|
public uint LowBaseAddr;
|
||||||
|
/// <summary>
|
||||||
|
/// High 32 bits of the base address
|
||||||
|
/// </summary>
|
||||||
|
[FieldOffset(8)]
|
||||||
|
public uint HighBaseAddr;
|
||||||
|
/// <summary>
|
||||||
|
/// Low 32 bits of the length of memory block in bytes
|
||||||
|
/// </summary>
|
||||||
|
[FieldOffset(12)]
|
||||||
|
public uint LowLength;
|
||||||
|
/// <summary>
|
||||||
|
/// High 32 bits of the length of memory block in bytes
|
||||||
|
/// </summary>
|
||||||
|
[FieldOffset(16)]
|
||||||
|
public uint HighLength;
|
||||||
|
/// <summary>
|
||||||
|
/// Type of memory area, 1 if usable RAM, everything else unusable.
|
||||||
|
/// </summary>
|
||||||
|
[FieldOffset(20)]
|
||||||
|
public uint Type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ namespace Cosmos.Core
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public unsafe class MemoryOperations
|
public unsafe class MemoryOperations
|
||||||
{
|
{
|
||||||
|
#region Fill
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fill memory block. Plugged.
|
/// Fill memory block. Plugged.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -183,6 +184,23 @@ namespace Cosmos.Core
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fill source to destination.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dest">Destination.</param>
|
||||||
|
/// <param name="src">Source.</param>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe void Fill(sbyte[] dest, sbyte[] src)
|
||||||
|
{
|
||||||
|
fixed (sbyte* destPtr = dest)
|
||||||
|
fixed (sbyte* srcPtr = src)
|
||||||
|
{
|
||||||
|
Copy(destPtr, srcPtr, dest.Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion Fill
|
||||||
|
|
||||||
|
#region Copy
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Copy source to destination.
|
/// Copy source to destination.
|
||||||
/// plugged.
|
/// plugged.
|
||||||
|
|
@ -329,19 +347,6 @@ namespace Cosmos.Core
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
#endregion Copy
|
||||||
/// Fill source to destination.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="dest">Destination.</param>
|
|
||||||
/// <param name="src">Source.</param>
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static unsafe void Fill(sbyte[] dest, sbyte[] src)
|
|
||||||
{
|
|
||||||
fixed (sbyte* destPtr = dest)
|
|
||||||
fixed (sbyte* srcPtr = src)
|
|
||||||
{
|
|
||||||
Copy(destPtr, srcPtr, dest.Length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -139,7 +139,7 @@ namespace Cosmos.Core
|
||||||
/// <returns>True if is available, false if not</returns>
|
/// <returns>True if is available, false if not</returns>
|
||||||
public static bool IsAvailable()
|
public static bool IsAvailable()
|
||||||
{
|
{
|
||||||
if ((Bootstrap.header->Flags & VBEINFO_PRESENT) == 0)
|
if ((Bootstrap.MultibootHeader->Flags & VBEINFO_PRESENT) == 0)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ namespace Cosmos.Core_Asm
|
||||||
{
|
{
|
||||||
public override void AssembleNew(Assembler aAssembler, object aMethodInfo)
|
public override void AssembleNew(Assembler aAssembler, object aMethodInfo)
|
||||||
{
|
{
|
||||||
XS.Push("MultibootSignature");
|
XS.Push("MultiBootInfo_Structure", isIndirect: true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue