2e8df660bb8cf5b90ec82e25a4f2415b58232ac7
[reactos.git] / reactos / ntoskrnl / ke / bug.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id$
20 *
21 * PROJECT: ReactOS kernel
22 * FILE: ntoskrnl/ke/bug.c
23 * PURPOSE: Graceful system shutdown if a bug is detected
24 * PROGRAMMER: David Welch (welch@cwcom.net)
25 * PORTABILITY: Unchecked
26 * UPDATE HISTORY:
27 * Created 22/05/98
28 * Phillip Susi: 12/8/99: Minor fix
29 */
30
31 /* INCLUDES *****************************************************************/
32
33 #include <ntoskrnl.h>
34 #include <ntos/bootvid.h>
35 #include <internal/debug.h>
36 #include "../../hal/halx86/include/hal.h"
37
38 /* GLOBALS ******************************************************************/
39
40 static LIST_ENTRY BugcheckCallbackListHead = {NULL,NULL};
41 static ULONG InBugCheck;
42
43 /* FUNCTIONS *****************************************************************/
44
45 VOID INIT_FUNCTION
46 KeInitializeBugCheck(VOID)
47 {
48 InitializeListHead(&BugcheckCallbackListHead);
49 InBugCheck = 0;
50 }
51
52 /*
53 * @implemented
54 */
55 BOOLEAN STDCALL
56 KeDeregisterBugCheckCallback(PKBUGCHECK_CALLBACK_RECORD CallbackRecord)
57 {
58 /* Check the Current State */
59 if (CallbackRecord->State == BufferInserted) {
60 CallbackRecord->State = BufferEmpty;
61 RemoveEntryList(&CallbackRecord->Entry);
62 return TRUE;
63 }
64
65 /* The callback wasn't registered */
66 return FALSE;
67 }
68
69 /*
70 * @implemented
71 */
72 BOOLEAN STDCALL
73 KeRegisterBugCheckCallback(PKBUGCHECK_CALLBACK_RECORD CallbackRecord,
74 PKBUGCHECK_CALLBACK_ROUTINE CallbackRoutine,
75 PVOID Buffer,
76 ULONG Length,
77 PUCHAR Component)
78 {
79
80 /* Check the Current State first so we don't double-register */
81 if (CallbackRecord->State == BufferEmpty) {
82 CallbackRecord->Length = Length;
83 CallbackRecord->Buffer = Buffer;
84 CallbackRecord->Component = Component;
85 CallbackRecord->CallbackRoutine = CallbackRoutine;
86 CallbackRecord->State = BufferInserted;
87 InsertTailList(&BugcheckCallbackListHead, &CallbackRecord->Entry);
88
89 return TRUE;
90 }
91
92 /* The Callback was already registered */
93 return(FALSE);
94 }
95
96 VOID STDCALL
97 KeBugCheckWithTf(ULONG BugCheckCode,
98 ULONG BugCheckParameter1,
99 ULONG BugCheckParameter2,
100 ULONG BugCheckParameter3,
101 ULONG BugCheckParameter4,
102 PKTRAP_FRAME Tf)
103 {
104 PRTL_MESSAGE_RESOURCE_ENTRY Message;
105 NTSTATUS Status;
106 ULONG Mask;
107 KIRQL OldIrql;
108
109 /* Make sure we're switching back to the blue screen and print messages on it */
110 HalReleaseDisplayOwnership();
111 if (0 == (KdDebugState & KD_DEBUG_GDB))
112 {
113 KdDebugState |= KD_DEBUG_SCREEN;
114 }
115
116 Ke386DisableInterrupts();
117 DebugLogDumpMessages();
118
119 if (MmGetKernelAddressSpace()->Lock.Owner == KeGetCurrentThread())
120 {
121 MmUnlockAddressSpace(MmGetKernelAddressSpace());
122 }
123
124 if (KeGetCurrentIrql() < DISPATCH_LEVEL)
125 {
126 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
127 }
128 DbgPrint("Bug detected (code %x param %x %x %x %x)\n",
129 BugCheckCode,
130 BugCheckParameter1,
131 BugCheckParameter2,
132 BugCheckParameter3,
133 BugCheckParameter4);
134
135 Status = RtlFindMessage((PVOID)KERNEL_BASE, //0xC0000000,
136 11, //RT_MESSAGETABLE,
137 0x09, //0x409,
138 BugCheckCode,
139 &Message);
140 if (NT_SUCCESS(Status))
141 {
142 if (Message->Flags == 0)
143 DbgPrint(" %s\n", Message->Text);
144 else
145 DbgPrint(" %S\n", (PWSTR)Message->Text);
146 }
147 else
148 {
149 DbgPrint(" No message text found!\n\n");
150 }
151 Mask = 1 << KeGetCurrentProcessorNumber();
152 if (InBugCheck & Mask)
153 {
154 #ifdef MP
155 DbgPrint("Recursive bug check on CPU%d, halting now\n", KeGetCurrentProcessorNumber());
156 /*
157 * FIXME:
158 * Send an ipi to all other processors which halt them too.
159 */
160 #else
161 DbgPrint("Recursive bug check halting now\n");
162 #endif
163 Ke386HaltProcessor();
164 }
165 /*
166 * FIXME:
167 * Use InterlockedOr or InterlockedBitSet.
168 */
169 InBugCheck |= Mask;
170 if (Tf != NULL)
171 {
172 KiDumpTrapFrame(Tf, BugCheckParameter1, BugCheckParameter2);
173 }
174 else
175 {
176 #if defined(__GNUC__)
177 KeDumpStackFrames((PULONG)__builtin_frame_address(0));
178 #elif defined(_MSC_VER)
179 __asm push ebp
180 __asm call KeDumpStackFrames
181 __asm add esp, 4
182 #else
183 #error Unknown compiler for inline assembler
184 #endif
185 }
186 MmDumpToPagingFile(BugCheckCode, BugCheckParameter1,
187 BugCheckParameter2, BugCheckParameter3,
188 BugCheckParameter4, Tf);
189
190 if (KdDebuggerEnabled)
191 {
192 Ke386EnableInterrupts();
193 DbgBreakPointNoBugCheck();
194 Ke386DisableInterrupts();
195 }
196
197 for (;;)
198 {
199 /*
200 * FIXME:
201 * Send an ipi to all other processors which halt them too.
202 */
203 Ke386HaltProcessor();
204 }
205 }
206
207 /*
208 * @implemented
209 */
210 VOID STDCALL
211 KeBugCheckEx(ULONG BugCheckCode,
212 ULONG BugCheckParameter1,
213 ULONG BugCheckParameter2,
214 ULONG BugCheckParameter3,
215 ULONG BugCheckParameter4)
216 /*
217 * FUNCTION: Brings the system down in a controlled manner when an
218 * inconsistency that might otherwise cause corruption has been detected
219 * ARGUMENTS:
220 * BugCheckCode = Specifies the reason for the bug check
221 * BugCheckParameter[1-4] = Additional information about bug
222 * RETURNS: Doesn't
223 */
224 {
225 KeBugCheckWithTf(BugCheckCode, BugCheckParameter1, BugCheckParameter2,
226 BugCheckParameter3, BugCheckParameter4, NULL);
227 }
228
229 /*
230 * @implemented
231 */
232 VOID STDCALL
233 KeBugCheck(ULONG BugCheckCode)
234 /*
235 * FUNCTION: Brings the system down in a controlled manner when an
236 * inconsistency that might otherwise cause corruption has been detected
237 * ARGUMENTS:
238 * BugCheckCode = Specifies the reason for the bug check
239 * RETURNS: Doesn't
240 */
241 {
242 KeBugCheckEx(BugCheckCode, 0, 0, 0, 0);
243 }
244
245 /* EOF */