memory savings

This commit is contained in:
maksw committed 2026-05-14 14:57:00 +02:00
1 parent ddb074f0e0
commit def649b995
7 files changed
+193 -27

No files matched your search

Binary file not shown.
+125 -21
View File
@@ -109,21 +109,91 @@ static UINT64* AllocPage(EFI_PHYSICAL_ADDRESS* physOut) {
#define PDT_IDX(va) (((va) >> 21) & 0x1FF)
#define PT_IDX(va) (((va) >> 12) & 0x1FF)
#define PAGE_2M (2ULL * 1024ULL * 1024ULL)
#define PAGE_1G (1024ULL * 1024ULL * 1024ULL)
static UINT64* gPml4;
static void MapPage(UINT64 virt, UINT64 phys, UINT64 flags) {
UINT64* pml4e = &gPml4[PML4_IDX(virt)];
if (!(*pml4e & 1)) { EFI_PHYSICAL_ADDRESS p; AllocPage(&p); *pml4e = p | 3; }
UINT64* pdpt = (UINT64 *)(*pml4e & ~0xFFFULL);
UINT64* pdpte = &pdpt[PDPT_IDX(virt)];
if (!(*pdpte & 1)) { EFI_PHYSICAL_ADDRESS p; AllocPage(&p); *pdpte = p | 3; }
UINT64* pdt = (UINT64 *)(*pdpte & ~0xFFFULL);
UINT64* pdte = &pdt[PDT_IDX(virt)];
if (!(*pdte & 1)) { EFI_PHYSICAL_ADDRESS p; AllocPage(&p); *pdte = p | 3; }
UINT64* pt = (UINT64 *)(*pdte & ~0xFFFULL);
static UINT64* EnsureTable(UINT64* parent, UINTN index) {
UINT64* entry = &parent[index];
if (!(*entry & 1)) {
EFI_PHYSICAL_ADDRESS p;
UINT64* child = AllocPage(&p);
*entry = p | 3;
return child;
}
return (UINT64 *)(*entry & ~0xFFFULL);
}
static void Map4K(UINT64 virt, UINT64 phys, UINT64 flags) {
UINT64* pdpt = EnsureTable(gPml4, PML4_IDX(virt));
UINT64* pdt = EnsureTable(pdpt, PDPT_IDX(virt));
UINT64* pt = EnsureTable(pdt, PDT_IDX(virt));
pt[PT_IDX(virt)] = phys | flags;
}
static void Map2M(UINT64 virt, UINT64 phys, UINT64 flags) {
UINT64* pdpt = EnsureTable(gPml4, PML4_IDX(virt));
UINT64* pdt = EnsureTable(pdpt, PDPT_IDX(virt));
pdt[PDT_IDX(virt)] = phys | flags | 0x80ULL; // PS bit
}
static void Map1G(UINT64 virt, UINT64 phys, UINT64 flags) {
UINT64* pdpt = EnsureTable(gPml4, PML4_IDX(virt));
pdpt[PDPT_IDX(virt)] = phys | flags | 0x80ULL; // PS bit
}
static void MapRangeSmart(UINT64 virt, UINT64 phys, UINT64 size, UINT64 flags) {
while (size) {
if ((virt & (PAGE_1G - 1)) == 0 && (phys & (PAGE_1G - 1)) == 0 && size >= PAGE_1G) {
Map1G(virt, phys, flags);
virt += PAGE_1G;
phys += PAGE_1G;
size -= PAGE_1G;
} else if ((virt & (PAGE_2M - 1)) == 0 && (phys & (PAGE_2M - 1)) == 0 && size >= PAGE_2M) {
Map2M(virt, phys, flags);
virt += PAGE_2M;
phys += PAGE_2M;
size -= PAGE_2M;
} else {
Map4K(virt, phys, flags);
virt += PAGE_SIZE;
phys += PAGE_SIZE;
size -= PAGE_SIZE;
}
}
}
static void MapRangeSkipping(UINT64 virt, UINT64 phys, UINT64 size, UINT64 flags,
const UINT64* holes, UINTN holeCount) {
UINT64 curVirt = virt;
UINT64 curPhys = phys;
UINT64 end = virt + size;
for (UINTN i = 0; i < holeCount; i++) {
UINT64 hStart = holes[i * 2 + 0];
UINT64 hEnd = holes[i * 2 + 1];
if (hEnd <= curVirt || hStart >= end) continue;
if (curVirt < hStart) {
UINT64 prefixSize = hStart - curVirt;
MapRangeSmart(curVirt, curPhys, prefixSize, flags);
curPhys += prefixSize;
curVirt += prefixSize;
}
if (curVirt < hEnd) {
UINT64 skip = hEnd - curVirt;
curVirt += skip;
curPhys += skip;
}
}
if (curVirt < end) {
MapRangeSmart(curVirt, curPhys, end - curVirt, flags);
}
}
// ---------------------------------------------------------------------------
// File loading
// ---------------------------------------------------------------------------
@@ -592,7 +662,7 @@ EFI_STATUS EFIAPI UefiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable
imgLen = (imgLen + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
for (UINT64 off = 0; off < imgLen; off += PAGE_SIZE) {
MapPage(virtCursor + off, physBase + off, 0x03 /* P|W */);
Map4K(virtCursor + off, physBase + off, 0x03 /* P|W */);
}
// Fill BOOT_INFO
@@ -642,6 +712,8 @@ EFI_STATUS EFIAPI UefiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable
// Query GOP FIRST, before the GetMemoryMap loop
EFI_GRAPHICS_OUTPUT_PROTOCOL* gop;
UINT64 fbBase = 0;
UINT64 fbBytes = 0;
if (!EFI_ERROR(gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid, NULL, (VOID **)&gop))) {
bi->FramebufferBase = gop->Mode->FrameBufferBase;
bi->FramebufferWidth = gop->Mode->Info->HorizontalResolution;
@@ -651,15 +723,16 @@ EFI_STATUS EFIAPI UefiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable
// FrameBufferSize is a lie - EFI reports it as Width*Height*4.
// The ACTUAL consumed bytes are Stride*Height*4.
// Add one extra page as a safety margin.
UINT64 fbBytes = (UINT64)gop->Mode->Info->PixelsPerScanLine
fbBase = gop->Mode->FrameBufferBase;
fbBytes = (UINT64)gop->Mode->Info->PixelsPerScanLine
* (UINT64)gop->Mode->Info->VerticalResolution
* 4 + PAGE_SIZE;
fbBytes = (fbBytes + PAGE_SIZE - 1) & ~(UINT64)(PAGE_SIZE - 1);
for (UINT64 i = 0; i < fbBytes; i += PAGE_SIZE) {
UINT64 phys = gop->Mode->FrameBufferBase + i;
MapPage(PHYS_MAP_BASE + phys, phys, 0x13); // P|W|PCD (write-combined MMIO)
MapPage(phys, phys, 0x13);
Map4K(PHYS_MAP_BASE + phys, phys, 0x13); // P|W|PCD (write-combined MMIO)
Map4K(phys, phys, 0x13);
}
}
@@ -672,10 +745,43 @@ EFI_STATUS EFIAPI UefiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable
EFI_MEMORY_DESCRIPTOR* efiMap = AllocatePool(mapSize);
gBS->GetMemoryMap(&mapSize, efiMap, &mapKey, &descSz, &descVer);
{
UINT64 idHoles[4];
UINT64 winHoles[4];
UINTN holeCount = 0;
if (fbBytes) {
idHoles[holeCount * 2 + 0] = fbBase;
idHoles[holeCount * 2 + 1] = fbBase + fbBytes;
winHoles[holeCount * 2 + 0] = PHYS_MAP_BASE + fbBase;
winHoles[holeCount * 2 + 1] = PHYS_MAP_BASE + fbBase + fbBytes;
holeCount++;
}
idHoles[holeCount * 2 + 0] = 0xFEC00000ULL;
idHoles[holeCount * 2 + 1] = 0xFEE01000ULL;
winHoles[holeCount * 2 + 0] = PHYS_MAP_BASE + 0xFEC00000ULL;
winHoles[holeCount * 2 + 1] = PHYS_MAP_BASE + 0xFEE01000ULL;
holeCount++;
if (holeCount == 2) {
if (idHoles[2] < idHoles[0]) {
UINT64 t0 = idHoles[0], t1 = idHoles[1];
idHoles[0] = idHoles[2];
idHoles[1] = idHoles[3];
idHoles[2] = t0;
idHoles[3] = t1;
}
if (winHoles[2] < winHoles[0]) {
UINT64 t0 = winHoles[0], t1 = winHoles[1];
winHoles[0] = winHoles[2];
winHoles[1] = winHoles[3];
winHoles[2] = t0;
winHoles[3] = t1;
}
}
for (UINTN i = 0; i < mapSize / descSz; i++) {
EFI_MEMORY_DESCRIPTOR* desc = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)efiMap + i * descSz);
// Map everything except unusable memory to the Physical Window
// Map everything except unusable memory to the Physical Window.
if (desc->Type != EfiUnusableMemory && desc->Type != EfiMemoryMappedIOPortSpace) {
UINT64 start = desc->PhysicalStart;
UINT64 end = start + (desc->NumberOfPages * PAGE_SIZE);
@@ -685,10 +791,8 @@ EFI_STATUS EFIAPI UefiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable
// memory because of buggy UEFI size reporting.
end += 2 * PAGE_SIZE;
for (UINT64 phys = start; phys < end; phys += PAGE_SIZE) {
MapPage(phys, phys, 0x03); // Identity
MapPage(PHYS_MAP_BASE + phys, phys, 0x03); // High-half
}
MapRangeSkipping(start, start, end - start, 0x03, idHoles, holeCount);
MapRangeSkipping(PHYS_MAP_BASE + start, start, end - start, 0x03, winHoles, holeCount);
}
}
}
@@ -703,8 +807,8 @@ EFI_STATUS EFIAPI UefiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable
for (UINT64 phys = 0xFEC00000; phys < 0xFEE01000; phys += PAGE_SIZE) {
// In a production OS you'd use Cache-Disable flags (0x13 or 0x1B),
// but 0x03 is fine for hobby OS initialization before PAT is set up.
MapPage(phys, phys, 0x03); // Identity Map
MapPage(PHYS_MAP_BASE + phys, phys, 0x03); // Physical Window Map
Map4K(phys, phys, 0x03); // Identity Map
Map4K(PHYS_MAP_BASE + phys, phys, 0x03); // Physical Window Map
}
Print(L"8\n");
+32
View File
@@ -30,6 +30,37 @@ typedef KSTATUS (*DRIVER_ENTRY_FN)(const HAL_API *);
// threading a parameter through every call chain.
static const HAL_API* gKmainHal;
static int PageInBootloaderRegion(const BOOT_INFO* bootInfo, PHYSICAL_ADDRESS page) {
for (uint32_t i = 0; i < bootInfo->MemoryMap.RegionCount; i++) {
const MEMORY_REGION* r = &bootInfo->MemoryMap.Regions[i];
if (r->Type != MemoryBootloader) continue;
uintptr_t start = r->Base & PAGE_MASK;
uintptr_t end = (r->Base + r->Length + PAGE_SIZE - 1) & PAGE_MASK;
if ((uintptr_t)page >= start && (uintptr_t)page < end) {
return 1;
}
}
return 0;
}
static void ReclaimBootloaderMemory(const BOOT_INFO* bootInfo) {
// Reclaim only the raw buffers backing boot-loaded .sys modules.
// The kernel/HAL images, page tables, and bootloader code remain live.
for (uint32_t i = 2; i < bootInfo->ModuleCount; i++) {
const BOOT_MODULE* mod = &bootInfo->Modules[i];
if (!mod->PhysBase || !mod->ImageSize) continue;
uintptr_t base = (uintptr_t)(mod->PhysBase & PAGE_MASK);
uintptr_t end = (uintptr_t)((mod->PhysBase + mod->ImageSize + PAGE_SIZE - 1) & PAGE_MASK);
for (uintptr_t page = base; page < end; page += PAGE_SIZE) {
if (!PageInBootloaderRegion(bootInfo, (PHYSICAL_ADDRESS)page)) continue;
MmFreeFrame((PHYSICAL_ADDRESS)page);
}
}
}
// ---------------------------------------------------------------------------
// Phase Helper: Resolve Imports for core modules
// ---------------------------------------------------------------------------
@@ -330,6 +361,7 @@ void SystemInitThread(void* arg) {
InitializeDrivers(args->bootInfo, args->hal);
ResolveSystemImports(args->bootInfo);
ReclaimBootloaderMemory(args->bootInfo);
args->hal->Screen.Clear(0x000000);
+2 -4
View File
@@ -37,6 +37,7 @@ static void PushFrame(PHYSICAL_ADDRESS frame) {
uintptr_t flags = KeAcquireSpinlock(&gFrameStack.Lock);
if (gFrameStack.Top < gFrameStack.Capacity) {
gFrameStack.Stack[gFrameStack.Top++] = frame;
gFrameStack.Total++;
}
KeReleaseSpinlock(&gFrameStack.Lock, flags);
}
@@ -90,10 +91,7 @@ bool MmInitializePhysical(const MEMORY_MAP* map, uint64_t physicalWindowBase) {
for (PHYSICAL_ADDRESS frame = base; frame < end; frame += PAGE_SIZE) {
if (frame >= stackPhys && frame < stackEnd) continue;
if (gFrameStack.Top < gFrameStack.Capacity) {
gFrameStack.Stack[gFrameStack.Top++] = frame;
gFrameStack.Total++;
}
PushFrame(frame);
}
}
+33
View File
@@ -239,6 +239,37 @@ static void FreeListRemove(HEAP* h, BLOCK_HDR* blk) {
blk->PrevFree = blk->NextFree = (BLOCK_HDR *)0;
}
static void HeapTryDecommitTail(HEAP* h, BLOCK_HDR* blk) {
if (!blk || blk->Free == 0) return;
while (h->Brk > h->Start) {
uintptr_t blockEnd = (uintptr_t)blk + HDR_SIZE + blk->Size + FTR_SIZE;
if (blockEnd != h->Brk) break;
// Keep at least one page for the block header/footer and a small payload.
if (blk->Size < PAGE_SIZE + sizeof(void*)) break;
uintptr_t pageStart = h->Brk - PAGE_SIZE;
if (pageStart <= (uintptr_t)blk) break; // would unmap the page containing the header
PHYSICAL_ADDRESS phys = MmGetPhysicalAddress(pageStart);
if (!phys) break;
if (!KSUCCESS(MmUnmapPage(pageStart))) {
break;
}
MmFreeFrame(phys);
h->Brk -= PAGE_SIZE;
blk->Size -= PAGE_SIZE;
}
if (blk->Free) {
HdrToFtr(blk)->Size = blk->Size;
HdrToFtr(blk)->Magic = BLOCK_MAGIC;
HdrToFtr(blk)->Free = 1;
}
}
static void* HeapAlloc(HEAP* h, size_t size) {
if (!size) return (void *)0;
size = (size + 7) & ~7ULL; // 8-byte align
@@ -338,6 +369,8 @@ static void HeapFree(HEAP* h, void* ptr) {
HdrToFtr(blk)->Free = 1;
HdrToFtr(blk)->Magic = BLOCK_MAGIC;
HeapTryDecommitTail(h, blk);
KeReleaseSpinlock(&h->Lock, flags);
}
+1 -1
View File
@@ -106,7 +106,7 @@ int main(const char* cmdline) {
BinkNextFrame(b);
}
WriteConsoleA(h, "shell: goodbye\n", 15, 0, 0);
WriteConsoleA(h, "video: goodbye\n", 15, 0, 0);
ExitProcess(0);
}
-1
View File
@@ -78,7 +78,6 @@ The Win32 personality supports programs that expect drive letters, familiar proc
- open the VS x64 build tools as administrator
- change into this directory
- run `mkimage.bat`
- run `build.bat`
- use one of `run.bat` (IDE), `rund.bat` (IDE, debug), `runa.bat` (AHCI), or `runad.bat` (AHCI, debug)