Skip to content

Commit

Permalink
WIP - BareMetal (#1099)
Browse files Browse the repository at this point in the history
  • Loading branch information
tgiphil committed Jul 30, 2023
1 parent 462955b commit 35cb5fa
Show file tree
Hide file tree
Showing 9 changed files with 118 additions and 72 deletions.
2 changes: 1 addition & 1 deletion Source/Mosa.DeviceDriver/ISA/ISABus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ protected void StartISADevices()
{
if (driver is ISADeviceDriverRegistryEntry)
{
HAL.DebugWrite("ISA: ");
HAL.DebugWrite(" > ISA Driver: ");
HAL.DebugWriteLine(driver.Name);

StartISADevice(driver as ISADeviceDriverRegistryEntry);
Expand Down
12 changes: 6 additions & 6 deletions Source/Mosa.DeviceSystem/Service/DeviceService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,31 +152,31 @@ private void StartDevice(Device device)

device.Status = DeviceStatus.Initializing;

HAL.DebugWriteLine($" # Setup");
//HAL.DebugWriteLine($" # Setup");

device.DeviceDriver.Setup(device);

HAL.DebugWriteLine($" # Setup [Done]");
//HAL.DebugWriteLine($" # Setup [Done]");

if (device.Status == DeviceStatus.Initializing)
{
HAL.DebugWriteLine(" # Initializing");
//HAL.DebugWriteLine(" # Initializing");
device.DeviceDriver.Initialize();

HAL.DebugWrite(" # Initialized: ");
HAL.DebugWriteLine(device.Name);

if (device.Status == DeviceStatus.Initializing)
{
HAL.DebugWriteLine(" # Probing");
//HAL.DebugWriteLine(" # Probing");
device.DeviceDriver.Probe();

if (device.Status == DeviceStatus.Available)
{
HAL.DebugWriteLine(" # Starting");
//HAL.DebugWriteLine(" # Starting");
device.DeviceDriver.Start();

HAL.DebugWriteLine(" # Started");
//HAL.DebugWriteLine(" # Started");

AddInterruptHandler(device);
}
Expand Down
69 changes: 45 additions & 24 deletions Source/Mosa.Kernel.BareMetal.x86/PageTable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,34 @@ internal static class PageTable
public static Pointer PageTables;
public static GDT GDTTable;

#region Constants

private static class Constant
{
public const uint Present = 0x01;
public const uint ReadWrite = 0x02;
public const uint UserSupervisor = 0x04;
public const uint WriteThrough = 0x08;
public const uint CacheDisable = 1 << 4;
public const uint Accessed = 1 << 5;
public const uint Dirty = 1 << 6;
}

#endregion Constants

public const uint PageTableCount = 1024;
public const uint IdentityPages = 32768; // 128MB

public static void Setup()
{
Debug.WriteLine("x86.PageTable:Setup()");

GDTTable.Setup();
PageDirectory = PageFrameAllocator.Allocate(1024);
PageTables = PageFrameAllocator.Allocate(1024);
PageDirectory = PageFrameAllocator.Allocate();
PageTables = PageFrameAllocator.Allocate(PageTableCount);

Debug.WriteLine(" * Page Directory @ ", new Hex(PageDirectory));
Debug.WriteLine(" * Page Table @ ", new Hex(PageTables));
Debug.WriteLine(" > Page Directory @ ", new Hex(PageDirectory));
Debug.WriteLine(" > Page Table @ ", new Hex(PageTables));

Debug.WriteLine("x86.PageTable:Setup() [Exit]");
}
Expand All @@ -33,33 +51,40 @@ public static void Initialize()
Debug.WriteLine("x86.PageTable:Initialize()");

// Setup Page Directory
Debug.WriteLine(" > Setup Page Directory");
for (uint index = 0; index < 1024; index++)
Debug.WriteLine(" * Setup Page Directory");
for (var index = 0u; index < PageTableCount; index++)
{
PageDirectory.Store32(index << 2, (PageTables.ToUInt32() + index * Page.Size) | 0x04 | 0x02 | 0x01);
PageDirectory.Store32(index << 2, (PageTables.ToUInt32() + index * Page.Size) | Constant.Present | Constant.ReadWrite | Constant.UserSupervisor);
}

// Clear the Page Tables
Debug.WriteLine(" > Clear the Page Tables");
for (uint index = 0; index < PageFrameAllocator.TotalPages; index++)
{
PageTables.Store32(index << 2, (index * Page.Size) | 0x04 | 0x02 | 0x01);
}
Debug.WriteLine(" * Clearing Page Table Entries");
PageTables.Clear(PageTableCount * Page.Size);

// Setup Identity Pages
Debug.WriteLine(" > Setup Identity Pages");
Debug.WriteLine(" * Setup Identity Pages");
MapIdentityPages(PageTables, PageTableCount);
MapIdentityPages(PageDirectory, 1);

// Map the first 128MB of memory
var endPage = new Pointer(128 * 1024 * 1024);
MapIdentityPages(Pointer.Zero, IdentityPages);

Debug.WriteLine(" * Identity End @ ", new Hex(endPage));
Debug.WriteLine("x86.PageTable:Initialize() [Exit]");
}

private static void MapIdentityPages(Pointer start, uint pages)
{
Debug.WriteLine("x86.PageTable:MapIdentityPages()");
Debug.WriteLine(" > Start: ", new Hex(start));

var end = start + (pages * Page.Size);

for (var page = Pointer.Zero; page < endPage; page += Page.Size)
Debug.WriteLine(" > End: ", new Hex(end));

for (var page = start; page < end; page += Page.Size)
{
MapVirtualAddressToPhysical(page, page, true);
}

Debug.WriteLine("x86.PageTable:Initialize() [Exit]");
Debug.WriteLine("x86.PageTable:MapIdentityPages() [Exit]");
}

public static void Enable()
Expand All @@ -77,15 +102,11 @@ public static void Enable()

public static void MapVirtualAddressToPhysical(Pointer virtualAddress, Pointer physicalAddress, bool present = true)
{
//FUTURE: traverse page directory from CR3 --- do not assume page table is linearly allocated

PageTables.Store32((virtualAddress.ToUInt32() & 0xFFFFF000u) >> 10, physicalAddress.ToUInt32() & 0xFFFFF000u | 0x04u | 0x02u | (present ? 0x1u : 0x0u));
PageTables.Store32((virtualAddress.ToUInt32() & 0xFFFFF000u) >> 10, (physicalAddress.ToUInt32() & 0xFFFFF000u) | (present ? Constant.Present : 0x0u) | Constant.ReadWrite | Constant.UserSupervisor);
}

public static Pointer GetPhysicalAddressFromVirtual(Pointer virtualAddress)
{
//FUTURE: traverse page directory from CR3 --- do not assume page table is linearly allocated

var address = virtualAddress.ToUInt32();
var offset = ((address & 0xFFFFF000u) >> 10) + (address & 0xFFFu);

Expand Down
2 changes: 1 addition & 1 deletion Source/Mosa.Kernel.BareMetal/BootPageAllocator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public static Pointer AllocatePages(uint pages = 1)

Page.ClearPage(result);

Debug.WriteLine(" * Boot Page Allocated @ ", new Hex(result));
Debug.WriteLine(" > Boot Page Allocated @ ", new Hex(result));

// TODO: Release lock

Expand Down
2 changes: 1 addition & 1 deletion Source/Mosa.Kernel.BareMetal/Page.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public static Pointer ClearPage(Pointer page)
{
var writes = Size / 4;

for (uint i = 0; i < writes; i += 4)
for (var i = 0u; i < writes; i += 4)
{
page.Store32(i, 0);
}
Expand Down
37 changes: 25 additions & 12 deletions Source/Mosa.Kernel.BareMetal/PageFrameAllocator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,14 +138,9 @@ public static void Setup()
SetPageBitMapEntry(startPage, pages, false);
}

// Reserve the first page
SetPageBitMapEntry(1, 1, false);

// TODO - reserve kernel code + memory

SearchNextStartPage = MinimumAvailablePage;

//Debug.Kill();
ReserveMemory();
}

public static void Release(Pointer page, uint count)
Expand Down Expand Up @@ -194,7 +189,7 @@ public static Pointer Allocate(uint count, uint alignment = 1)

SearchNextStartPage = restartAt;

//Debug.WriteLine(" > return: ", at);
Debug.WriteLine(" > Return: ", new Hex(at));

return new Pointer(at * Page.Size);
}
Expand All @@ -209,7 +204,9 @@ public static Pointer Allocate(uint count, uint alignment = 1)
restartAt = MinimumAvailablePage;

if (wrap)
{
Debug.Kill();
}

wrap = true;
}
Expand All @@ -219,7 +216,8 @@ public static Pointer Allocate(uint count, uint alignment = 1)
// looped around in the search
// quit, as there are no free pages

//Debug.WriteLine(" > return: Zero");
Debug.WriteLine(" > return: Zero");
Debug.Fatal();

return Pointer.Zero;
}
Expand Down Expand Up @@ -303,9 +301,9 @@ private static void SetPageBitMapEntry(uint start, uint count, bool set)
}
}

private static bool CheckFreePage32(uint at, uint count, out uint nextAt)
private static bool CheckFreePage32(uint at, uint count, out uint next)
{
nextAt = at;
next = at;

//Debug.WriteLine("CheckFreePage32:PhysicalPageAllocator()");
//Debug.WriteLine(" > count = ", count);
Expand All @@ -330,14 +328,14 @@ private static bool CheckFreePage32(uint at, uint count, out uint nextAt)

if (maskvalue == 0)
{
nextAt = at + bitlen;
next = at + bitlen;
count -= bitlen;
at += bitlen;
}
else
{
// Future optimization: return nextAt page of the first available bit after the first unavailble bit, and if not, then start at next 32-bit aligned page number
nextAt = at + 1;
next = at + 1;

return false;
}
Expand All @@ -346,5 +344,20 @@ private static bool CheckFreePage32(uint at, uint count, out uint nextAt)
return true;
}

private static void ReserveMemory()
{
// Reserve the first page
SetPageBitMapEntry(0, 1, false);

// Reserve Boot Page Allocator
var region = Platform.GetBootReservedRegion();
SetPageBitMapEntry((uint)(region.Address.ToInt64() / Page.Size), ((uint)region.Size / Page.Size) + 1, false);

// Reserve first 24MB
SetPageBitMapEntry(0, 24 * 1024 * 1024 / Page.Size, false);

// TODO - reserve kernel code + memory
}

#endregion Private API
}
16 changes: 12 additions & 4 deletions Source/Mosa.Kernel.x86/PageTable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,23 @@ namespace Mosa.Kernel.x86;
/// </summary>
public static class PageTable
{
/// <summary>
/// Sets up the PageTable
/// </summary>
private static class Constant
{
public const uint Present = 1 << 0;
public const uint ReadWrite = 1 << 1;
public const uint UserSupervisor = 1 << 2;
public const uint WriteThrough = 1 << 3;
public const uint CacheDisable = 1 << 4;
public const uint Accessed = 1 << 5;
public const uint Dirty = 1 << 6;
}

public static void Setup()
{
// Setup Page Directory
for (int index = 0; index < 1024; index++)
{
new Pointer(Address.PageDirectory).Store32(index << 2, (uint)(Address.PageTable + index * 4096 | 0x04 | 0x02 | 0x01));
new Pointer(Address.PageDirectory).Store32(index << 2, (uint)(Address.PageTable + index * 4096 | Constant.UserSupervisor | Constant.ReadWrite | Constant.Present));
}

// Map the first 128MB of memory (32786 4K pages) (why 128MB?)
Expand Down
44 changes: 21 additions & 23 deletions Source/Mosa.Runtime/Internal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -186,23 +186,19 @@ public static Pointer UnboxAny(Pointer src, Pointer dest, uint size)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void MemoryCopy(Pointer dest, Pointer src, uint count)
{
MemoryCopy1(dest, src, count);
//if (count < 4)
//{
// MemoryCopy1(dest, src, count);
//}
//else
//{
// var mod = count % 4;
//MemoryCopy1(dest, src, count);
var mod = count % 4;

// MemoryCopy4(dest, src, count - mod);
// MemoryCopy1(dest + mod, src + mod, mod);
//}
MemoryCopy1(dest, src, mod);
MemoryCopy4(dest + mod, src + mod, count - mod);
}

[MethodImpl(MethodImplOptions.NoInlining)]
private static void MemoryCopy1(Pointer dest, Pointer src, uint count)
{
if (count == 0)
return;

for (var i = 0; i < count; i++)
{
var value = src.Load8(i);
Expand All @@ -213,6 +209,9 @@ private static void MemoryCopy1(Pointer dest, Pointer src, uint count)
[MethodImpl(MethodImplOptions.NoInlining)]
private static void MemoryCopy4(Pointer dest, Pointer src, uint count)
{
if (count == 0)
return;

for (var i = 0; i < count; i += 4)
{
var value = src.Load32(i);
Expand Down Expand Up @@ -247,32 +246,31 @@ public static void MemorySet(Pointer dest, uint value, uint count)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void MemoryClear(Pointer dest, uint count)
{
MemoryClear1(dest, count);
//if (count < 4)
//{
// MemoryClear1(dest, count);
//}
//else
//{
// var mod = count % 4;
//MemoryClear1(dest, count);
var mod = count % 4;

// MemoryClear4(dest, count - mod);
// MemoryClear1(dest + mod, mod);
//}
MemoryClear1(dest, mod);
MemoryClear4(dest + mod, count - mod);
}

[MethodImpl(MethodImplOptions.NoInlining)]
private static void MemoryClear1(Pointer dest, uint count)
{
if (count == 0)
return;

for (var i = 0; i < count; i++)
{
dest.Store8(i, 0);
}
}

[MethodImpl(MethodImplOptions.NoInlining)]
private static void MemoryClear4(Pointer dest, uint count)
public static void MemoryClear4(Pointer dest, uint count)
{
if (count == 0)
return;

for (var i = 0; i < count; i += 4)
{
dest.Store32(i, 0);
Expand Down
6 changes: 6 additions & 0 deletions Source/Mosa.Runtime/Pointer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -583,4 +583,10 @@ public void StorePointer(ulong offset, Pointer value)
{
Intrinsic.StorePointer(this, offset, value);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Clear(uint size)
{
Internal.MemoryClear(this, size);
}
}

0 comments on commit 35cb5fa

Please sign in to comment.