feat: port gcc to MontaukOS

This commit is contained in:
2026-07-17 15:47:45 +02:00
parent 324b18edda
commit 8e6b619b02
14 changed files with 493 additions and 19 deletions
+43 -3
View File
@@ -78,8 +78,10 @@ namespace Hal {
return frame;
}
template<size_t i>
__attribute__((interrupt)) void ExceptionHandler(System::PanicFrame* frame)
// Shared fatal-exception path: kill the faulting user process (with a
// crash report) or panic the kernel. `frame` is the RAW interrupt frame
// (error code at offset 0 for vectors that push one). Never returns.
static void HandleFatalException(uint8_t i, System::PanicFrame* frame)
{
uint64_t cs = GetExceptionCS(i, frame);
bool fromUser = (cs & 3) == 3;
@@ -165,6 +167,41 @@ namespace Hal {
if (fromUser) asm volatile("swapgs");
}
template<size_t i>
__attribute__((interrupt)) void ExceptionHandler(System::PanicFrame* frame)
{
HandleFatalException(i, frame);
}
// Page faults get a dedicated handler with the proper error-code
// signature (so GCC pops the error code before IRET) because, unlike
// the generic handler, this one can RETURN: a non-present fault in the
// user stack growth region maps a fresh zeroed page and retries the
// faulting instruction. With the two-argument form, `frame` points past
// the error code, directly at the saved IP.
__attribute__((interrupt)) void PageFaultHandler(System::PanicFrame* frame, uint64_t errorCode)
{
bool fromUser = (frame->CS & 3) == 3;
if (fromUser) asm volatile("swapgs");
uint64_t cr2;
asm volatile("mov %%cr2, %0" : "=r"(cr2));
// Bit 0 of the error code: 0 = non-present page. Covers both user
// pushes past the mapped stack and kernel accesses to not-yet-grown
// user stack buffers passed into syscalls.
if ((errorCode & 1) == 0 && Sched::GetCurrentPid() >= 0
&& Sched::TryGrowUserStack(cr2)) {
if (fromUser) asm volatile("swapgs");
return;
}
// Not a growable fault. Hand the RAW frame (error code at offset 0)
// to the fatal path, which re-derives fromUser and swaps GS itself.
if (fromUser) asm volatile("swapgs");
HandleFatalException(0x0E, (System::PanicFrame*)((uint8_t*)frame - 8));
}
void LoadIDT(IDTRStruct& idtr) {
asm("lidt %0" : : "m"(idtr));
}
@@ -208,7 +245,10 @@ namespace Hal {
// Use IST1 for NMI (2) and Double Fault (8) so they get a
// known-good stack even if the kernel stack has overflowed.
uint8_t ist = (I == 2 || I == 8) ? 1 : 0;
IDTEncodeInterrupt(I, (void*)ExceptionHandler<I>, InterruptGate, ist);
// Vector 14 uses the dedicated page fault handler (stack growth).
void* handler = (I == 14) ? (void*)PageFaultHandler
: (void*)ExceptionHandler<I>;
IDTEncodeInterrupt(I, handler, InterruptGate, ist);
SetHandler<I+1,N>::run();
}
};