From 9c91a4d8e309d27e53ff5a4cccf5721b997f93b8 Mon Sep 17 00:00:00 2001 From: Chloe M Date: Sat, 11 Jul 2026 00:21:45 -0400 Subject: [PATCH] ptos/amd64+ke: Add bugcheck support Signed-off-by: Chloe M --- service/ptos/arch/amd64/ke/bugcheck.S | 40 ++++++++++++++++++ service/ptos/head/ke/bugcheck.h | 42 +++++++++++++++++++ service/ptos/ke/bugcheck.c | 59 +++++++++++++++++++++++++++ 3 files changed, 141 insertions(+) create mode 100644 service/ptos/arch/amd64/ke/bugcheck.S create mode 100644 service/ptos/head/ke/bugcheck.h create mode 100644 service/ptos/ke/bugcheck.c diff --git a/service/ptos/arch/amd64/ke/bugcheck.S b/service/ptos/arch/amd64/ke/bugcheck.S new file mode 100644 index 0000000..eae4e92 --- /dev/null +++ b/service/ptos/arch/amd64/ke/bugcheck.S @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2026, Chloe M. + * Provided under the BSD-3 clause. + * + * Description: AMD64 bugcheck wrapper + * Author: Chloe M. + */ + + .text + .globl KeBugCheck +KeBugCheck: + cli /* Disable interrupts */ + cld /* Just in case */ + mov $1, %rax /* Prep the lock */ + xchg %rax, MpLock /* Acquire the lock */ + or %rax, %rax /* Are we another core? */ + jnz .LockOut /* Yes, lock out */ + + /* + * During most cases in which an interrupt occurs, the processor + * is to automatically switch to its own interrupt stack and during + * such cases it is guaranteed that the stack is safe. However, we still + * cannot trust the stack as we do not know if we are coming from an interrupt + * or not and thus need to update it to avoid dodgy states from worsening our + * problem... Whatever it is... + */ + lea StackTop(%rip), %rsp + + /* From here we can call the actual bugcheck handler */ + call KiBugCheck +.LockOut: + hlt + jmp .LockOut + + .section .data +MpLock: .quad 0 + +/* Our bugcheck stack */ +Stack: .fill 4096, 1, 0 +StackTop: diff --git a/service/ptos/head/ke/bugcheck.h b/service/ptos/head/ke/bugcheck.h new file mode 100644 index 0000000..7cad9ff --- /dev/null +++ b/service/ptos/head/ke/bugcheck.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2026, Chloe M. + * Provided under the BSD-3 clause. + * + * Description: Bugcheck interface + * Author: Chloe M. + */ + +#ifndef _KE_BUGCHECK_H_ +#define _KE_BUGCHECK_H_ 1 + +#include + +/* + * A list of reasons to why a bug check can happen + * + * @BUGCHECK_MISC: Misc reason + * @BUGCHECK_OOM: Out of memory during critical operation + * @BUGCHECK_IO_ERROR: Fatal I/O error + * @BUGCHECK_UNBOUND_RESRC: Fatal unbound resource + * @BUGCHECK_EXCEPTION: Fatal exception + */ +typedef enum { + BUGCHECK_MISC, + BUGCHECK_OOM, + BUGCHECK_IO_ERROR, + BUGCHECK_UNBOUND_RESRC, + BUGCHECK_EXCEPTION +} BUGCHECK_REASON; + +/* + * Signal to the user that something has gone terribly wrong + * during system operation and that the machine needs to come to + * a screetching halt. + * + * @Reason: Broad reason of bugcheck + * @Fmt: Format specifier + * @<...>: Variadic arguments + */ +NO_RETURN VOID KeBugCheck(BUGCHECK_REASON Reason, const CHAR *Fmt, ...); + +#endif /* !_KE_BUGCHECK_H_ */ diff --git a/service/ptos/ke/bugcheck.c b/service/ptos/ke/bugcheck.c new file mode 100644 index 0000000..e35a763 --- /dev/null +++ b/service/ptos/ke/bugcheck.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2026, Chloe M. + * Provided under the BSD-3 clause. + * + * Description: Bugcheck handler + * Author: Chloe M. + */ + +#include +#include +#include +#include + +/* Used to safely obtain bugcheck reason */ +#define BUGCHECK_REASON(REASON) \ + ((REASON) >= NELEM(ReasonTable)) \ + ? "bad" \ + : ReasonTable[(REASON)] + +/* Prints the bugcheck banner */ +#define BUGCHECK_BANNER() \ + TRACE( \ + "\033[31;40m! ***** \033[37;40mBUGCHECK \033[31;40m***** !\033[0m\n" \ + ); + +/* Globals to reduce stack usage */ +static va_list Ap; +static CHAR BugCheckBuf[256]; +static CHAR BugCheckMsg[] = + "Something went wrong during system operation and the machine has\n" + "been halted to prevent data loss.\n\n"; + +/* Table of reason strings */ +static CHAR *ReasonTable[] = { + [BUGCHECK_MISC] = "misc reason", + [BUGCHECK_OOM] = "out of memory", + [BUGCHECK_IO_ERROR] = "i/o error", + [BUGCHECK_UNBOUND_RESRC] = "unbounded resource", + [BUGCHECK_EXCEPTION] = "fatal exception" +}; + +VOID +KiBugCheck(BUGCHECK_REASON Reason, const CHAR *Fmt, ...) +{ + /* Enable the console if we don't have one */ + if (!BootVidConsEn()) { + BootVidInitCons(NULL); + } + + va_start(Ap, Fmt); + VFmtPrintf(BugCheckBuf, sizeof(BugCheckBuf), Fmt, Ap); + + BUGCHECK_BANNER(); + TRACE("\033[37;40m"); + TRACE(BugCheckMsg); + TRACE("\033[31;40mbugcheck: \033[37;40m%s", BugCheckBuf); + TRACE("\033[31;40mreason: \033[37;40m%s\n", BUGCHECK_REASON(Reason)); + TRACE("\033[37;40m"); +}