add missing fault handlers instead of throwing everything into the GP bin, add more ways to crash in native shell
This commit is contained in:
1 parent
e1248f4afe
commit
03bf767ac2
9 files changed
+387
-50
No files matched your search
Binary file not shown.
+54
-30
@@ -745,36 +745,60 @@ 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++;
|
||||
UINT64 idHoles[8];
|
||||
UINT64 winHoles[8];
|
||||
UINTN idHoleCount = 0;
|
||||
UINTN winHoleCount = 0;
|
||||
|
||||
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;
|
||||
// Leave virtual page zero genuinely unmapped. Mapping it supervisor/NX
|
||||
// still hides null pointer bugs from the page-fault path and makes
|
||||
// diagnostics worse. The physical-window alias for frame zero remains
|
||||
// available at PHYS_MAP_BASE if low physical memory is ever needed.
|
||||
idHoles[idHoleCount * 2 + 0] = 0;
|
||||
idHoles[idHoleCount * 2 + 1] = PAGE_SIZE;
|
||||
idHoleCount++;
|
||||
|
||||
if (fbBytes) {
|
||||
idHoles[idHoleCount * 2 + 0] = fbBase;
|
||||
idHoles[idHoleCount * 2 + 1] = fbBase + fbBytes;
|
||||
idHoleCount++;
|
||||
|
||||
winHoles[winHoleCount * 2 + 0] = PHYS_MAP_BASE + fbBase;
|
||||
winHoles[winHoleCount * 2 + 1] = PHYS_MAP_BASE + fbBase + fbBytes;
|
||||
winHoleCount++;
|
||||
}
|
||||
|
||||
idHoles[idHoleCount * 2 + 0] = 0xFEC00000ULL;
|
||||
idHoles[idHoleCount * 2 + 1] = 0xFEE01000ULL;
|
||||
idHoleCount++;
|
||||
|
||||
winHoles[winHoleCount * 2 + 0] = PHYS_MAP_BASE + 0xFEC00000ULL;
|
||||
winHoles[winHoleCount * 2 + 1] = PHYS_MAP_BASE + 0xFEE01000ULL;
|
||||
winHoleCount++;
|
||||
|
||||
for (UINTN pass = 0; pass < idHoleCount; pass++) {
|
||||
for (UINTN i = 1; i < idHoleCount; i++) {
|
||||
if (idHoles[i * 2] < idHoles[(i - 1) * 2]) {
|
||||
UINT64 s0 = idHoles[(i - 1) * 2 + 0];
|
||||
UINT64 e0 = idHoles[(i - 1) * 2 + 1];
|
||||
idHoles[(i - 1) * 2 + 0] = idHoles[i * 2 + 0];
|
||||
idHoles[(i - 1) * 2 + 1] = idHoles[i * 2 + 1];
|
||||
idHoles[i * 2 + 0] = s0;
|
||||
idHoles[i * 2 + 1] = e0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (UINTN pass = 0; pass < winHoleCount; pass++) {
|
||||
for (UINTN i = 1; i < winHoleCount; i++) {
|
||||
if (winHoles[i * 2] < winHoles[(i - 1) * 2]) {
|
||||
UINT64 s0 = winHoles[(i - 1) * 2 + 0];
|
||||
UINT64 e0 = winHoles[(i - 1) * 2 + 1];
|
||||
winHoles[(i - 1) * 2 + 0] = winHoles[i * 2 + 0];
|
||||
winHoles[(i - 1) * 2 + 1] = winHoles[i * 2 + 1];
|
||||
winHoles[i * 2 + 0] = s0;
|
||||
winHoles[i * 2 + 1] = e0;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -791,8 +815,8 @@ EFI_STATUS EFIAPI UefiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable
|
||||
// memory because of buggy UEFI size reporting.
|
||||
end += 2 * PAGE_SIZE;
|
||||
|
||||
MapRangeSkipping(start, start, end - start, 0x03, idHoles, holeCount);
|
||||
MapRangeSkipping(PHYS_MAP_BASE + start, start, end - start, 0x03, winHoles, holeCount);
|
||||
MapRangeSkipping(start, start, end - start, 0x03, idHoles, idHoleCount);
|
||||
MapRangeSkipping(PHYS_MAP_BASE + start, start, end - start, 0x03, winHoles, winHoleCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+65
-14
@@ -76,16 +76,66 @@ __declspec(dllexport) void KePrintConsole(const char* buf, size_t len) {
|
||||
// can continue running everything else.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Return the short exception name for a vector number.
|
||||
// Return the short exception name for a CPU exception vector.
|
||||
// Keep this table complete for vectors 0..31 so faults never collapse into
|
||||
// a vague "general protection" bucket just because the IDT entry existed
|
||||
// first or the crash printer lacked a name.
|
||||
static const char* KiFaultVectorName(int vector) {
|
||||
switch (vector) {
|
||||
case 0: return "#DE Divide Error";
|
||||
case 1: return "#DB Debug";
|
||||
case 2: return "NMI Interrupt";
|
||||
case 3: return "#BP Breakpoint";
|
||||
case 4: return "#OF Overflow";
|
||||
case 5: return "#BR Bound Range Exceeded";
|
||||
case 6: return "#UD Invalid Opcode";
|
||||
case 7: return "#NM Device Not Available";
|
||||
case 8: return "#DF Double Fault";
|
||||
case 9: return "Coprocessor Segment Overrun";
|
||||
case 10: return "#TS Invalid TSS";
|
||||
case 11: return "#NP Segment Not Present";
|
||||
case 12: return "#SS Stack-Segment Fault";
|
||||
case 13: return "#GP General Protection";
|
||||
case 14: return "#PF Page Fault";
|
||||
case 15: return "Reserved Exception 15";
|
||||
case 16: return "#MF x87 Floating-Point Exception";
|
||||
case 17: return "#AC Alignment Check";
|
||||
case 18: return "#MC Machine Check";
|
||||
case 19: return "#XM SIMD Floating-Point Exception";
|
||||
case 20: return "#VE Virtualization Exception";
|
||||
case 21: return "#CP Control Protection Exception";
|
||||
case 22: return "Reserved Exception 22";
|
||||
case 23: return "Reserved Exception 23";
|
||||
case 24: return "Reserved Exception 24";
|
||||
case 25: return "Reserved Exception 25";
|
||||
case 26: return "Reserved Exception 26";
|
||||
case 27: return "Reserved Exception 27";
|
||||
case 28: return "#HV Hypervisor Injection Exception";
|
||||
case 29: return "#VC VMM Communication Exception";
|
||||
case 30: return "#SX Security Exception";
|
||||
case 31: return "Reserved Exception 31";
|
||||
default: return "Unknown Exception";
|
||||
}
|
||||
}
|
||||
|
||||
static int KiFaultHasErrorCode(int vector) {
|
||||
switch (vector) {
|
||||
case 8: // #DF
|
||||
case 10: // #TS
|
||||
case 11: // #NP
|
||||
case 12: // #SS
|
||||
case 13: // #GP
|
||||
case 14: // #PF
|
||||
case 17: // #AC
|
||||
case 21: // #CP
|
||||
case 29: // #VC
|
||||
case 30: // #SX
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Walk the process module list to find which image owns an address.
|
||||
// Returns the module name string, or "unknown" if the address is outside all
|
||||
// known image ranges. Base/size are optional and are useful for offset dumps.
|
||||
@@ -391,22 +441,23 @@ __declspec(dllexport) _Noreturn void KeFaultDispatchFrame(const KFAULT_FRAME* fr
|
||||
}
|
||||
|
||||
if ((frame->Cs & 3) == 0) {
|
||||
switch ((int)frame->Vector) {
|
||||
case 0:
|
||||
KePanic("PANIC: #DE Divide Error | RIP: %016llx\n",
|
||||
(unsigned long long)frame->Rip);
|
||||
case 13:
|
||||
KePanic("PANIC: #GP General Protection | RIP: %016llx | Code: %04llx\n",
|
||||
(unsigned long long)frame->Rip,
|
||||
(unsigned long long)frame->ErrorCode);
|
||||
case 14:
|
||||
KePanic("PANIC: #PF Page Fault | RIP: %016llx | Code: %04llx | CR2: %016llx\n",
|
||||
int vector = (int)frame->Vector;
|
||||
const char* name = KiFaultVectorName(vector);
|
||||
|
||||
if (vector == 14) {
|
||||
KePanic("PANIC: %s | RIP: %016llx | Code: %04llx | CR2: %016llx\n",
|
||||
name,
|
||||
(unsigned long long)frame->Rip,
|
||||
(unsigned long long)frame->ErrorCode,
|
||||
(unsigned long long)frame->Cr2);
|
||||
default:
|
||||
KePanic("PANIC: Exception #%llu | RIP: %016llx\n",
|
||||
(unsigned long long)frame->Vector,
|
||||
} else if (KiFaultHasErrorCode(vector)) {
|
||||
KePanic("PANIC: %s | RIP: %016llx | Code: %04llx\n",
|
||||
name,
|
||||
(unsigned long long)frame->Rip,
|
||||
(unsigned long long)frame->ErrorCode);
|
||||
} else {
|
||||
KePanic("PANIC: %s | RIP: %016llx\n",
|
||||
name,
|
||||
(unsigned long long)frame->Rip);
|
||||
}
|
||||
}
|
||||
|
||||
+47
-3
@@ -41,6 +41,36 @@ extern void KeIrqStub21(void);
|
||||
extern void KeIrqStub22(void);
|
||||
extern void KeIrqStub23(void);
|
||||
|
||||
extern void KeFaultDB(void);
|
||||
extern void KeFaultNMI(void);
|
||||
extern void KeFaultBP(void);
|
||||
extern void KeFaultOF(void);
|
||||
extern void KeFaultBR(void);
|
||||
extern void KeFaultUD(void);
|
||||
extern void KeFaultNM(void);
|
||||
extern void KeFaultDF(void);
|
||||
extern void KeFaultCSO(void);
|
||||
extern void KeFaultTS(void);
|
||||
extern void KeFaultNP(void);
|
||||
extern void KeFaultSS(void);
|
||||
extern void KeFaultRSV15(void);
|
||||
extern void KeFaultMF(void);
|
||||
extern void KeFaultAC(void);
|
||||
extern void KeFaultMC(void);
|
||||
extern void KeFaultXM(void);
|
||||
extern void KeFaultVE(void);
|
||||
extern void KeFaultCP(void);
|
||||
extern void KeFaultRSV22(void);
|
||||
extern void KeFaultRSV23(void);
|
||||
extern void KeFaultRSV24(void);
|
||||
extern void KeFaultRSV25(void);
|
||||
extern void KeFaultRSV26(void);
|
||||
extern void KeFaultRSV27(void);
|
||||
extern void KeFaultHV(void);
|
||||
extern void KeFaultVC(void);
|
||||
extern void KeFaultSX(void);
|
||||
extern void KeFaultRSV31(void);
|
||||
|
||||
#define NUM_IRQS 24
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -150,9 +180,23 @@ static void KiIdtSetGate(int vec, uintptr_t handler,
|
||||
void KeInitializeIdt(void) {
|
||||
memset(gIdt, 0, sizeof(gIdt));
|
||||
|
||||
KiIdtSetGate(0, (uintptr_t)KeFaultDE, 0x8E, 0);
|
||||
KiIdtSetGate(13, (uintptr_t)KeFaultGP, 0x8E, 0);
|
||||
KiIdtSetGate(14, (uintptr_t)KeFaultPF, 0x8E, 0);
|
||||
static void* faultStubs[32] = {
|
||||
(void*)KeFaultDE, (void*)KeFaultDB, (void*)KeFaultNMI,
|
||||
(void*)KeFaultBP, (void*)KeFaultOF, (void*)KeFaultBR,
|
||||
(void*)KeFaultUD, (void*)KeFaultNM, (void*)KeFaultDF,
|
||||
(void*)KeFaultCSO, (void*)KeFaultTS, (void*)KeFaultNP,
|
||||
(void*)KeFaultSS, (void*)KeFaultGP, (void*)KeFaultPF,
|
||||
(void*)KeFaultRSV15, (void*)KeFaultMF, (void*)KeFaultAC,
|
||||
(void*)KeFaultMC, (void*)KeFaultXM, (void*)KeFaultVE,
|
||||
(void*)KeFaultCP, (void*)KeFaultRSV22, (void*)KeFaultRSV23,
|
||||
(void*)KeFaultRSV24, (void*)KeFaultRSV25, (void*)KeFaultRSV26,
|
||||
(void*)KeFaultRSV27, (void*)KeFaultHV, (void*)KeFaultVC,
|
||||
(void*)KeFaultSX, (void*)KeFaultRSV31,
|
||||
};
|
||||
|
||||
for (int i = 0; i < 32; i++)
|
||||
KiIdtSetGate(i, (uintptr_t)faultStubs[i], 0x8E, 0);
|
||||
|
||||
KiIdtSetGate(0x40, (uintptr_t)KeSyscallEntry, 0xEE, 0);
|
||||
|
||||
static void *irqStubs[NUM_IRQS] = {
|
||||
|
||||
@@ -32,3 +32,4 @@ extern void KeSyscallEntry(void);
|
||||
extern void KeFaultDE(void); // #DE divide error
|
||||
extern void KeFaultGP(void); // #GP general protection
|
||||
extern void KeFaultPF(void); // #PF page fault
|
||||
extern void KeFaultUD(void); // #UD invalid opcode
|
||||
@@ -477,6 +477,24 @@ static void KiRunIrpKernelApcSelfTest(const HAL_API* hal) {
|
||||
|
||||
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Virtual memory mapping invariants
|
||||
// -------------------------------------------------------------------------
|
||||
static void KiRunMemoryMappingSelfTest(void) {
|
||||
PHYSICAL_ADDRESS phys = 0;
|
||||
uint64_t flags = 0;
|
||||
KSTATUS s = MmQueryPage(0, &phys, &flags);
|
||||
if (s != STATUS_NOT_FOUND) {
|
||||
KePanic("MM selftest: virtual page zero is mapped phys=%016llx flags=%016llx status=%u\n",
|
||||
(unsigned long long)phys,
|
||||
(unsigned long long)flags,
|
||||
(unsigned)s);
|
||||
}
|
||||
|
||||
DbgPrint("MM selftest: page zero unmapped\n");
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// String-view ABI self-test
|
||||
// -------------------------------------------------------------------------
|
||||
@@ -732,6 +750,7 @@ static void KiRunTrapFrameSelfTest(void) {
|
||||
void KiRunKernelSelfTests(const HAL_API* hal) {
|
||||
DbgPrint("Kernel selftests: begin\n");
|
||||
KiRunKernelApcSelfTest();
|
||||
KiRunMemoryMappingSelfTest();
|
||||
KiRunStringViewSelfTest();
|
||||
KiRunIrpKernelApcSelfTest(hal);
|
||||
KiRunAsyncFileIoSelfTest();
|
||||
|
||||
@@ -377,6 +377,167 @@ pf_call:
|
||||
call KeFaultDispatchFrame
|
||||
KeFaultPF ENDP
|
||||
|
||||
|
||||
; ---------------------------------------------------------
|
||||
; Generic CPU exception stubs.
|
||||
; Each vector gets its own IDT entry and vector number so faults like #UD
|
||||
; do not fall through an absent descriptor and reappear as #GP.
|
||||
; ---------------------------------------------------------
|
||||
FAULT_NOERR MACRO StubName, VecNum
|
||||
LOCAL noerr_kernel_frame, noerr_call
|
||||
StubName PROC
|
||||
push rax
|
||||
push r11
|
||||
mov r11, rsp
|
||||
sub rsp, KFAULT_SIZE
|
||||
mov rax, rsp
|
||||
mov [rax + KF_R10], r10
|
||||
|
||||
mov r10, KFAULT_MAGIC
|
||||
mov [rax + KF_Magic], r10
|
||||
mov qword ptr [rax + KF_Vector], VecNum
|
||||
mov qword ptr [rax + KF_ErrorCode], 0
|
||||
mov qword ptr [rax + KF_Cr2], 0
|
||||
|
||||
mov [rax + KF_Rcx], rcx
|
||||
mov [rax + KF_Rdx], rdx
|
||||
mov [rax + KF_Rbx], rbx
|
||||
mov [rax + KF_Rbp], rbp
|
||||
mov [rax + KF_Rsi], rsi
|
||||
mov [rax + KF_Rdi], rdi
|
||||
mov [rax + KF_R8], r8
|
||||
mov [rax + KF_R9], r9
|
||||
mov r10, [r11]
|
||||
mov [rax + KF_R11], r10
|
||||
mov r10, [r11+8]
|
||||
mov [rax + KF_Rax], r10
|
||||
mov [rax + KF_R12], r12
|
||||
mov [rax + KF_R13], r13
|
||||
mov [rax + KF_R14], r14
|
||||
mov [rax + KF_R15], r15
|
||||
|
||||
lea rdx, [r11+16]
|
||||
mov r10, [rdx]
|
||||
mov [rax + KF_Rip], r10
|
||||
mov r10, [rdx+8]
|
||||
mov [rax + KF_Cs], r10
|
||||
mov r10, [rdx+16]
|
||||
mov [rax + KF_Rflags], r10
|
||||
|
||||
mov r10, [rax + KF_Cs]
|
||||
test r10, 3
|
||||
jz noerr_kernel_frame
|
||||
mov r10, [rdx+24]
|
||||
mov [rax + KF_Rsp], r10
|
||||
mov r10, [rdx+32]
|
||||
mov [rax + KF_Ss], r10
|
||||
jmp noerr_call
|
||||
|
||||
noerr_kernel_frame:
|
||||
mov qword ptr [rax + KF_Rsp], 0
|
||||
mov qword ptr [rax + KF_Ss], 0
|
||||
|
||||
noerr_call:
|
||||
and rsp, -16
|
||||
sub rsp, FAULT_CALL_SHADOW
|
||||
mov rcx, rax
|
||||
call KeFaultDispatchFrame
|
||||
StubName ENDP
|
||||
ENDM
|
||||
|
||||
FAULT_ERR MACRO StubName, VecNum
|
||||
LOCAL err_kernel_frame, err_call
|
||||
StubName PROC
|
||||
push rax
|
||||
push r11
|
||||
mov r11, rsp
|
||||
sub rsp, KFAULT_SIZE
|
||||
mov rax, rsp
|
||||
mov [rax + KF_R10], r10
|
||||
|
||||
mov r10, KFAULT_MAGIC
|
||||
mov [rax + KF_Magic], r10
|
||||
mov qword ptr [rax + KF_Vector], VecNum
|
||||
mov qword ptr [rax + KF_Cr2], 0
|
||||
|
||||
mov [rax + KF_Rcx], rcx
|
||||
mov [rax + KF_Rdx], rdx
|
||||
mov [rax + KF_Rbx], rbx
|
||||
mov [rax + KF_Rbp], rbp
|
||||
mov [rax + KF_Rsi], rsi
|
||||
mov [rax + KF_Rdi], rdi
|
||||
mov [rax + KF_R8], r8
|
||||
mov [rax + KF_R9], r9
|
||||
mov r10, [r11]
|
||||
mov [rax + KF_R11], r10
|
||||
mov r10, [r11+8]
|
||||
mov [rax + KF_Rax], r10
|
||||
mov [rax + KF_R12], r12
|
||||
mov [rax + KF_R13], r13
|
||||
mov [rax + KF_R14], r14
|
||||
mov [rax + KF_R15], r15
|
||||
|
||||
lea rdx, [r11+16]
|
||||
mov r10, [rdx]
|
||||
mov [rax + KF_ErrorCode], r10
|
||||
mov r10, [rdx+8]
|
||||
mov [rax + KF_Rip], r10
|
||||
mov r10, [rdx+16]
|
||||
mov [rax + KF_Cs], r10
|
||||
mov r10, [rdx+24]
|
||||
mov [rax + KF_Rflags], r10
|
||||
|
||||
mov r10, [rax + KF_Cs]
|
||||
test r10, 3
|
||||
jz err_kernel_frame
|
||||
mov r10, [rdx+32]
|
||||
mov [rax + KF_Rsp], r10
|
||||
mov r10, [rdx+40]
|
||||
mov [rax + KF_Ss], r10
|
||||
jmp err_call
|
||||
|
||||
err_kernel_frame:
|
||||
mov qword ptr [rax + KF_Rsp], 0
|
||||
mov qword ptr [rax + KF_Ss], 0
|
||||
|
||||
err_call:
|
||||
and rsp, -16
|
||||
sub rsp, FAULT_CALL_SHADOW
|
||||
mov rcx, rax
|
||||
call KeFaultDispatchFrame
|
||||
StubName ENDP
|
||||
ENDM
|
||||
|
||||
FAULT_NOERR KeFaultDB, 1
|
||||
FAULT_NOERR KeFaultNMI, 2
|
||||
FAULT_NOERR KeFaultBP, 3
|
||||
FAULT_NOERR KeFaultOF, 4
|
||||
FAULT_NOERR KeFaultBR, 5
|
||||
FAULT_NOERR KeFaultUD, 6
|
||||
FAULT_NOERR KeFaultNM, 7
|
||||
FAULT_ERR KeFaultDF, 8
|
||||
FAULT_NOERR KeFaultCSO, 9
|
||||
FAULT_ERR KeFaultTS, 10
|
||||
FAULT_ERR KeFaultNP, 11
|
||||
FAULT_ERR KeFaultSS, 12
|
||||
FAULT_NOERR KeFaultRSV15, 15
|
||||
FAULT_NOERR KeFaultMF, 16
|
||||
FAULT_ERR KeFaultAC, 17
|
||||
FAULT_NOERR KeFaultMC, 18
|
||||
FAULT_NOERR KeFaultXM, 19
|
||||
FAULT_NOERR KeFaultVE, 20
|
||||
FAULT_ERR KeFaultCP, 21
|
||||
FAULT_NOERR KeFaultRSV22, 22
|
||||
FAULT_NOERR KeFaultRSV23, 23
|
||||
FAULT_NOERR KeFaultRSV24, 24
|
||||
FAULT_NOERR KeFaultRSV25, 25
|
||||
FAULT_NOERR KeFaultRSV26, 26
|
||||
FAULT_NOERR KeFaultRSV27, 27
|
||||
FAULT_NOERR KeFaultHV, 28
|
||||
FAULT_ERR KeFaultVC, 29
|
||||
FAULT_ERR KeFaultSX, 30
|
||||
FAULT_NOERR KeFaultRSV31, 31
|
||||
|
||||
EXTERN KeIrqDispatch:PROC
|
||||
EXTERN KiEnterInterrupt:PROC
|
||||
EXTERN KiExitInterrupt:PROC
|
||||
|
||||
@@ -209,7 +209,44 @@ static int runCommand(const char* cmd) {
|
||||
if (strcmp(cmd, "exit") == 0) return 1;
|
||||
if (strcmp(cmd, "help") == 0) { cmd_help(); return 0; }
|
||||
if (strcmp(cmd, "clear") == 0) { SysScreenClear(0); return 0; }
|
||||
if (strcmp(cmd, "crash") == 0) { *(int*)0 = 42; return 0; }
|
||||
if (strncmp(cmd, "crash", 5) == 0) {
|
||||
// Check the sub-option trailing "crash " (offset 6)
|
||||
if (strcmp(cmd + 6, "void") == 0) {
|
||||
// Jumping into the void
|
||||
void (*invalid_func)(void) = NULL;
|
||||
invalid_func();
|
||||
return 0;
|
||||
}
|
||||
else if (strcmp(cmd + 6, "noncanonical") == 0) {
|
||||
// Non-canonical pointer dereference
|
||||
volatile int *ptr = (volatile int*)0x4242424242424242ULL;
|
||||
*ptr = 1337;
|
||||
return 0;
|
||||
}
|
||||
else if (strcmp(cmd + 6, "ud2") == 0) {
|
||||
__ud2();
|
||||
return 0;
|
||||
}
|
||||
else if (strcmp(cmd + 6, "nx") == 0) {
|
||||
// NX / DEP Violation
|
||||
unsigned char code[] = { 0xC3 };
|
||||
void (*execute_stack)(void) = (void (*)(void))code;
|
||||
execute_stack();
|
||||
return 0;
|
||||
}
|
||||
else if (strcmp(cmd + 6, "divzero") == 0) {
|
||||
// Division by zero
|
||||
volatile int zero = 0;
|
||||
volatile int result = 1 / zero;
|
||||
(void)result;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
// Default fallback if just "crash" or an unknown sub-option is passed
|
||||
*(volatile int*)0 = 42;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (strcmp(cmd, "mem") == 0) { cmd_mem(); return 0; }
|
||||
if (strcmp(cmd, "dir") == 0) { cmd_dir("."); return 0; }
|
||||
if (strncmp(cmd, "dir ", 4) == 0) { cmd_dir(cmd + 4); return 0; }
|
||||
|
||||
@@ -10,7 +10,7 @@ NT-Lite is a 64-bit operating system kernel written from scratch. It has a UEFI
|
||||
|
||||
It boots into a shell, launches user processes, survives application crashes, and can run things it probably should not be able to run yet.
|
||||
|
||||
The codebase is still small enough to understand, but large enough to hurt your feelings. The kernel is just 7k lines of code and the entire project is about 15k lines.
|
||||
The codebase is still small enough to understand, but large enough to hurt your feelings. The kernel is just 10k lines of code and the entire project is about 20k lines.
|
||||
|
||||
## features
|
||||
|
||||
@@ -295,7 +295,7 @@ Q: How often does it crash?
|
||||
A: Like Windows 11.
|
||||
|
||||
Q: Can it recover from a crash?
|
||||
A: Yes. Unless the kernel faulted.
|
||||
A: Works on my machine.
|
||||
|
||||
Q: Is this finished?
|
||||
A: No. And it never will be.
|
||||
|
||||
Reference in new issue
Block a user