uh save this
This commit is contained in:
parent
516329d25c
commit
4334e21878
@ -8,7 +8,7 @@ lw_project(lcrash
|
||||
enable_language(ASM)
|
||||
|
||||
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)
|
||||
set_property(TARGET lcrashkernld PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/lcrash.ld)
|
||||
|
@ -15,7 +15,7 @@ struct DebugExtendedDebugInformationBlock* DebugEDIB = 0;
|
||||
struct GdbDataBlock* DebugGDB = (struct GdbDataBlock*)0x100000;
|
||||
|
||||
int DebugInitialize() {
|
||||
DebugEDIB = KernelHeapAlloc(sizeof(struct DebugExtendedDebugInformationBlock), 0);
|
||||
DebugEDIB = KernelHeapAlloc(sizeof(struct DebugExtendedDebugInformationBlock), 1, 0);
|
||||
if (DebugEDIB == 0) return -1;
|
||||
|
||||
DebugGDB->EDIB = DebugEDIB;
|
||||
|
@ -10,10 +10,10 @@ struct SysbusDevice* SysbusRootDevice = 0;
|
||||
* Create a new device description
|
||||
*/
|
||||
struct SysbusDeviceDescription* SysbusCreateDeviceDescriptionInternal() {
|
||||
struct SysbusDeviceDescription* Description = KernelHeapAlloc(sizeof(struct SysbusDeviceDescription), 0);
|
||||
struct SysbusDeviceDescription* Description = KernelHeapAlloc(sizeof(struct SysbusDeviceDescription), 1, 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->InstanceSlots = 4;
|
||||
Description->CreateDevice = 0;
|
||||
@ -29,7 +29,7 @@ struct SysbusDeviceDescription* SysbusCreateDeviceDescriptionInternal() {
|
||||
void SysbusAttachChildDeviceInternal(struct SysbusDevice* Parent, struct SysbusDevice* Child) {
|
||||
// See if we need to grow the list
|
||||
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++) {
|
||||
NewList[i] = Parent->Children[i];
|
||||
}
|
||||
@ -59,12 +59,12 @@ struct SysbusDevice* SysbusCreateDeviceInternal(
|
||||
void* DeviceData,
|
||||
bool IsRootDevice
|
||||
) {
|
||||
struct SysbusDevice* Device = KernelHeapAlloc(sizeof(struct SysbusDevice), 0);
|
||||
struct SysbusDevice* Device = KernelHeapAlloc(sizeof(struct SysbusDevice), 1, 0);
|
||||
Device->DeviceDescription = Description;
|
||||
Device->DeviceName = 0;
|
||||
Device->DeviceData = 0;
|
||||
Device->Parent = Parent;
|
||||
Device->Children = KernelHeapAlloc(sizeof(struct SysbusDevice*) * 4, 0);
|
||||
Device->Children = KernelHeapAlloc(sizeof(struct SysbusDevice*) * 4, 1, 0);
|
||||
Device->ChildCount = 0;
|
||||
Device->ChildSlots = 4;
|
||||
|
||||
@ -73,7 +73,7 @@ struct SysbusDevice* SysbusCreateDeviceInternal(
|
||||
|
||||
// See if we need to grow the instance list
|
||||
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++) {
|
||||
NewList[i] = Description->Instances[i];
|
||||
}
|
||||
@ -122,7 +122,5 @@ void SysbusInitialize() {
|
||||
);
|
||||
SysbusRootDevice->DeviceName = "Lcrash System Bus";
|
||||
|
||||
Panic("Failed to initialize system bus");
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <lcrash/cmdline.h>
|
||||
#include <lcrash/debug/debug.h>
|
||||
#include <lcrash/driver/sysbus.h>
|
||||
#include <lcrash/mm/virt.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "lnxboot.h"
|
||||
@ -38,6 +39,9 @@ void entry64(struct boot_params* BootParams) {
|
||||
// Initialize the extended debugging information block
|
||||
if (DebugInitialize()) while (1) {}
|
||||
|
||||
// Initialize the virtual memory manager
|
||||
VmemInitialize();
|
||||
|
||||
// Initialize the system bus
|
||||
SysbusInitialize();
|
||||
|
||||
|
@ -136,11 +136,99 @@ int KernelHeapInitialize() {
|
||||
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
|
||||
for (struct KernelHeapZone* Zone = KernelHeapFirst; Zone != 0; Zone = Zone->Next) {
|
||||
for (struct KernelHeapBlock* Block = Zone->FirstFree; Block != 0; Block = Block->NextFree) {
|
||||
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;
|
||||
|
||||
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) {
|
||||
|
@ -10,7 +10,7 @@ int KernelHeapInitialize();
|
||||
/**
|
||||
* Allocate memory
|
||||
*/
|
||||
void* KernelHeapAlloc(u32 Size, u32 Flags);
|
||||
void* KernelHeapAlloc(u32 Size, u32 Align, u32 Flags);
|
||||
|
||||
/**
|
||||
* Free memory
|
||||
|
74
lcrash/mm/virt.c
Normal file
74
lcrash/mm/virt.c
Normal 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
5
lcrash/mm/virt.h
Normal file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <lcrash/types.h>
|
||||
|
||||
void VmemInitialize();
|
@ -2,22 +2,46 @@
|
||||
|
||||
#include <lcrash/acpi/acpi.h>
|
||||
#include <lcrash/debug/debug.h>
|
||||
#include <lcrash/driver/sysbus.h>
|
||||
|
||||
bool PciIsPresent = false;
|
||||
bool PciSupportsECM = false;
|
||||
|
||||
void PciInitialize() {
|
||||
// Try to figure out if we have PCIe
|
||||
if (AcpiPresent()) {
|
||||
struct AcpiMCFG* BridgeTable = AcpiGetTable("MCFG");
|
||||
void* PciBusses[256] = {};
|
||||
|
||||
// Guess not
|
||||
if (BridgeTable == NULL) goto nopcie;
|
||||
void PciScanDevice(u32 Bus, u32 Device) {
|
||||
struct PciConfigurationSpaceHeader* DeviceHeader = (struct PciConfigurationSpaceHeader*)(PciBusses[Bus] + Device * 0x800);
|
||||
|
||||
// Is a device connected here?
|
||||
if (DeviceHeader->VendorID != 0xFFFF) {
|
||||
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;
|
||||
}
|
||||
|
@ -2,6 +2,28 @@
|
||||
|
||||
#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.
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user