completely redesign how user mode memory is allocated, fix a few smp and scheduler bugs, terminating a process now terminates the process, telemetry, optimize text editor, new font, new color scheme

This commit is contained in:
maksw committed 2026-06-09 18:02:28 +02:00
1 parent 27b31f62b6
commit 325149006c
45 files changed
+2091 -760

No files matched your search

+50 -7
View File
@@ -11,7 +11,8 @@
//
// User heap:
// A single best-fit free list in the lower half.
// Backed on demand from the PMM. No per-process heaps.
// Page-granular lower-half regions owned by PROCESS metadata. Sub-page
// allocation is a user-mode runtime concern.
#include <stddef.h>
#include <string.h>
#include <intrin.h>
@@ -164,7 +165,7 @@ int MmHandleTlbShootdownNmi(void) {
// ---------------------------------------------------------------------------
// Public mapping
// ---------------------------------------------------------------------------
__declspec(dllexport) KSTATUS MmMapPage(uintptr_t virt, PHYSICAL_ADDRESS phys, uint64_t flags) {
__declspec(dllexport) KSTATUS MmMapPage(uintptr_t virt, PHYSICAL_ADDRESS phys, uint64_t flags, MM_MAP_MODE mode) {
unsigned userFlag = (flags & PAGE_USER) ? PAGE_USER : 0;
uintptr_t lockFlags = KeAcquireSpinlock(&gPageTableLock);
@@ -186,6 +187,10 @@ __declspec(dllexport) KSTATUS MmMapPage(uintptr_t virt, PHYSICAL_ADDRESS phys, u
}
uint64_t* pte = KiPtePtr(pt, PT_IDX(virt));
if ((*pte & PAGE_PRESENT) && mode == MmMapFailIfPresent) {
KeReleaseSpinlock(&gPageTableLock, lockFlags);
return STATUS_ALREADY_EXISTS;
}
*pte = phys | flags;
KeReleaseSpinlock(&gPageTableLock, lockFlags);
@@ -525,7 +530,7 @@ static int KiHeapEnsureMapped(HEAP* h, uintptr_t start, size_t size) {
PHYSICAL_ADDRESS frame = MmAllocateFrame();
if (!frame) return 0;
KSTATUS ms = MmMapPage(va, frame, h->MapFlags);
KSTATUS ms = MmMapPage(va, frame, h->MapFlags, MmMapFailIfPresent);
if (!KSUCCESS(ms)) {
MmFreeFrame(frame);
return 0;
@@ -544,7 +549,7 @@ static int KiHeapGrow(HEAP* h, size_t need) {
for (uintptr_t va = h->Brk; va < h->Brk + grow; va += PAGE_SIZE) {
PHYSICAL_ADDRESS frame = MmAllocateFrame();
if (!frame) return 0;
if (!KSUCCESS(MmMapPage(va, frame, h->MapFlags))) {
if (!KSUCCESS(MmMapPage(va, frame, h->MapFlags, MmMapFailIfPresent))) {
MmFreeFrame(frame);
return 0;
}
@@ -965,7 +970,7 @@ KSTATUS MmCreateUserRegion(PROCESS* process, size_t size, size_t alignment,
s = STATUS_NO_MEMORY;
break;
}
s = MmMapPage(va, frame, pageFlags);
s = MmMapPage(va, frame, pageFlags, MmMapFailIfPresent);
if (!KSUCCESS(s)) {
MmFreeFrame(frame);
break;
@@ -1036,7 +1041,7 @@ KSTATUS MmEnsureUserRegionMapped(PROCESS* process, void* base, size_t size, uint
PHYSICAL_ADDRESS frame = MmAllocateFrame();
if (!frame) return STATUS_NO_MEMORY;
KSTATUS ms = MmMapPage(va, frame, flags);
KSTATUS ms = MmMapPage(va, frame, flags, MmMapFailIfPresent);
if (!KSUCCESS(ms)) {
MmFreeFrame(frame);
return ms;
@@ -1073,6 +1078,16 @@ KSTATUS MmProtectUserRegion(PROCESS* process, void* base, size_t size, uint64_t
return STATUS_NOT_FOUND;
}
if (pageFlags == 0) {
for (uintptr_t va = alignedStart; va < alignedEnd; va += PAGE_SIZE) {
if (va < regionBase || va >= regionEnd) return STATUS_ACCESS_DENIED;
PHYSICAL_ADDRESS phys = MmGetPhysicalAddress(va);
if (phys && KSUCCESS(MmUnmapPage(va)))
MmFreeFrame(phys);
}
return STATUS_SUCCESS;
}
uint64_t finalFlags = pageFlags | PAGE_PRESENT | PAGE_USER;
for (uintptr_t va = alignedStart; va < alignedEnd; va += PAGE_SIZE) {
@@ -1091,7 +1106,7 @@ KSTATUS MmProtectUserRegion(PROCESS* process, void* base, size_t size, uint64_t
if (!KSUCCESS(qs) || !(existingFlags & PAGE_PRESENT)) {
PHYSICAL_ADDRESS frame = MmAllocateFrame();
if (!frame) return STATUS_NO_MEMORY;
KSTATUS ms = MmMapPage(va, frame, PAGE_PRESENT | PAGE_WRITE | PAGE_USER | PAGE_NX);
KSTATUS ms = MmMapPage(va, frame, PAGE_PRESENT | PAGE_WRITE | PAGE_USER | PAGE_NX, MmMapFailIfPresent);
if (!KSUCCESS(ms)) {
MmFreeFrame(frame);
return ms;
@@ -1161,6 +1176,34 @@ void MmDestroyAllUserRegions(PROCESS* process) {
}
}
KSTATUS MmQueryUserRegion(PROCESS* process, const void* address, void** baseOut, size_t* sizeOut,
uint64_t* pageFlagsOut, USER_REGION_TYPE* typeOut, uint32_t* regionFlagsOut) {
if (!process || !address) return STATUS_INVALID_PARAMETER;
uintptr_t addr = (uintptr_t)address;
uintptr_t procFlags = KeAcquireSpinlock(&process->UserRegionLock);
for (LIST_ENTRY* node = process->UserRegions.Fwd; node != &process->UserRegions; node = node->Fwd) {
USER_VA_REGION* r = CONTAINING_RECORD(node, USER_VA_REGION, ProcessLink);
uintptr_t end = r->Base + r->CommittedSize;
if (addr >= r->Base && addr < end) {
if (baseOut) *baseOut = (void*)r->Base;
if (sizeOut) *sizeOut = r->CommittedSize;
if (pageFlagsOut) {
PHYSICAL_ADDRESS phys = 0;
uint64_t flags = 0;
KSTATUS qs = MmQueryPage(addr & PAGE_MASK, &phys, &flags);
*pageFlagsOut = KSUCCESS(qs) ? flags : 0;
}
if (typeOut) *typeOut = r->Type;
if (regionFlagsOut) *regionFlagsOut = r->Flags;
KeReleaseSpinlock(&process->UserRegionLock, procFlags);
return STATUS_SUCCESS;
}
}
KeReleaseSpinlock(&process->UserRegionLock, procFlags);
return STATUS_NOT_FOUND;
}
size_t MmGetUserRegionSize(PROCESS* process, const void* base) {
if (!process || !base) return 0;
uintptr_t procFlags = KeAcquireSpinlock(&process->UserRegionLock);