uh save this

This commit is contained in:
xwashere 2024-04-22 07:58:33 -04:00
parent 516329d25c
commit 4334e21878
Signed by: XWasHere
GPG Key ID: 042F8BFA1B0EF93B
10 changed files with 242 additions and 20 deletions

View File

@ -8,7 +8,7 @@ lw_project(lcrash
enable_language(ASM) enable_language(ASM)
lw_add_executable(lcrashkern lw_add_executable(lcrashkern
SOURCES main.c cmdline.c util.c lnxboot.c math.c debug/debug.c acpi/acpi.c efi/efi.c efi/guid.c efi/memmap.c gdb/gdb.c pci/pci.c mm/phys.c mm/kmalloc.c driver/sysbus.c SOURCES main.c cmdline.c util.c lnxboot.c math.c debug/debug.c acpi/acpi.c efi/efi.c efi/guid.c efi/memmap.c gdb/gdb.c pci/pci.c mm/phys.c mm/kmalloc.c mm/virt.c driver/sysbus.c
) )
add_executable(lcrashkernld IMPORTED) add_executable(lcrashkernld IMPORTED)
set_property(TARGET lcrashkernld PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/lcrash.ld) set_property(TARGET lcrashkernld PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/lcrash.ld)

View File

@ -15,7 +15,7 @@ struct DebugExtendedDebugInformationBlock* DebugEDIB = 0;
struct GdbDataBlock* DebugGDB = (struct GdbDataBlock*)0x100000; struct GdbDataBlock* DebugGDB = (struct GdbDataBlock*)0x100000;
int DebugInitialize() { int DebugInitialize() {
DebugEDIB = KernelHeapAlloc(sizeof(struct DebugExtendedDebugInformationBlock), 0); DebugEDIB = KernelHeapAlloc(sizeof(struct DebugExtendedDebugInformationBlock), 1, 0);
if (DebugEDIB == 0) return -1; if (DebugEDIB == 0) return -1;
DebugGDB->EDIB = DebugEDIB; DebugGDB->EDIB = DebugEDIB;

View File

@ -10,10 +10,10 @@ struct SysbusDevice* SysbusRootDevice = 0;
* Create a new device description * Create a new device description
*/ */
struct SysbusDeviceDescription* SysbusCreateDeviceDescriptionInternal() { struct SysbusDeviceDescription* SysbusCreateDeviceDescriptionInternal() {
struct SysbusDeviceDescription* Description = KernelHeapAlloc(sizeof(struct SysbusDeviceDescription), 0); struct SysbusDeviceDescription* Description = KernelHeapAlloc(sizeof(struct SysbusDeviceDescription), 1, 0);
Description->DeviceName = 0; Description->DeviceName = 0;
Description->Instances = KernelHeapAlloc(sizeof(struct SysbusDevice*) * 4, 0); Description->Instances = KernelHeapAlloc(sizeof(struct SysbusDevice*) * 4, 1, 0);
Description->InstanceCount = 0; Description->InstanceCount = 0;
Description->InstanceSlots = 4; Description->InstanceSlots = 4;
Description->CreateDevice = 0; Description->CreateDevice = 0;
@ -29,7 +29,7 @@ struct SysbusDeviceDescription* SysbusCreateDeviceDescriptionInternal() {
void SysbusAttachChildDeviceInternal(struct SysbusDevice* Parent, struct SysbusDevice* Child) { void SysbusAttachChildDeviceInternal(struct SysbusDevice* Parent, struct SysbusDevice* Child) {
// See if we need to grow the list // See if we need to grow the list
if (Parent->ChildCount >= Parent->ChildSlots) { if (Parent->ChildCount >= Parent->ChildSlots) {
struct SysbusDevice** NewList = KernelHeapAlloc(sizeof(struct SysbusDevice*) * Parent->ChildSlots * 2, 0); struct SysbusDevice** NewList = KernelHeapAlloc(sizeof(struct SysbusDevice*) * Parent->ChildSlots * 2, 1, 0);
for (int i = 0; i < Parent->ChildCount; i++) { for (int i = 0; i < Parent->ChildCount; i++) {
NewList[i] = Parent->Children[i]; NewList[i] = Parent->Children[i];
} }
@ -59,12 +59,12 @@ struct SysbusDevice* SysbusCreateDeviceInternal(
void* DeviceData, void* DeviceData,
bool IsRootDevice bool IsRootDevice
) { ) {
struct SysbusDevice* Device = KernelHeapAlloc(sizeof(struct SysbusDevice), 0); struct SysbusDevice* Device = KernelHeapAlloc(sizeof(struct SysbusDevice), 1, 0);
Device->DeviceDescription = Description; Device->DeviceDescription = Description;
Device->DeviceName = 0; Device->DeviceName = 0;
Device->DeviceData = 0; Device->DeviceData = 0;
Device->Parent = Parent; Device->Parent = Parent;
Device->Children = KernelHeapAlloc(sizeof(struct SysbusDevice*) * 4, 0); Device->Children = KernelHeapAlloc(sizeof(struct SysbusDevice*) * 4, 1, 0);
Device->ChildCount = 0; Device->ChildCount = 0;
Device->ChildSlots = 4; Device->ChildSlots = 4;
@ -73,7 +73,7 @@ struct SysbusDevice* SysbusCreateDeviceInternal(
// See if we need to grow the instance list // See if we need to grow the instance list
if (Description->InstanceCount >= Description->InstanceSlots) { if (Description->InstanceCount >= Description->InstanceSlots) {
struct SysbusDevice** NewList = KernelHeapAlloc(sizeof(struct SysbusDevice*) * Description->InstanceSlots * 2, 0); struct SysbusDevice** NewList = KernelHeapAlloc(sizeof(struct SysbusDevice*) * Description->InstanceSlots * 2, 1, 0);
for (int i = 0; i < Description->InstanceCount; i++) { for (int i = 0; i < Description->InstanceCount; i++) {
NewList[i] = Description->Instances[i]; NewList[i] = Description->Instances[i];
} }
@ -122,7 +122,5 @@ void SysbusInitialize() {
); );
SysbusRootDevice->DeviceName = "Lcrash System Bus"; SysbusRootDevice->DeviceName = "Lcrash System Bus";
Panic("Failed to initialize system bus");
return; return;
} }

View File

@ -8,6 +8,7 @@
#include <lcrash/cmdline.h> #include <lcrash/cmdline.h>
#include <lcrash/debug/debug.h> #include <lcrash/debug/debug.h>
#include <lcrash/driver/sysbus.h> #include <lcrash/driver/sysbus.h>
#include <lcrash/mm/virt.h>
#include "types.h" #include "types.h"
#include "lnxboot.h" #include "lnxboot.h"
@ -38,6 +39,9 @@ void entry64(struct boot_params* BootParams) {
// Initialize the extended debugging information block // Initialize the extended debugging information block
if (DebugInitialize()) while (1) {} if (DebugInitialize()) while (1) {}
// Initialize the virtual memory manager
VmemInitialize();
// Initialize the system bus // Initialize the system bus
SysbusInitialize(); SysbusInitialize();

View File

@ -136,11 +136,99 @@ int KernelHeapInitialize() {
return 0; return 0;
} }
void* KernelHeapAlloc(u32 Size, u32 Flags) { /// Shamelessly copy pasted from function above
int KernelHeapGrow(struct KernelHeapZone* Zone, u32 Level, u32 Flags) {
// Allocate
struct PmemAllocation Block;
if (PmemAllocateBlock(1 << Level, &Block)) return -1;
// Make the frame block
struct KernelHeapBlock* FrameBlock = Block.Address;
FrameBlock->Prev = Zone->Last;
FrameBlock->PrevFree = Zone->LastFree;
FrameBlock->Size = sizeof(struct KernelHeapFrame);
FrameBlock->Free = false;
// Make the frame structure
struct KernelHeapFrame* Frame = Block.Address
+ sizeof(struct KernelHeapBlock);
Frame->Block = Block;
Frame->Size = 1 << Level;
Frame->NextFrame = 0;
Frame->PrevFrame = Zone->LastFrame;
// Make the root block
struct KernelHeapBlock* RootBlock = (struct KernelHeapBlock*)((void*)Frame + sizeof(struct KernelHeapFrame));
RootBlock->Prev = FrameBlock;
FrameBlock->Next = RootBlock;
FrameBlock->NextFree = RootBlock;
RootBlock->Next = 0;
RootBlock->PrevFree = Zone->LastFree;
RootBlock->NextFree = 0;
RootBlock->Free = true;
RootBlock->Size = (1 << Level)
- sizeof(struct KernelHeapBlock)
- sizeof(struct KernelHeapFrame)
- sizeof(struct KernelHeapBlock);
// Fill out the rest of the zone
Zone->LastFrame->NextFrame = Frame;
Zone->LastFrame = Frame;
Zone->Last->Next = FrameBlock;
for (struct KernelHeapBlock* Block = Zone->Last; Block != 0 && Block->NextFree == 0; Block = Block->Prev) Block->NextFree = RootBlock;
Zone->Last = RootBlock;
return 0;
}
void* KernelHeapAllocInternal(u32 Size, u32 Align, u32 Flags, u32 Iteration) {
u64 AlignMask = 0;
for (u32 i = 1; i < Align; i <<= 1) AlignMask |= i;
AlignMask = ~AlignMask;
// Find a free block // Find a free block
for (struct KernelHeapZone* Zone = KernelHeapFirst; Zone != 0; Zone = Zone->Next) { for (struct KernelHeapZone* Zone = KernelHeapFirst; Zone != 0; Zone = Zone->Next) {
for (struct KernelHeapBlock* Block = Zone->FirstFree; Block != 0; Block = Block->NextFree) { for (struct KernelHeapBlock* Block = Zone->FirstFree; Block != 0; Block = Block->NextFree) {
if (Block->Size >= Size) { if (Block->Size >= Size) {
u64 PaddingSize = 0;
if (Align > 1) {
// Align uses memory poorly
if (Block->Prev == 0) continue;
u64 BlockStart = (uptr)Block + sizeof(struct KernelHeapBlock);
u64 BlockEnd = BlockStart + Block->Size;
if (!(BlockStart < ((BlockStart + Align) & AlignMask) && BlockEnd > ((BlockStart + Align) & AlignMask))) continue;
PaddingSize = ((BlockStart + Align) & AlignMask) - BlockStart;
}
if (PaddingSize > 0) {
struct KernelHeapBlock* NewBlock = (struct KernelHeapBlock*)((void*)Block + PaddingSize);
NewBlock->Prev = Block->Prev;
NewBlock->Next = Block->Next;
NewBlock->PrevFree = Block->PrevFree;
NewBlock->NextFree = Block->NextFree;
NewBlock->Free = Block->Free;
NewBlock->Size = Block->Size - PaddingSize;
// This is incredibly slow
struct KernelHeapBlock* Next = Zone->First;
while (Next != 0) {
struct KernelHeapBlock* NextNext = Next->Next;
if (Next->Prev == Block) Next->Prev = NewBlock;
if (Next->Next == Block) Next->Next = NewBlock;
if (Next->PrevFree == Block) Next->PrevFree = NewBlock;
if (Next->NextFree == Block) Next->NextFree = NewBlock;
Next = NextNext;
}
// GOD.
if (NewBlock->Prev != 0) NewBlock->Prev->Size += (uptr)Block + PaddingSize;
Block = NewBlock;
}
s64 SplitSize = (s64)Block->Size - Size - (sizeof(struct KernelHeapBlock) * 2) - 8; s64 SplitSize = (s64)Block->Size - Size - (sizeof(struct KernelHeapBlock) * 2) - 8;
if (SplitSize > 0) { if (SplitSize > 0) {
@ -179,7 +267,14 @@ void* KernelHeapAlloc(u32 Size, u32 Flags) {
} }
} }
return 0; if (Iteration < 3) {
KernelHeapGrow(KernelHeapLast, 20, 0);
return KernelHeapAllocInternal(Size, Align, Flags, Iteration + 1);
} else return 0;
}
void* KernelHeapAlloc(u32 Size, u32 Align, u32 Flags) {
return KernelHeapAllocInternal(Size, Align, Flags, 0);
} }
void KernelHeapFree(void* Address) { void KernelHeapFree(void* Address) {

View File

@ -10,7 +10,7 @@ int KernelHeapInitialize();
/** /**
* Allocate memory * Allocate memory
*/ */
void* KernelHeapAlloc(u32 Size, u32 Flags); void* KernelHeapAlloc(u32 Size, u32 Align, u32 Flags);
/** /**
* Free memory * Free memory

74
lcrash/mm/virt.c Normal file
View File

@ -0,0 +1,74 @@
#include <lcrash/mm/virt.h>
#include <lcrash/mm/kmalloc.h>
#include <lcrash/debug/debug.h>
u64 (*VmemOriginalPML4)[512] = 0;
u64 (*VmemPML4)[512] = 0;
void VmemInitialize() {
// Copy control registers
u64 CR3;
asm ("mov %%cr3, %0" : "=r" (CR3));
u64 CR4;
asm ("mov %%cr4, %0" : "=r" (CR4));
if (CR4 & 0x800) Panic("5 Level paging not supported");
u64 (*OriginalPML4)[512] = (u64(*)[512])(CR3 & 0x0007fffffffff000);
u64 (*NewPML4)[512] = KernelHeapAlloc(sizeof(u64) * 512, 0x1000, 0);
for (int i = 0; i < 512; i++) {
if ((*OriginalPML4)[i] & 1) {
u64 (*OriginalPDPT)[512] = (u64(*)[512])(((*OriginalPML4)[i] & 0x0007fffffffff000));
u64 (*NewPDPT)[512] = KernelHeapAlloc(sizeof(u64) * 512, 0x1000, 0);
for (int j = 0; j < 512; j++) {
if ((*OriginalPDPT)[j] & 1) {
u64 (*OriginalPD)[512] = (u64(*)[512])(((*OriginalPDPT)[j] & 0x000ffffffffff000));
u64 (*NewPD)[512] = KernelHeapAlloc(sizeof(u64) * 512, 0x1000, 0);
for (int k = 0; k < 512; k++) {
if ((*OriginalPD)[k] & 1) {
u64 (*OriginalPT)[512] = (u64(*)[512])(((*OriginalPD)[k] & 0x000ffffffffff000));
u64 (*NewPT)[512] = KernelHeapAlloc(sizeof(u64) * 512, 0x1000, 0);
if ((s64)NewPT <= 0) Panic("Failed to allocate memory");
for (int l = 0; l < 512; l++) {
//if ((*OriginalPT)[l] & 1) {
// (*NewPT)[l] = (*OriginalPT)[l];
//} else (*NewPT)[l] = 0;*
(*NewPT)[l] = (*OriginalPT)[l] | 0x87;
}
NewPT = (void*)((u64)OriginalPT | 0x87);
(*NewPD)[k] = (u64)NewPT;
} else (*NewPD)[k] = 0;
}
NewPD = (void*)((uptr)NewPD | (((*OriginalPDPT)[j]) & ~0x0007fffffffff000));
(*NewPDPT)[j] = (u64)NewPD;
} else (*NewPDPT)[j] = 0;
}
NewPDPT = (void*)((uptr)NewPDPT | (((*OriginalPML4)[i]) & ~0x0007fffffffff000));
(*NewPML4)[i] = (u64)NewPDPT;
} else (*NewPML4)[i] = 0;
}
// Save these
VmemOriginalPML4 = OriginalPML4;
VmemPML4 = NewPML4;
// Load our new page table
CR3 ^= (u64)VmemOriginalPML4;
CR3 |= ((u64)VmemPML4) & 0x0007fffffffff000;
asm volatile ("mov %q0, %%cr3" : : "r" (CR3));
Panic("FUCK");
}

5
lcrash/mm/virt.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
#include <lcrash/types.h>
void VmemInitialize();

View File

@ -2,22 +2,46 @@
#include <lcrash/acpi/acpi.h> #include <lcrash/acpi/acpi.h>
#include <lcrash/debug/debug.h> #include <lcrash/debug/debug.h>
#include <lcrash/driver/sysbus.h>
bool PciIsPresent = false; bool PciIsPresent = false;
bool PciSupportsECM = false; bool PciSupportsECM = false;
void PciInitialize() { void* PciBusses[256] = {};
// Try to figure out if we have PCIe
if (AcpiPresent()) {
struct AcpiMCFG* BridgeTable = AcpiGetTable("MCFG");
// Guess not void PciScanDevice(u32 Bus, u32 Device) {
if (BridgeTable == NULL) goto nopcie; struct PciConfigurationSpaceHeader* DeviceHeader = (struct PciConfigurationSpaceHeader*)(PciBusses[Bus] + Device * 0x800);
// Is a device connected here?
if (DeviceHeader->VendorID != 0xFFFF) {
while (1) {} while (1) {}
} }
}
nopcie: Panic("Failed to initialize PCI"); void PciScanBus(u32 Bus) {
// Scan bus devices
for (int i = 0; i < 32; i++) PciScanDevice(Bus, i);
}
void PciInitialize() {
// Try to figure out if we have PCIe
if (!AcpiPresent()) Panic("Failed to initialize PCI");
struct AcpiMCFG* BridgeTable = AcpiGetTable("MCFG");
// Guess not
if (BridgeTable == NULL) Panic("Failed to find PCI bridge table");
// Take our pcie bridges
s32 Length = (BridgeTable->Header.Length - 44) / 16;
for (int i = 0; i < Length; i++) {
for (int Bus = BridgeTable->Bridges[i].StartBus; Bus < BridgeTable->Bridges[i].EndBus; Bus++) {
PciBusses[Bus] = BridgeTable->Bridges[i].Address + (Bus - BridgeTable->Bridges[i].StartBus) * 0x100000;
}
}
// Scan the root bus
PciScanBus(0);
return; return;
} }

View File

@ -2,6 +2,28 @@
#include <lcrash/types.h> #include <lcrash/types.h>
/**
* bwaaaaaa, the many ways to touch PCI things
*/
struct [[gnu::packed]] PciConfigurationSpaceHeader {
u16 VendorID;
u16 DeviceID;
u16 Status;
u16 Command;
u8 RevisionID : 8;
u32 ClassCode : 24;
u8 CacheLineSize;
u8 MasterLatencyTimer;
u8 HeaderType;
u8 BIST;
u8 Reserved[0x20];
u8 CapabilitiesPointer;
u8 Reserved2[7];
u8 InterruptLine;
u8 InterruptPin;
u8 Reserved3[2];
};
/** /**
* Initialize the PCI code. * Initialize the PCI code.
*/ */