My Project
Loading...
Searching...
No Matches
bugcheck.c
Go to the documentation of this file.
1/*
2 * PROJECT: MatanelOS Kernel
3 * LICENSE: GPLv3
4 * PURPOSE: Bugcheck functions implementation.
5 */
6
7#include "../../includes/me.h"
8#include "../../includes/mg.h"
11#include "../../includes/mh.h"
12#include "../../includes/ps.h"
13
14#ifndef DEBUG
15#define DEBUG
16#endif
17
18 // We require GOP, so we extern it.
20extern bool isBugChecking;
21extern bool smpInitialized;
22
23extern uint32_t cursor_x;
24extern uint32_t cursor_y;
25
26// switched to uint64_t and not BUGCHECK_CODES since the custom ones arent in that enum, and compiler throws an error.
27static void resolveStopCode(char** s, uint64_t stopcode) {
28 switch (stopcode) {
29 case DIVIDE_BY_ZERO:
30 *s = "DIVIDE_BY_ZERO";
31 break;
32 case SINGLE_STEP:
33 *s = "SINGLE_STEP";
34 break;
36 *s = "NON_MASKABLE_INTERRUPT";
37 break;
38 case BREAKPOINT:
39 *s = "BREAKPOINT";
40 break;
41 case OVERFLOW:
42 *s = "OVERFLOW";
43 break;
44 case BOUNDS_CHECK:
45 *s = "BOUNDS_CHECK";
46 break;
47 case INVALID_OPCODE:
48 *s = "INVALID_OPCODE";
49 break;
50 case NO_COPROCESSOR:
51 *s = "NO_COPROCESSOR";
52 break;
53 case DOUBLE_FAULT:
54 *s = "DOUBLE_FAULT";
55 break;
57 *s = "COPROCESSOR_SEGMENT_OVERRUN";
58 break;
59 case INVALID_TSS:
60 *s = "INVALID_TSS";
61 break;
63 *s = "SEGMENT_SELECTOR_NOTPRESENT";
64 break;
66 *s = "STACK_SEGMENT_OVERRUN";
67 break;
69 *s = "GENERAL_PROTECTION_FAULT";
70 break;
71 case PAGE_FAULT:
72 *s = "PAGE_FAULT";
73 break;
74 case RESERVED:
75 *s = "RESERVED";
76 break;
78 *s = "FLOATING_POINT_ERROR";
79 break;
80 case ALIGNMENT_CHECK:
81 *s = "ALIGNMENT_CHECK";
82 break;
84 *s = "SEVERE_MACHINE_CHECK";
85 break;
87 *s = "MEMORY_MAP_SIZE_OVERRUN";
88 break;
90 *s = "MANUALLY_INITIATED_CRASH";
91 break;
92 case BAD_PAGING:
93 *s = "BAD_PAGING";
94 break;
96 *s = "BLOCK_DEVICE_LIMIT_REACHED";
97 break;
99 *s = "NULL_POINTER_DEREFERENCE";
100 break;
101 case FILESYSTEM_PANIC:
102 *s = "FILESYSTEM_PANIC";
103 break;
105 *s = "UNABLE_TO_INIT_TRACELASTFUNC";
106 break;
108 *s = "FRAME_LIMIT_REACHED";
109 break;
111 *s = "IRQL_NOT_LESS_OR_EQUAL";
112 break;
114 *s = "INVALID_IRQL_SUPPLIED";
115 break;
117 *s = "NULL_CTX_RECEIVED";
118 break;
120 *s = "THREAD_EXIT_FAILURE";
121 break;
122 case BAD_AHCI_COUNT:
123 *s = "BAD_AHCI_COUNT";
124 break;
125 case AHCI_INIT_FAILED:
126 *s = "AHCI_INIT_FAILED";
127 break;
129 *s = "MEMORY_LIMIT_REACHED";
130 break;
132 *s = "HEAP_ALLOCATION_FAILED";
133 break;
134 case NULL_THREAD:
135 *s = "NULL_THREAD";
136 break;
138 *s = "FATAL_IRQL_CORRUPTION";
139 break;
141 *s = "THREAD_ID_CREATION_FAILURE";
142 break;
144 *s = "ASSERTION_FAILURE";
145 break;
147 *s = "FRAME_ALLOCATION_FAILED";
148 break;
150 *s = "FRAME_BITMAP_CREATION_FAILURE";
151 break;
153 *s = "MEMORY_INVALID_FREE";
154 break;
156 *s = "MEMORY_CORRUPT_HEADER";
157 break;
159 *s = "MEMORY_DOUBLE_FREE";
160 break;
162 *s = "MEMORY_CORRUPT_FOOTER";
163 break;
165 *s = "GUARD_PAGE_DEREFERENCE";
166 break;
168 *s = "IRQL_NOT_GREATER_OR_EQUAL";
169 break;
171 *s = "KERNEL_STACK_OVERFLOWN";
172 break;
173 case BAD_POOL_CALLER:
174 *s = "BAD_POOL_CALLER";
175 break;
177 *s = "KMODE_EXCEPTION_NOT_HANDLED";
178 break;
180 *s = "ATTEMPTED_SWITCH_FROM_DPC";
181 break;
183 *s = "ATTEMPTED_WRITE_TO_READONLY_MEMORY";
184 break;
186 *s = "PSMGR_INIT_FAILED";
187 break;
189 *s = "PAGE_FAULT_IN_FREED_NONPAGED_POOL";
190 break;
192 *s = "PAGE_FAULT_IN_FREED_PAGED_POOL";
193 break;
195 *s = "PSWORKER_INIT_FAILED";
196 break;
198 *s = "MANUALLY_INITIATED_CRASH2";
199 break;
201 *s = "DPC_NOT_INITIALIZED";
202 break;
204 *s = "INVALID_PROCESS_ATTACH_ATTEMPT";
205 break;
206 default:
207 *s = "UNKNOWN_BUGCHECK_CODE";
208 break;
209 }
210}
211
213void
215 IN enum _BUGCHECK_CODES BugCheckCode
216)
217
218/*++
219
220 Routine description : Gracefully crashes the system.
221
222 Arguments:
223
224 [IN] enum _BUGCHECK_CODES BugCheckCode
225
226 Return Values:
227
228 None - This function does not return to caller.
229
230--*/
231
232{
233 // Critical system error, instead of triple faulting, we hang the system with specified error codes.
234 if (smpInitialized) {
235 // If all other cores are online, we obviously want to stop them.
236 IPI_PARAMS dummy = { 0 };
238 }
239 // Disable interrupts if they werent disabled before.
240 __cli();
241
242 // atomically check & set isBugChecking
243 bool prev = InterlockedExchangeBool(&isBugChecking, true);
244
245 if (prev == 1) {
246 __hlt(); // someone set isBugChecking before us, we just halt, let em do their thing.
247 }
248
249 // Acquire exclusive ownership to this processor for framebuffer access.
251
252#ifdef DEBUG
253 IRQL recordedIrql = MeGetCurrentProcessor()->currentIrql;
254#endif
255 // Force to be redrawn from the top, instead of last place.
256 cursor_x = 0;
257 cursor_y = 0;
258 _MeSetIrql(HIGH_LEVEL); // SET the irql to high level (not raise) (we could raise, but this takes less cycles and so is faster) (previous comment was setting an IRQL to each CPU Core, instead, we send an IPI up top)
259
260 // Clear the screen to blue (bsod windows style)
261 gop_clear_screen(&gop_local, 0xFF0035b8);
262 // Write some debugging and an error message
263 gop_printf(0xFFFFFFFF, "FATAL ERROR: Your system has encountered a fatal error.\n\n");
264 gop_printf(0xFFFFFFFF, "Your system has been stopped for safety.\n\n");
265 char* stopCodeToStr = ""; // empty at first.
266 resolveStopCode(&stopCodeToStr, BugCheckCode);
267 gop_printf(0xFFFFFFFF, "**STOP CODE: ");
268 gop_printf(0xFF8B0000, "%s", stopCodeToStr);
269 gop_printf(0xFF00FF00, " (numerical: %d)**\n", BugCheckCode);
270#ifdef DEBUG
271 gop_printf(0xFFFFA500, "**Last IRQL: %d**\n", recordedIrql);
272 gop_printf(0xFFFFA500, "DPC Active: %s\n", (MeGetCurrentProcessor()->DpcRoutineActive) ? "Yes" : "No");
273#endif
275 gop_printf(0xFFFFFF00, "Current Thread ID: %d\n", currTid);
276 if (smpInitialized) {
277 gop_printf(COLOR_LIME, "Sent IPI To all CPUs to HALT.\n");
278 gop_printf(COLOR_LIME, "Current Executing CPU: %d\n", MeGetCurrentProcessor()->lapic_ID);
279 }
280#ifdef DEBUG
281 // Thread information
282 PETHREAD CurrentThread = PsGetCurrentThread();
283 if (CurrentThread) {
284 // Display thread debug info
285 uintptr_t StackBase = (uintptr_t)CurrentThread->InternalThread.StackBase; // high address
286 uintptr_t StackSize = (CurrentThread->InternalThread.IsLargeStack) ? MI_LARGE_STACK_SIZE : MI_STACK_SIZE;
287 uintptr_t StackLimit = StackBase - StackSize; // low address (bottom of stack)
288 uintptr_t ThreadTop = (uintptr_t)CurrentThread->InternalThread.TrapRegisters.rsp;
289 gop_printf(COLOR_WHITE, "Thread Stack Range | %p - %p | Last saved top: %p\n", (void*)StackLimit, (void*)StackBase, (void*)ThreadTop);
290 gop_printf(COLOR_YELLOW, "PreviousMode: %s\n", (MeGetPreviousMode() == KernelMode) ? "KernelMode" : "UserMode");
291 }
292#endif
293 gop_printf(COLOR_YELLOW, "Current CR3: %p\n", (void*)(uintptr_t)__read_cr3());
294 gop_printf(COLOR_YELLOW, "Current stack top: %p\n", (void*)(uintptr_t)__read_rsp());
295 __cli();
296 while (1) {
297 __hlt();
298 __pause();
299 }
300}
301
302
304void
306 IN enum _BUGCHECK_CODES BugCheckCode,
307 IN void* BugCheckParameter1,
308 IN void* BugCheckParameter2,
309 IN void* BugCheckParameter3,
310 IN void* BugCheckParameter4
311)
312
313/*++
314
315 Routine description : Gracefully crashes the system, supplies parameters for debugging by the developer.
316
317 Arguments:
318
319 [IN] enum _BUGCHECK_CODES BugCheckCode
320 [IN] void* BugCheckParameter1
321 [IN] void* BugCheckParameter2
322 [IN] void* BugCheckParameter3
323 [IN] void* BugCheckParameter4
324
325 Return Values:
326
327 None - This function does not return to caller.
328
329 TODO:
330
331 Add minidumps if the filesystem is initialized.
332
333--*/
334
335{
336 // Critical system error, instead of triple faulting, we hang the system with specified error codes.
337 // Disable interrupts if they werent disabled before.
338 __cli();
339 if (smpInitialized) {
340 // If all other cores are online, we obviously want to stop them.
341 IPI_PARAMS dummy = { 0 };
343 }
344
345 // atomically check & set isBugChecking
346 bool prev = InterlockedExchangeBool(&isBugChecking, true);
347
348 if (prev == 1) {
349 while (1) __hlt();
350 }
351
352 // Acquire exclusive ownership to this processor for framebuffer access.
354
355#ifdef DEBUG
356 IRQL recordedIrql = MeGetCurrentProcessor()->currentIrql;
357#endif
358 // Force to be redrawn from the top, instead of last place.
359 cursor_x = 0;
360 cursor_y = 0;
361 _MeSetIrql(HIGH_LEVEL); // SET the irql to high level (not raise) (we could raise, but this takes less cycles and so is faster)
362
363 // Clear the screen to blue (bsod windows style)
364 gop_clear_screen(&gop_local, 0xFF0035b8);
365 // Write some debugging and an error message
366 gop_printf(0xFFFFFFFF, "FATAL ERROR: Your system has encountered a fatal error.\n\n");
367 gop_printf(0xFFFFFFFF, "Your system has been stopped for safety.\n\n");
368 char* stopCodeToStr = ""; // empty at first.
369 resolveStopCode(&stopCodeToStr, BugCheckCode);
370 gop_printf(0xFFFFFFFF, "**STOP CODE: ");
371 gop_printf(0xFF8B0000, "%s", stopCodeToStr);
372 gop_printf(0xFF00FF00, " (numerical: %d)**\n", BugCheckCode);
373 {
374#ifdef DEBUG
375 if (BugCheckCode == ASSERTION_FAILURE) {
376 // Print expression, reason, file, line.
378 "Expression: %s\n"
379 "Reason: %s\n"
380 "File: %s\n"
381 "Line: %lld\n", // Changed to %d since assert_fail passes a decimal number and not a char ptr.
382 (char*)BugCheckParameter1,
383 (char*)BugCheckParameter2,
384 (char*)BugCheckParameter3,
385 (long long)(intptr_t)BugCheckParameter4);
386 }
387 else {
388#endif
389 // Print parameters.
391 "Parameter 1: (Pointer: %p | Decimal: %lld | Pure Hex: %llx)\n"
392 "Parameter 2: (Pointer: %p | Decimal: %lld | Pure Hex: %llx)\n"
393 "Parameter 3: (Pointer: %p | Decimal: %lld | Pure Hex: %llx)\n"
394 "Parameter 4: (Pointer: %p | Decimal: %lld | Pure Hex: %llx)\n",
395 (void*)(uintptr_t)BugCheckParameter1, (long long)(intptr_t)BugCheckParameter1, (unsigned long long)(uintptr_t)BugCheckParameter1,
396 (void*)(uintptr_t)BugCheckParameter2, (long long)(intptr_t)BugCheckParameter2, (unsigned long long)(uintptr_t)BugCheckParameter2,
397 (void*)(uintptr_t)BugCheckParameter3, (long long)(intptr_t)BugCheckParameter3, (unsigned long long)(uintptr_t)BugCheckParameter3,
398 (void*)(uintptr_t)BugCheckParameter4, (long long)(intptr_t)BugCheckParameter4, (unsigned long long)(uintptr_t)BugCheckParameter4);
399#ifdef DEBUG
400 }
401#endif
402 }
403#ifdef DEBUG
404 gop_printf(0xFFFFA500, "**Last IRQL: %d**\n", recordedIrql);
405 gop_printf(0xFFFFA500, "DPC Active: %s\n", (MeGetCurrentProcessor()->DpcRoutineActive) ? "Yes" : "No");
406#endif
408 gop_printf(0xFFFFFF00, "Current Thread ID: %d\n", currTid);
409 if (smpInitialized) {
410 gop_printf(COLOR_LIME, "Sent IPI To all CPUs to HALT.\n");
411 gop_printf(COLOR_LIME, "Current Executing CPU: %d\n", MeGetCurrentProcessor()->lapic_ID);
412 }
413#ifdef DEBUG
414 // Thread information
415 PETHREAD CurrentThread = PsGetCurrentThread();
416 if (CurrentThread) {
417 // Display thread debug info
418 uintptr_t StackBase = (uintptr_t)CurrentThread->InternalThread.StackBase; // high address
419 uintptr_t StackSize = (CurrentThread->InternalThread.IsLargeStack) ? MI_LARGE_STACK_SIZE : MI_STACK_SIZE;
420 uintptr_t StackLimit = StackBase - StackSize; // low address (bottom of stack)
421 uintptr_t ThreadTop = (uintptr_t)CurrentThread->InternalThread.TrapRegisters.rsp;
422 gop_printf(COLOR_WHITE, "Thread Stack Range | %p - %p | Last saved top: %p\n", (void*)StackLimit, (void*)StackBase, (void*)ThreadTop);
423 gop_printf(COLOR_YELLOW, "PreviousMode: %s\n", (MeGetPreviousMode() == KernelMode) ? "KernelMode" : "UserMode");
424 }
425 gop_printf(COLOR_YELLOW, "Current CR3: %p\n", (void*)(uintptr_t)__read_cr3());
426 gop_printf(COLOR_YELLOW, "Current stack top: %p\n", (void*)(uintptr_t)__read_rsp());
427#endif
428 __cli();
429 while (1) {
430 __hlt();
431 __pause();
432 }
433}
#define NORETURN
Definition annotations.h:13
#define IN
Definition annotations.h:7
FORCEINLINE bool InterlockedExchangeBool(volatile bool *target, bool value)
Definition atomic.h:165
NORETURN void MeBugCheck(IN enum _BUGCHECK_CODES BugCheckCode)
Definition bugcheck.c:214
bool smpInitialized
Definition kernel.c:146
bool isBugChecking
Definition kernel.c:19
NORETURN void MeBugCheckEx(IN enum _BUGCHECK_CODES BugCheckCode, IN void *BugCheckParameter1, IN void *BugCheckParameter2, IN void *BugCheckParameter3, IN void *BugCheckParameter4)
Definition bugcheck.c:305
uint32_t cursor_y
Definition gop.c:39
GOP_PARAMS gop_local
Definition gop.c:247
uint32_t cursor_x
Definition gop.c:39
@ HIGH_LEVEL
Definition core.h:20
enum _IRQL IRQL
ETHREAD * PETHREAD
Definition core.h:42
struct _GOP_PARAMS GOP_PARAMS
void MgAcquireExclusiveGopOwnerShip(void)
Definition gop.c:794
void gop_printf(uint32_t color, const char *fmt,...)
Definition gop.c:694
void gop_clear_screen(GOP_PARAMS *gop, uint32_t color)
Definition gop.c:249
int32_t HANDLE
Definition ht.h:59
FORCEINLINE void __pause(void)
Definition intrin.h:224
FORCEINLINE uint64_t __read_rsp(void)
Definition intrin.h:212
FORCEINLINE void __hlt(void)
Definition intrin.h:50
FORCEINLINE void __cli(void)
Definition intrin.h:38
FORCEINLINE uint64_t __read_cr3(void)
Definition intrin.h:78
void _MeSetIrql(IN IRQL NewIrql)
Definition irql.c:153
_BUGCHECK_CODES
Definition me.h:68
@ MANUALLY_INITIATED_CRASH
Definition me.h:90
@ NULL_POINTER_DEREFERENCE
Definition me.h:93
@ OVERFLOW
Definition me.h:73
@ FILESYSTEM_PANIC
Definition me.h:94
@ BAD_POOL_CALLER
Definition me.h:122
@ MEMORY_LIMIT_REACHED
Definition me.h:104
@ SEVERE_MACHINE_CHECK
Definition me.h:87
@ ATTEMPTED_WRITE_TO_READONLY_MEMORY
Definition me.h:123
@ COPROCESSOR_SEGMENT_OVERRUN
Definition me.h:78
@ FRAME_LIMIT_REACHED
Definition me.h:96
@ HEAP_ALLOCATION_FAILED
Definition me.h:105
@ NO_COPROCESSOR
Definition me.h:76
@ MEMORY_CORRUPT_HEADER
Definition me.h:113
@ PAGE_FAULT
Definition me.h:83
@ PAGE_FAULT_IN_FREED_NONPAGED_POOL
Definition me.h:125
@ PSMGR_INIT_FAILED
Definition me.h:130
@ FLOATING_POINT_ERROR
Definition me.h:85
@ GUARD_PAGE_DEREFERENCE
Definition me.h:116
@ MEMORY_INVALID_FREE
Definition me.h:112
@ IRQL_NOT_GREATER_OR_EQUAL
Definition me.h:98
@ THREAD_EXIT_FAILURE
Definition me.h:101
@ ASSERTION_FAILURE
Definition me.h:111
@ MEMORY_MAP_SIZE_OVERRUN
Custom ones.
Definition me.h:89
@ ATTEMPTED_SWITCH_FROM_DPC
Definition me.h:127
@ SINGLE_STEP
Definition me.h:70
@ KMODE_EXCEPTION_NOT_HANDLED
Definition me.h:118
@ DIVIDE_BY_ZERO
Definition me.h:69
@ NULL_THREAD
Definition me.h:106
@ KERNEL_STACK_OVERFLOWN
Definition me.h:117
@ BREAKPOINT
Definition me.h:72
@ ALIGNMENT_CHECK
Definition me.h:86
@ BAD_PAGING
Definition me.h:91
@ BLOCK_DEVICE_LIMIT_REACHED
Definition me.h:92
@ NON_MASKABLE_INTERRUPT
Definition me.h:71
@ INVALID_OPCODE
Definition me.h:75
@ INVALID_TSS
Definition me.h:79
@ FRAME_BITMAP_CREATION_FAILURE
Definition me.h:110
@ BAD_AHCI_COUNT
Definition me.h:102
@ NULL_CTX_RECEIVED
Definition me.h:100
@ MEMORY_DOUBLE_FREE
Definition me.h:114
@ FRAME_ALLOCATION_FAILED
Definition me.h:109
@ DPC_NOT_INITIALIZED
Definition me.h:132
@ UNABLE_TO_INIT_TRACELASTFUNC
Definition me.h:95
@ THREAD_ID_CREATION_FAILURE
Definition me.h:108
@ PAGE_FAULT_IN_FREED_PAGED_POOL
Definition me.h:126
@ PSWORKER_INIT_FAILED
Definition me.h:131
@ DOUBLE_FAULT
Definition me.h:77
@ MANUALLY_INITIATED_CRASH2
Definition me.h:129
@ STACK_SEGMENT_OVERRUN
Definition me.h:81
@ GENERAL_PROTECTION_FAULT
Definition me.h:82
@ SEGMENT_SELECTOR_NOTPRESENT
Definition me.h:80
@ AHCI_INIT_FAILED
Definition me.h:103
@ INVALID_PROCESS_ATTACH_ATTEMPT
Definition me.h:134
@ IRQL_NOT_LESS_OR_EQUAL
Definition me.h:97
@ BOUNDS_CHECK
Definition me.h:74
@ INVALID_IRQL_SUPPLIED
Definition me.h:99
@ FATAL_IRQL_CORRUPTION
Definition me.h:107
@ RESERVED
Definition me.h:84
@ MEMORY_CORRUPT_FOOTER
Definition me.h:115
FORCEINLINE PPROCESSOR MeGetCurrentProcessor(void)
Definition me.h:356
FORCEINLINE PRIVILEGE_MODE MeGetPreviousMode(void)
Definition me.h:534
#define COLOR_YELLOW
Definition mg.h:34
#define COLOR_WHITE
Definition mg.h:32
#define COLOR_LIME
Definition mg.h:44
@ CPU_ACTION_STOP
Definition mh.h:92
struct _IPI_PARAMS IPI_PARAMS
#define MI_LARGE_STACK_SIZE
Definition mm.h:220
@ KernelMode
Definition mm.h:333
#define MI_STACK_SIZE
Definition mm.h:219
void MhSendActionToCpusAndWait(CPU_ACTION action, IPI_PARAMS parameter)
Definition smp.c:212
struct _ITHREAD InternalThread
Definition ps.h:122
HANDLE TID
Definition ps.h:125
void * StackBase
Definition me.h:264
bool IsLargeStack
Definition me.h:265
struct _TRAP_FRAME TrapRegisters
Definition me.h:262
enum _IRQL currentIrql
Definition me.h:276
struct _ITHREAD * currentThread
Definition me.h:278
uint64_t rsp
Definition me.h:160
PETHREAD PsGetCurrentThread(void)
Definition thread.c:191