diff --git a/Kernel/Include/Arch/DTB.h b/Kernel/Include/Arch/DTB.h index c73efa9..215b4d7 100644 --- a/Kernel/Include/Arch/DTB.h +++ b/Kernel/Include/Arch/DTB.h @@ -1,6 +1,7 @@ #pragma once #include +#include typedef struct FDTHeader { UInt32 magic; // 0xd00dfeed @@ -32,4 +33,4 @@ enum { kFDTHeaderMagic = 0xd00dfeed, }; -void DTBParse(Pointer dtb); \ No newline at end of file +void DTBParse(Pointer dtb, VMBootMemoryMap* bootMap); \ No newline at end of file diff --git a/Kernel/Include/Lib/Stubs.h b/Kernel/Include/Lib/Stubs.h new file mode 100644 index 0000000..313fa92 --- /dev/null +++ b/Kernel/Include/Lib/Stubs.h @@ -0,0 +1,4 @@ +#pragma once +#include + +void* memset(void* destination, int value, Size count); \ No newline at end of file diff --git a/Kernel/Include/VM/PMM.h b/Kernel/Include/VM/PMM.h new file mode 100644 index 0000000..6704e4c --- /dev/null +++ b/Kernel/Include/VM/PMM.h @@ -0,0 +1,23 @@ +#pragma once +#include + +enum { + kVMPageSize = 4096, + kVMBlocksPerByte = 8, + kVMMaxReservedRegions = 128, +}; + +typedef struct { + UInt64 base; + Size size; +} VMMemoryRegion; + +typedef struct { + VMMemoryRegion totalRAM; + VMMemoryRegion reserved[kVMMaxReservedRegions]; + UInt32 reservedCount; +} VMBootMemoryMap; + +void PMMInitialize(VMBootMemoryMap* bootMap); +Pointer PMMAllocatePage(); +void PMMFreePage(Address address); \ No newline at end of file diff --git a/Kernel/Source/Arch/DTB.c b/Kernel/Source/Arch/DTB.c index 9cd89ee..6808a68 100644 --- a/Kernel/Source/Arch/DTB.c +++ b/Kernel/Source/Arch/DTB.c @@ -1,22 +1,33 @@ +#include "Types.h" #include #include #include #include #include #include +#include -void DTBParse(Pointer dtb) { +void DTBParse(Pointer dtb, VMBootMemoryMap* bootMap) { FDTHeader* header = (FDTHeader*)dtb; if (BytesSwap32(header->magic) != kFDTHeaderMagic) { OSPanic("Invalid DTB magic"); } + UInt32 index = bootMap->reservedCount; + bootMap->reserved[index].base = (Address)dtb; + bootMap->reserved[index].size = BytesSwap32(header->totalSize); + bootMap->reservedCount++; + UInt32 offStruct = BytesSwap32(header->offDtStruct); UInt32 offStrings = BytesSwap32(header->offDtStrings); BytePointer structs = (BytePointer)dtb + offStruct; ASCII* strings = (ASCII*)dtb + offStrings; + ASCII* currentNode = ""; + UInt32 currentDepth = 0; + UInt32 reservedMemoryDepth = 0; + bool inReservedMemory = false; while (true) { UInt32 token = BytesSwap32(*(UInt32*)structs); @@ -24,35 +35,59 @@ void DTBParse(Pointer dtb) { switch (token) { case FDTTokenBeginNode: { + currentDepth++; currentNode = (ASCII*)structs; + if (StringStartsWith(currentNode, "reserved-memory")) { + inReservedMemory = true; + reservedMemoryDepth = currentDepth; + } + UInt32 nameLength = StringGetLength(currentNode); structs += (nameLength + 1); structs = (BytePointer)AlignUp64((Address)structs, 4); - break; } case FDTTokenProperty: { UInt32 propertyLength = BytesSwap32(*(UInt32*)structs); UInt32 nameOffset = BytesSwap32(*(UInt32*)(structs + 4)); structs += 8; - ASCII* propertyName = strings + nameOffset; - if (StringCompare(propertyName, "reg") == 0 && StringStartsWith(currentNode, "memory")) { - UInt32* cells = (UInt32*)structs; - - UInt64 base = Merge32To64(BytesSwap32(cells[0]), BytesSwap32(cells[1])); - UInt64 size = Merge32To64(BytesSwap32(cells[2]), BytesSwap32(cells[3])); - OSLog("Memory: base=0x%x, size=0x%x\n", base, size); + if (StringCompare(propertyName, "reg") == 0) { + if (StringStartsWith(currentNode, "memory")) { + UInt32* cells = (UInt32*)structs; + Address base = Merge32To64(BytesSwap32(cells[1]), BytesSwap32(cells[0])); + Size size = Merge32To64(BytesSwap32(cells[3]), BytesSwap32(cells[2])); + + bootMap->totalRAM.base = base; + bootMap->totalRAM.size = size; + } + else if (inReservedMemory && currentDepth > reservedMemoryDepth) { + UInt32* cells = (UInt32*)structs; + Address base = Merge32To64(BytesSwap32(cells[1]), BytesSwap32(cells[0])); + Size size = Merge32To64(BytesSwap32(cells[3]), BytesSwap32(cells[2])); + + UInt32 index = bootMap->reservedCount; + bootMap->reserved[index].base = base; + bootMap->reserved[index].size = size; + bootMap->reservedCount++; + } } + structs += propertyLength; structs = (BytePointer)AlignUp64((Address)structs, 4); - break; } - case FDTTokenEndNode: break; + case FDTTokenEndNode: { + if (inReservedMemory && currentDepth == reservedMemoryDepth) { + inReservedMemory = false; + } + currentDepth--; + break; + } + case FDTTokenNOP: continue; case FDTTokenEnd: return; default: diff --git a/Kernel/Source/KernelMain.c b/Kernel/Source/KernelMain.c index 3611ac3..efe5aa1 100644 --- a/Kernel/Source/KernelMain.c +++ b/Kernel/Source/KernelMain.c @@ -1,4 +1,5 @@ #include "../Common/bootinfo.h" +#include #include #include #include @@ -8,6 +9,9 @@ void KernelMain(Bootinfo* bootinfo) { if (bootinfo->magic != BOOTINFO_MAGIC) { OSPanic("Invalid bootinfo magic"); } - - DTBParse(bootinfo->dtb); + + VMBootMemoryMap bootMap = {0}; + bootMap.reservedCount = 0; + DTBParse(bootinfo->dtb, &bootMap); + PMMInitialize(&bootMap); } \ No newline at end of file diff --git a/Kernel/Source/Lib/Stubs.c b/Kernel/Source/Lib/Stubs.c new file mode 100644 index 0000000..8a5544f --- /dev/null +++ b/Kernel/Source/Lib/Stubs.c @@ -0,0 +1,6 @@ +#include +#include + +void* memset(void* destination, int value, Size count) { + return StringSet(destination, value, count); +} \ No newline at end of file diff --git a/Kernel/Source/VM/PMM.c b/Kernel/Source/VM/PMM.c new file mode 100644 index 0000000..e15d06e --- /dev/null +++ b/Kernel/Source/VM/PMM.c @@ -0,0 +1,83 @@ +#include +#include + +extern char _kernelStart[]; +extern char _kernelEnd[]; + +static inline Size BitmapGetByteIndex(Address address) { + return (address / kVMPageSize) / kVMBlocksPerByte; +} + +static inline UInt8 BitmapGetBitOffset(Address address) { + return (UInt8)((address / kVMPageSize) % kVMBlocksPerByte); +} + +static inline Boolean BitmapTest(const MemoryPointer bitmap, Address address) { + return (bitmap[BitmapGetByteIndex(address)] & (1U << BitmapGetBitOffset(address))) != 0; +} + +static inline void BitmapSet(MemoryPointer bitmap, Address address) { + bitmap[BitmapGetByteIndex(address)] |= (1U << BitmapGetBitOffset(address)); +} + +static inline void BitmapUnset(MemoryPointer bitmap, Address address) { + bitmap[BitmapGetByteIndex(address)] &= ~(1U << BitmapGetBitOffset(address)); +} + +static MemoryPointer sPMMBitmap; +static Size sPMMBitmapSize; +static Size sPMMTotalPages; + +void PMMInitialize(VMBootMemoryMap* bootMap) { + UInt32 vIndex = bootMap->reservedCount; + bootMap->reserved[vIndex].base = 0x0; + bootMap->reserved[vIndex].size = bootMap->totalRAM.base; + bootMap->reservedCount++; + + UInt32 kIndex = bootMap->reservedCount; + bootMap->reserved[kIndex].base = (Address)_kernelStart; + bootMap->reserved[kIndex].size = (Address)_kernelEnd - (Address)_kernelStart; + bootMap->reservedCount++; + + sPMMTotalPages = bootMap->totalRAM.size / kVMPageSize; + sPMMBitmapSize = sPMMTotalPages / kVMBlocksPerByte; + sPMMBitmap = (MemoryPointer)_kernelEnd; + + StringSet(sPMMBitmap, 0, sPMMBitmapSize); + + UInt32 bIndex = bootMap->reservedCount; + bootMap->reserved[bIndex].base = (Address)sPMMBitmap; + bootMap->reserved[bIndex].size = sPMMBitmapSize; + bootMap->reservedCount++; + + for (Size i = 0; i < bootMap->reservedCount; i++) { + Address regionBase = bootMap->reserved[i].base; + Size regionSize = bootMap->reserved[i].size; + + Size pagesToReserve = (regionSize + kVMPageSize - 1) / kVMPageSize; + + for (Size p = 0; p < pagesToReserve; p++) { + Address pageAdress = regionBase + (p * kVMPageSize); + BitmapSet(sPMMBitmap, pageAdress); + } + } +} + +Pointer PMMAllocatePage() { + for (Size i = 0; i < sPMMBitmapSize; i++) { + if (sPMMBitmap[i] == 0xFF) continue; + for (Size bit = 0; bit < kVMBlocksPerByte; bit++) { + if ((sPMMBitmap[i] & (1 << bit)) == 0) { + Address address = (i * kVMBlocksPerByte + bit) * kVMPageSize; + BitmapSet(sPMMBitmap, address); + return (Pointer)address; + } + } + } + + return nullptr; +} + +void PMMFreePage(Address address) { + BitmapUnset(sPMMBitmap, address); +} \ No newline at end of file diff --git a/Kernel/linker.ld b/Kernel/linker.ld index b793125..4e8729e 100644 --- a/Kernel/linker.ld +++ b/Kernel/linker.ld @@ -7,14 +7,22 @@ PHDRS SECTIONS { . = 0x40100000; + _kernelStart = .; .text : { *(.text.boot) *(.text*) } :text + . = ALIGN(8); .rodata : { *(.rodata*) } :text + . = ALIGN(4096); .data : { *(.data*) } :data + + . = ALIGN(8); .bss : { *(.bss*) *(COMMON) } :data + + . = ALIGN(4096); + _kernelEnd = .; } \ No newline at end of file