fix: plug memory map leak, save sp_el0, dynamic UART, kill loop

- Bootloader: reallocate memory map buffer when ExitBootServices fails,
  so GetMemoryMap doesn't scribble past the old allocation on retry.
- vectors.S: actually store sp_el0 into the exception frame. Previously
  it was read into x24 and then… vanished. EL0 tasks would wake up with
  a corrupted stack pointer. Not great.
- Serial: split hardcoded 0x09000000 into a fallback default; add
  SerialUpdate() so the DTB-parsed UART address actually gets used.
- DTB: add bounds check on reserved[] with PMM's 3 extra slots accounted
  for, so malformed/overstuffed DTBs don't silently corrupt memory.
- PMM.h: bump kVMMaxReservedRegions 128→256, define kPMMReservedRegionCount.
- Types.h: remove `#define loop while(1)`. while(true) is fine.
- Rename IOSerial* → Serial* — the IO prefix was redundant, Serial.c
  already lives under IO/.
This commit is contained in:
karina
2026-05-03 00:32:30 +04:00
parent 7ff9f4ad4c
commit 6dd68f8162
11 changed files with 47 additions and 28 deletions
+4 -3
View File
@@ -2,8 +2,9 @@
#include <Types.h>
enum {
kUARTBaseAddress = 0x09000000, // TODO: make it dynamic by parsing DTB
kUARTBaseAddress = 0x09000000,
};
Int32 IOSerialPutCharacter(ASCII character);
Int32 IOSerialPutString(const ASCII* string);
void SerialUpdate(UInt64 address);
Int32 SerialPutCharacter(ASCII character);
Int32 SerialPutString(const ASCII* string);
+1 -2
View File
@@ -12,7 +12,7 @@
typedef unsigned char UInt8;
typedef unsigned short UInt16;
typedef unsigned int UInt32;
typedef unsigned long long UInt64;
typedef unsigned long long UInt64;
typedef unsigned long long UInt;
typedef void* Pointer;
@@ -31,4 +31,3 @@ typedef UInt64 Size;
typedef char ASCII;
typedef _Bool Boolean;
#define loop while (1)
+3 -2
View File
@@ -4,7 +4,8 @@
enum {
kVMPageSize = 4096,
kVMBlocksPerByte = 8,
kVMMaxReservedRegions = 128,
kVMMaxReservedRegions = 256,
kPMMReservedRegionCount = 3,
};
typedef struct {
@@ -28,4 +29,4 @@ typedef struct {
void PMMInitialize(VMBootMemoryMap* bootMap);
Pointer PMMAllocatePage();
void PMMFreePage(Address address);
void PMMFreePage(Address address);
+7 -4
View File
@@ -24,10 +24,13 @@ void DTBParse(Pointer dtb, VMBootMemoryMap* bootMap) {
ASCII* currentNode = "";
UInt32 currentDepth = 0;
UInt32 reservedMemoryDepth = 0;
UInt32 reservedMemoryDepth = 0;
Boolean inReservedMemory = false;
while (true) {
if (bootMap->reservedCount + kPMMReservedRegionCount >= kVMMaxReservedRegions) {
OSPanic("Too many reserved memory regions!"); // should never occur but jic
}
UInt32 token = BytesSwap32(*(UInt32*)structs);
structs += 4;
@@ -81,7 +84,7 @@ void DTBParse(Pointer dtb, VMBootMemoryMap* bootMap) {
bootMap->GIC.GICD.base = Merge32To64(BytesSwap32(cells[1]), BytesSwap32(cells[0]));
bootMap->GIC.GICD.size = Merge32To64(BytesSwap32(cells[3]), BytesSwap32(cells[2]));
bootMap->GIC.GICC.base = Merge32To64(BytesSwap32(cells[5]), BytesSwap32(cells[4]));
bootMap->GIC.GICC.size = Merge32To64(BytesSwap32(cells[7]), BytesSwap32(cells[6]));
}
@@ -99,7 +102,7 @@ void DTBParse(Pointer dtb, VMBootMemoryMap* bootMap) {
currentDepth--;
break;
}
case FDTTokenNOP: continue;
case FDTTokenEnd: return;
default:
@@ -107,4 +110,4 @@ void DTBParse(Pointer dtb, VMBootMemoryMap* bootMap) {
}
}
}
}
+3 -2
View File
@@ -1,7 +1,7 @@
.macro ventry type
.align 7
sub sp, sp, #288 // save 288 bytes of stack
stp x0, x1, [sp, #0] // move stack
stp x0, x1, [sp, #0] // move stack
mov x1, #\type // move type to x1
b ExceptionsTrapEntry
.endm
@@ -54,6 +54,7 @@ ExceptionsTrapEntry:
stp x30, x21, [sp, #16 * 15]
stp x22, x23, [sp, #16 * 16]
stp x24, xzr, [sp, #16 * 17]
mov x0, sp
bl ExceptionsHandler
@@ -92,4 +93,4 @@ ExceptionsVectorsInit:
adr x0, ExceptionsVectorsTable
msr vbar_el1, x0
isb
ret
ret
+11 -5
View File
@@ -2,22 +2,28 @@
#include <Arch/IO.h>
#include <Arch/CPU.h>
Int32 IOSerialPutCharacter(ASCII character) {
static UInt64 sUARTAddress = kUARTBaseAddress;
void SerialUpdate(UInt64 address) {
sUARTAddress = address;
}
Int32 SerialPutCharacter(ASCII character) {
// TXFF -- TRansmit FIFO Full for PL011 is 5 bit of FR reg (0x18)
UInt64 uartFR = kUARTBaseAddress + 0x18;
UInt64 uartFR = sUARTAddress + 0x18;
while ((IOAddressRead32(uartFR) & (1 << 5)) != 0) {
CPUYield();
}
IOAddressWrite32(kUARTBaseAddress, character);
IOAddressWrite32(sUARTAddress, character);
return character;
}
Int32 IOSerialPutString(const ASCII* string) {
Int32 SerialPutString(const ASCII* string) {
Int i = 0;
while (string[i] != '\0') {
IOSerialPutCharacter(string[i]);
SerialPutCharacter(string[i]);
i++;
}
+3 -1
View File
@@ -3,6 +3,7 @@
#include <Arch/Timer.h>
#include <Arch/CPU.h>
#include <Arch/GIC.h>
#include <IO/Serial.h>
#include <VM/PMM.h>
#include <VM/VMM.h>
#include <VM/Heap.h>
@@ -17,9 +18,10 @@ void KernelMain(Bootinfo* bootinfo) {
}
VMBootMemoryMap bootMap = {0};
bootMap.reservedCount = 0;
DTBParse(bootinfo->dtb, &bootMap);
SerialUpdate(bootMap.UART.base);
PMMInitialize(&bootMap);
VMMInitialize(&bootMap, bootinfo);
+3 -3
View File
@@ -5,11 +5,11 @@
void OSLog(const ASCII* format, ...) {
ASCII buffer[kOSLogBufferSize];
va_list args;
va_start(args, format);
StringFormatVariadic(buffer, kOSLogBufferSize, format, args);
va_end(args);
IOSerialPutString(buffer);
}
SerialPutString(buffer);
}
+2 -2
View File
@@ -40,7 +40,7 @@ static const ASCII* sFunMessages[] = {
};
__attribute__((noreturn)) static void Halt() {
loop {
while (true) {
CPUDisableInterrupts();
CPUWaitForInterrupt();
}
@@ -134,4 +134,4 @@ __attribute__((noreturn)) void OSPanicException(ExceptionsContext* frame) {
DrawPanicFooter();
Halt();
}
}
+4 -4
View File
@@ -85,11 +85,11 @@ Address SchedulerNext(Address stackPointer) {
if (taskIterator->sleepTicks > 0) taskIterator->sleepTicks--;
taskIterator = taskIterator->next;
} while (taskIterator != gOSSchedulerCurrentTask->next);
if (gOSSchedulerCurrentTask->sleepTicks > 0) gOSSchedulerCurrentTask->sleepTicks--;
OSTask* nextTask = gOSSchedulerCurrentTask->next;
loop {
while (true) {
if (nextTask->state == OSTaskStateDead) {
nextTask = nextTask->next;
if (nextTask == gOSSchedulerCurrentTask) OSPanic("No running tasks");
@@ -110,7 +110,7 @@ Address SchedulerNext(Address stackPointer) {
CPUSwitchAddressSpace(physicalL0Table);
}
gOSSchedulerCurrentTask = nextTask;
return gOSSchedulerCurrentTask->stackPointer;
}
@@ -118,4 +118,4 @@ void SchedulerYield(UInt64 ticks) {
gOSSchedulerCurrentTask->sleepTicks = ticks;
gOSSchedulerCurrentTask->state = OSTaskStateSleeping;
CPUException(kOSSchedulerExceptionNumber);
}
}