From 785a61b451597ff0169f2b560b8dcbb0e8db0b2c Mon Sep 17 00:00:00 2001 From: karina Date: Sun, 26 Apr 2026 13:32:44 +0400 Subject: [PATCH 1/2] feat: DTB now populates VMBootMemoryMap structure. --- Kernel/Include/Arch/DTB.h | 3 ++- Kernel/Include/Lib/Stubs.h | 4 +++ Kernel/Include/VM/PMM.h | 19 ++++++++++++++ Kernel/Source/Arch/DTB.c | 53 ++++++++++++++++++++++++++++++-------- Kernel/Source/KernelMain.c | 8 ++++-- Kernel/Source/Lib/Stubs.c | 6 +++++ Kernel/Source/VM/PMM.c | 22 ++++++++++++++++ Kernel/linker.ld | 8 ++++++ 8 files changed, 109 insertions(+), 14 deletions(-) create mode 100644 Kernel/Include/Lib/Stubs.h create mode 100644 Kernel/Include/VM/PMM.h create mode 100644 Kernel/Source/Lib/Stubs.c create mode 100644 Kernel/Source/VM/PMM.c 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..6beddd3 --- /dev/null +++ b/Kernel/Include/VM/PMM.h @@ -0,0 +1,19 @@ +#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; \ No newline at end of file diff --git a/Kernel/Source/Arch/DTB.c b/Kernel/Source/Arch/DTB.c index 9cd89ee..69c4f7e 100644 --- a/Kernel/Source/Arch/DTB.c +++ b/Kernel/Source/Arch/DTB.c @@ -4,8 +4,9 @@ #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"); @@ -16,7 +17,11 @@ void DTBParse(Pointer dtb) { 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 +29,61 @@ 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; + UInt64 base = Merge32To64(BytesSwap32(cells[1]), BytesSwap32(cells[0])); + UInt64 size = Merge32To64(BytesSwap32(cells[3]), BytesSwap32(cells[2])); + OSLog("Main Memory: base=0x%x, size=0x%x\n", base, size); + bootMap->totalRAM.base = base; + bootMap->totalRAM.size = size; + } + else if (inReservedMemory && currentDepth > reservedMemoryDepth) { + UInt32* cells = (UInt32*)structs; + UInt64 base = Merge32To64(BytesSwap32(cells[1]), BytesSwap32(cells[0])); + UInt64 size = Merge32To64(BytesSwap32(cells[3]), BytesSwap32(cells[2])); + + UInt32 index = bootMap->reservedCount; + bootMap->reserved[index].base = base; + bootMap->reserved[index].size = size; + bootMap->reservedCount++; + + OSLog("Reserved Region (%s): base=0x%x, size=0x%x\n", currentNode, base, size); + } } + 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..a0fb291 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); + OSLog("Meow...\n"); } \ 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..280983a --- /dev/null +++ b/Kernel/Source/VM/PMM.c @@ -0,0 +1,22 @@ +#include + +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)); +} + 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 From 55335013a940a4c39baf34d1c42ea47d0072b2da Mon Sep 17 00:00:00 2001 From: karina Date: Sun, 26 Apr 2026 15:12:04 +0400 Subject: [PATCH 2/2] feat: completely functional PMM --- Kernel/Include/VM/PMM.h | 6 +++- Kernel/Source/Arch/DTB.c | 18 ++++++----- Kernel/Source/KernelMain.c | 2 +- Kernel/Source/VM/PMM.c | 61 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 78 insertions(+), 9 deletions(-) diff --git a/Kernel/Include/VM/PMM.h b/Kernel/Include/VM/PMM.h index 6beddd3..6704e4c 100644 --- a/Kernel/Include/VM/PMM.h +++ b/Kernel/Include/VM/PMM.h @@ -16,4 +16,8 @@ typedef struct { VMMemoryRegion totalRAM; VMMemoryRegion reserved[kVMMaxReservedRegions]; UInt32 reservedCount; -} VMBootMemoryMap; \ No newline at end of file +} 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 69c4f7e..6808a68 100644 --- a/Kernel/Source/Arch/DTB.c +++ b/Kernel/Source/Arch/DTB.c @@ -1,3 +1,4 @@ +#include "Types.h" #include #include #include @@ -12,6 +13,11 @@ void DTBParse(Pointer dtb, VMBootMemoryMap* bootMap) { 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); @@ -51,23 +57,21 @@ void DTBParse(Pointer dtb, VMBootMemoryMap* bootMap) { if (StringCompare(propertyName, "reg") == 0) { if (StringStartsWith(currentNode, "memory")) { UInt32* cells = (UInt32*)structs; - UInt64 base = Merge32To64(BytesSwap32(cells[1]), BytesSwap32(cells[0])); - UInt64 size = Merge32To64(BytesSwap32(cells[3]), BytesSwap32(cells[2])); - OSLog("Main Memory: base=0x%x, size=0x%x\n", base, size); + 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; - UInt64 base = Merge32To64(BytesSwap32(cells[1]), BytesSwap32(cells[0])); - UInt64 size = Merge32To64(BytesSwap32(cells[3]), BytesSwap32(cells[2])); + 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++; - - OSLog("Reserved Region (%s): base=0x%x, size=0x%x\n", currentNode, base, size); } } diff --git a/Kernel/Source/KernelMain.c b/Kernel/Source/KernelMain.c index a0fb291..efe5aa1 100644 --- a/Kernel/Source/KernelMain.c +++ b/Kernel/Source/KernelMain.c @@ -13,5 +13,5 @@ void KernelMain(Bootinfo* bootinfo) { VMBootMemoryMap bootMap = {0}; bootMap.reservedCount = 0; DTBParse(bootinfo->dtb, &bootMap); - OSLog("Meow...\n"); + PMMInitialize(&bootMap); } \ No newline at end of file diff --git a/Kernel/Source/VM/PMM.c b/Kernel/Source/VM/PMM.c index 280983a..e15d06e 100644 --- a/Kernel/Source/VM/PMM.c +++ b/Kernel/Source/VM/PMM.c @@ -1,4 +1,8 @@ #include +#include + +extern char _kernelStart[]; +extern char _kernelEnd[]; static inline Size BitmapGetByteIndex(Address address) { return (address / kVMPageSize) / kVMBlocksPerByte; @@ -20,3 +24,60 @@ 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