mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 17:05:46 +00:00
Alex Ionescu <ionucu@videotron.ca>
Various bugcheck code improvements: - Fix bugcheck code and make debugging easier for unhandled exceptions/spinlocks. - Fix a race condition with TAB+B, - Fix irql to be high_level. - Fix calling unsafe function by caching bugcode data. - Fix support for smp by using IPI. - Fix not-breakpointing when no debugger is there. - Implement KeBugCheck callbacks with reason. - Fix callbacks not being called. - Fix proper breakpoint during bugcheck. Filip Navara <xnavara@volny.cz> - Move the bugcheck initialization code into Ke (was in Ex on Alex's branch). svn path=/trunk/; revision=13969
This commit is contained in:
parent
5307ffb9c6
commit
f954a88f34
7 changed files with 414 additions and 191 deletions
|
@ -38,11 +38,11 @@
|
|||
/* Assert only on "checked" version */
|
||||
#ifndef NASSERT
|
||||
#ifdef CONFIG_SMP
|
||||
#define assert(x) if (!(x)) {DbgPrint("Assertion "#x" failed at %s:%d for CPU%d\n", __FILE__,__LINE__, KeGetCurrentKPCR()->ProcessorNumber), KeBugCheck(0); }
|
||||
#define ASSERT(x) if (!(x)) {DbgPrint("Assertion "#x" failed at %s:%d for CPU%d\n", __FILE__,__LINE__, KeGetCurrentKPCR()->ProcessorNumber), KeBugCheck(0); }
|
||||
#define assert(x) if (!(x)) {DbgPrint("Assertion "#x" failed at %s:%d for CPU%d\n", __FILE__,__LINE__, KeGetCurrentKPCR()->ProcessorNumber), DbgBreakPoint(); }
|
||||
#define ASSERT(x) if (!(x)) {DbgPrint("Assertion "#x" failed at %s:%d for CPU%d\n", __FILE__,__LINE__, KeGetCurrentKPCR()->ProcessorNumber), DbgBreakPoint(); }
|
||||
#else
|
||||
#define assert(x) if (!(x)) {DbgPrint("Assertion "#x" failed at %s:%d\n", __FILE__,__LINE__); KeBugCheck(0); }
|
||||
#define ASSERT(x) if (!(x)) {DbgPrint("Assertion "#x" failed at %s:%d\n", __FILE__,__LINE__); KeBugCheck(0); }
|
||||
#define assert(x) if (!(x)) {DbgPrint("Assertion "#x" failed at %s:%d\n", __FILE__,__LINE__); DbgBreakPoint(); }
|
||||
#define ASSERT(x) if (!(x)) {DbgPrint("Assertion "#x" failed at %s:%d\n", __FILE__,__LINE__); DbgBreakPoint(); }
|
||||
#endif
|
||||
|
||||
#define assertmsg(_c_, _m_) \
|
||||
|
|
|
@ -196,7 +196,7 @@ VOID KeInitDpc(struct _KPCR* Pcr);
|
|||
VOID KeInitDispatcher(VOID);
|
||||
VOID KeInitializeDispatcher(VOID);
|
||||
VOID KiInitializeSystemClock(VOID);
|
||||
VOID KeInitializeBugCheck(VOID);
|
||||
VOID KiInitializeBugCheck(VOID);
|
||||
VOID Phase1Initialization(PVOID Context);
|
||||
|
||||
VOID KeInit1(PCHAR CommandLine, PULONG LastKernelAddress);
|
||||
|
|
|
@ -1,200 +1,445 @@
|
|||
/* $Id$
|
||||
*
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/ke/bug.c
|
||||
* PURPOSE: Graceful system shutdown if a bug is detected
|
||||
*
|
||||
* PROGRAMMERS: David Welch (welch@cwcom.net)
|
||||
* PROGRAMMERS: Alex Ionescu - Rewrote Bugcheck Routines and implemented Reason Callbacks.
|
||||
* David Welch (welch@cwcom.net)
|
||||
* Phillip Susi
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <ntoskrnl.h>
|
||||
#include <ntos/bootvid.h>
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
#include "../../hal/halx86/include/hal.h"
|
||||
|
||||
/* GLOBALS ******************************************************************/
|
||||
|
||||
static LIST_ENTRY BugcheckCallbackListHead = {NULL,NULL};
|
||||
static LIST_ENTRY BugcheckReasonCallbackListHead = {NULL,NULL};
|
||||
static ULONG InBugCheck;
|
||||
static PRTL_MESSAGE_RESOURCE_DATA KiBugCodeMessages;
|
||||
static ULONG KeBugCheckCount = 1;
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
VOID INIT_FUNCTION
|
||||
KeInitializeBugCheck(VOID)
|
||||
VOID
|
||||
INIT_FUNCTION
|
||||
KiInitializeBugCheck(VOID)
|
||||
{
|
||||
InitializeListHead(&BugcheckCallbackListHead);
|
||||
InBugCheck = 0;
|
||||
PRTL_MESSAGE_RESOURCE_DATA BugCheckData;
|
||||
LDR_RESOURCE_INFO ResourceInfo;
|
||||
PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Initialize Callbadk Listhead and State */
|
||||
InitializeListHead(&BugcheckCallbackListHead);
|
||||
InitializeListHead(&BugcheckReasonCallbackListHead);
|
||||
InBugCheck = 0;
|
||||
|
||||
/* Cache the Bugcheck Message Strings. Prepare the Lookup Data */
|
||||
ResourceInfo.Type = 11;
|
||||
ResourceInfo.Name = 1;
|
||||
ResourceInfo.Language = 9;
|
||||
|
||||
/* Do the lookup. */
|
||||
Status = LdrFindResource_U((PVOID)KERNEL_BASE,
|
||||
&ResourceInfo,
|
||||
RESOURCE_DATA_LEVEL,
|
||||
&ResourceDataEntry);
|
||||
|
||||
/* Make sure it worked */
|
||||
if (NT_SUCCESS(Status)) {
|
||||
|
||||
DPRINT1("Found Bugcheck Resource Data!\n");
|
||||
|
||||
/* Now actually get a pointer to it */
|
||||
Status = LdrAccessResource((PVOID)KERNEL_BASE,
|
||||
ResourceDataEntry,
|
||||
(PVOID*)&BugCheckData,
|
||||
NULL);
|
||||
|
||||
/* Make sure it worked */
|
||||
if (NT_SUCCESS(Status)) {
|
||||
|
||||
DPRINT1("Got Pointer to Bugcheck Resource Data!\n");
|
||||
KiBugCodeMessages = BugCheckData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOLEAN STDCALL
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
KeDeregisterBugCheckCallback(PKBUGCHECK_CALLBACK_RECORD CallbackRecord)
|
||||
{
|
||||
/* Check the Current State */
|
||||
if (CallbackRecord->State == BufferInserted) {
|
||||
CallbackRecord->State = BufferEmpty;
|
||||
RemoveEntryList(&CallbackRecord->Entry);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* The callback wasn't registered */
|
||||
return FALSE;
|
||||
KIRQL OldIrql;
|
||||
BOOLEAN Status = FALSE;
|
||||
|
||||
/* Raise IRQL to High */
|
||||
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||||
|
||||
/* Check the Current State */
|
||||
if (CallbackRecord->State == BufferInserted) {
|
||||
|
||||
/* Reset state and remove from list */
|
||||
CallbackRecord->State = BufferEmpty;
|
||||
RemoveEntryList(&CallbackRecord->Entry);
|
||||
|
||||
Status = TRUE;
|
||||
}
|
||||
|
||||
/* Lower IRQL and return */
|
||||
KeLowerIrql(OldIrql);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOLEAN STDCALL
|
||||
KeRegisterBugCheckCallback(PKBUGCHECK_CALLBACK_RECORD CallbackRecord,
|
||||
PKBUGCHECK_CALLBACK_ROUTINE CallbackRoutine,
|
||||
PVOID Buffer,
|
||||
ULONG Length,
|
||||
PUCHAR Component)
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
KeDeregisterBugCheckReasonCallback(IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
BOOLEAN Status = FALSE;
|
||||
|
||||
/* Raise IRQL to High */
|
||||
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||||
|
||||
/* Check the Current State */
|
||||
if (CallbackRecord->State == BufferInserted) {
|
||||
|
||||
/* Check the Current State first so we don't double-register */
|
||||
if (CallbackRecord->State == BufferEmpty) {
|
||||
CallbackRecord->Length = Length;
|
||||
CallbackRecord->Buffer = Buffer;
|
||||
CallbackRecord->Component = Component;
|
||||
CallbackRecord->CallbackRoutine = CallbackRoutine;
|
||||
CallbackRecord->State = BufferInserted;
|
||||
InsertTailList(&BugcheckCallbackListHead, &CallbackRecord->Entry);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* The Callback was already registered */
|
||||
return(FALSE);
|
||||
/* Reset state and remove from list */
|
||||
CallbackRecord->State = BufferEmpty;
|
||||
RemoveEntryList(&CallbackRecord->Entry);
|
||||
|
||||
Status = TRUE;
|
||||
}
|
||||
|
||||
/* Lower IRQL and return */
|
||||
KeLowerIrql(OldIrql);
|
||||
return Status;
|
||||
}
|
||||
|
||||
VOID STDCALL
|
||||
KeBugCheckWithTf(ULONG BugCheckCode,
|
||||
ULONG BugCheckParameter1,
|
||||
ULONG BugCheckParameter2,
|
||||
ULONG BugCheckParameter3,
|
||||
ULONG BugCheckParameter4,
|
||||
PKTRAP_FRAME Tf)
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
KeRegisterBugCheckCallback(PKBUGCHECK_CALLBACK_RECORD CallbackRecord,
|
||||
PKBUGCHECK_CALLBACK_ROUTINE CallbackRoutine,
|
||||
PVOID Buffer,
|
||||
ULONG Length,
|
||||
PUCHAR Component)
|
||||
{
|
||||
PRTL_MESSAGE_RESOURCE_ENTRY Message;
|
||||
NTSTATUS Status;
|
||||
ULONG Mask;
|
||||
KIRQL OldIrql;
|
||||
|
||||
/* Make sure we're switching back to the blue screen and print messages on it */
|
||||
HalReleaseDisplayOwnership();
|
||||
if (0 == (KdDebugState & KD_DEBUG_GDB))
|
||||
{
|
||||
KdDebugState |= KD_DEBUG_SCREEN;
|
||||
KIRQL OldIrql;
|
||||
BOOLEAN Status = FALSE;
|
||||
|
||||
/* Raise IRQL to High */
|
||||
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||||
|
||||
/* Check the Current State first so we don't double-register */
|
||||
if (CallbackRecord->State == BufferEmpty) {
|
||||
|
||||
/* Set the Callback Settings and insert into the list */
|
||||
CallbackRecord->Length = Length;
|
||||
CallbackRecord->Buffer = Buffer;
|
||||
CallbackRecord->Component = Component;
|
||||
CallbackRecord->CallbackRoutine = CallbackRoutine;
|
||||
CallbackRecord->State = BufferInserted;
|
||||
InsertTailList(&BugcheckCallbackListHead, &CallbackRecord->Entry);
|
||||
|
||||
Status = TRUE;
|
||||
}
|
||||
|
||||
Ke386DisableInterrupts();
|
||||
DebugLogDumpMessages();
|
||||
/* Lower IRQL and return */
|
||||
KeLowerIrql(OldIrql);
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (MmGetKernelAddressSpace()->Lock.Owner == KeGetCurrentThread())
|
||||
{
|
||||
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
KeRegisterBugCheckReasonCallback(IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord,
|
||||
IN PKBUGCHECK_REASON_CALLBACK_ROUTINE CallbackRoutine,
|
||||
IN KBUGCHECK_CALLBACK_REASON Reason,
|
||||
IN PUCHAR Component)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
BOOLEAN Status = FALSE;
|
||||
|
||||
/* Raise IRQL to High */
|
||||
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||||
|
||||
/* Check the Current State first so we don't double-register */
|
||||
if (CallbackRecord->State == BufferEmpty) {
|
||||
|
||||
/* Set the Callback Settings and insert into the list */
|
||||
CallbackRecord->Component = Component;
|
||||
CallbackRecord->CallbackRoutine = CallbackRoutine;
|
||||
CallbackRecord->State = BufferInserted;
|
||||
CallbackRecord->Reason = Reason;
|
||||
InsertTailList(&BugcheckReasonCallbackListHead, &CallbackRecord->Entry);
|
||||
|
||||
Status = TRUE;
|
||||
}
|
||||
|
||||
if (KeGetCurrentIrql() < DISPATCH_LEVEL)
|
||||
{
|
||||
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
|
||||
}
|
||||
DbgPrint("Bug detected (code %x param %x %x %x %x)\n",
|
||||
BugCheckCode,
|
||||
BugCheckParameter1,
|
||||
BugCheckParameter2,
|
||||
BugCheckParameter3,
|
||||
BugCheckParameter4);
|
||||
/* Lower IRQL and return */
|
||||
KeLowerIrql(OldIrql);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = RtlFindMessage((PVOID)KERNEL_BASE, //0xC0000000,
|
||||
11, //RT_MESSAGETABLE,
|
||||
0x09, //0x409,
|
||||
BugCheckCode,
|
||||
&Message);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
if (Message->Flags == 0)
|
||||
DbgPrint(" %s\n", Message->Text);
|
||||
else
|
||||
DbgPrint(" %S\n", (PWSTR)Message->Text);
|
||||
VOID
|
||||
STDCALL
|
||||
KeGetBugMessageText(ULONG BugCheckCode, PANSI_STRING OutputString)
|
||||
{
|
||||
ULONG i;
|
||||
ULONG IdOffset;
|
||||
ULONG_PTR MessageEntry;
|
||||
PCHAR BugCode;
|
||||
|
||||
/* Find the message. This code is based on RtlFindMesssage -- Alex */
|
||||
for (i = 0; i < KiBugCodeMessages->NumberOfBlocks; i++) {
|
||||
|
||||
/* Check if the ID Matches */
|
||||
if ((BugCheckCode >= KiBugCodeMessages->Blocks[i].LowId) &&
|
||||
(BugCheckCode <= KiBugCodeMessages->Blocks[i].HighId)) {
|
||||
|
||||
/* Get Offset to Entry */
|
||||
MessageEntry = (ULONG_PTR)KiBugCodeMessages + KiBugCodeMessages->Blocks[i].OffsetToEntries;
|
||||
IdOffset = BugCheckCode - KiBugCodeMessages->Blocks[i].LowId;
|
||||
|
||||
/* Get offset to ID */
|
||||
for (i = 0; i < IdOffset; i++) {
|
||||
|
||||
/* Advance in the Entries */
|
||||
MessageEntry += ((PRTL_MESSAGE_RESOURCE_ENTRY)MessageEntry)->Length;
|
||||
}
|
||||
|
||||
/* Get the final Code */
|
||||
BugCode = ((PRTL_MESSAGE_RESOURCE_ENTRY)MessageEntry)->Text;
|
||||
|
||||
/* Return it in the OutputString */
|
||||
if (OutputString) {
|
||||
|
||||
OutputString->Buffer = BugCode;
|
||||
OutputString->Length = strlen(BugCode) + 1;
|
||||
OutputString->MaximumLength = strlen(BugCode) + 1;
|
||||
|
||||
} else {
|
||||
|
||||
/* Direct Output to Screen */
|
||||
DbgPrint("%s\n", BugCode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgPrint(" No message text found!\n\n");
|
||||
}
|
||||
|
||||
VOID
|
||||
STDCALL
|
||||
KiDoBugCheckCallbacks(VOID)
|
||||
{
|
||||
PKBUGCHECK_CALLBACK_RECORD CurrentRecord;
|
||||
PLIST_ENTRY ListHead;
|
||||
PLIST_ENTRY NextEntry;
|
||||
|
||||
/* FIXME: Check Checksum and add support for WithReason Callbacks */
|
||||
|
||||
/* First make sure that the list is Initialized... it might not be */
|
||||
ListHead = &BugcheckCallbackListHead;
|
||||
if (ListHead->Flink && ListHead->Blink) {
|
||||
|
||||
/* Loop the list */
|
||||
NextEntry = ListHead->Flink;
|
||||
while (NextEntry != ListHead) {
|
||||
|
||||
/* Get the Callback Record */
|
||||
CurrentRecord = CONTAINING_RECORD(NextEntry,
|
||||
KBUGCHECK_CALLBACK_RECORD,
|
||||
Entry);
|
||||
|
||||
/* Make sure it's inserted */
|
||||
if (CurrentRecord->State == BufferInserted) {
|
||||
|
||||
/* Call the routine */
|
||||
CurrentRecord->State = BufferStarted;
|
||||
(CurrentRecord->CallbackRoutine)(CurrentRecord->Buffer,
|
||||
CurrentRecord->Length);
|
||||
CurrentRecord->State = BufferFinished;
|
||||
}
|
||||
|
||||
/* Move to next Entry */
|
||||
NextEntry = NextEntry->Flink;
|
||||
}
|
||||
}
|
||||
Mask = 1 << KeGetCurrentProcessorNumber();
|
||||
if (InBugCheck & Mask)
|
||||
{
|
||||
#ifdef MP
|
||||
DbgPrint("Recursive bug check on CPU%d, halting now\n", KeGetCurrentProcessorNumber());
|
||||
/*
|
||||
* FIXME:
|
||||
* Send an ipi to all other processors which halt them too.
|
||||
*/
|
||||
#else
|
||||
DbgPrint("Recursive bug check halting now\n");
|
||||
}
|
||||
|
||||
VOID
|
||||
STDCALL
|
||||
KeBugCheckWithTf(ULONG BugCheckCode,
|
||||
ULONG BugCheckParameter1,
|
||||
ULONG BugCheckParameter2,
|
||||
ULONG BugCheckParameter3,
|
||||
ULONG BugCheckParameter4,
|
||||
PKTRAP_FRAME Tf)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
BOOLEAN GotExtendedCrashInfo = FALSE;
|
||||
PVOID Address = 0;
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
MODULE_TEXT_SECTION* CurrentSection = NULL;
|
||||
extern LIST_ENTRY ModuleTextListHead;
|
||||
|
||||
/* Make sure we're switching back to the blue screen and print messages on it */
|
||||
HalReleaseDisplayOwnership();
|
||||
if (0 == (KdDebugState & KD_DEBUG_GDB)) KdDebugState |= KD_DEBUG_SCREEN;
|
||||
|
||||
/* Try to find out who did this. For this, we need a Trap Frame.
|
||||
* Note: Some special BSODs pass the Frame/EIP as a Param. MSDN has the
|
||||
* info so it eventually needs to be supported.
|
||||
*/
|
||||
if (Tf) {
|
||||
|
||||
/* For now, get Address from EIP */
|
||||
Address = (PVOID)Tf->Eip;
|
||||
|
||||
/* Try to get information on the module */
|
||||
CurrentEntry = ModuleTextListHead.Flink;
|
||||
while (CurrentEntry != &ModuleTextListHead && CurrentEntry != NULL) {
|
||||
|
||||
/* Get the current Section */
|
||||
CurrentSection = CONTAINING_RECORD(CurrentEntry,
|
||||
MODULE_TEXT_SECTION,
|
||||
ListEntry);
|
||||
|
||||
/* Check if this is the right one */
|
||||
if ((Address != NULL && (Address >= (PVOID)CurrentSection->Base &&
|
||||
Address < (PVOID)(CurrentSection->Base + CurrentSection->Length)))) {
|
||||
|
||||
/* We got it */
|
||||
GotExtendedCrashInfo = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Loop again */
|
||||
CurrentEntry = CurrentEntry->Flink;
|
||||
}
|
||||
}
|
||||
|
||||
/* Raise IRQL to HIGH_LEVEL */
|
||||
Ke386DisableInterrupts();
|
||||
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||||
|
||||
/* Disable Interrupts, Dump Debug Messages */
|
||||
DebugLogDumpMessages();
|
||||
|
||||
/* Unload the Kernel Adress Space if we own it */
|
||||
if (MmGetKernelAddressSpace()->Lock.Owner == KeGetCurrentThread())
|
||||
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||||
|
||||
/* FIXMEs: Use inbv to clear, fill and write to screen. */
|
||||
|
||||
/* Show the STOP Message */
|
||||
DbgPrint("A problem has been detected and ReactOS has been shut down to prevent "
|
||||
"damage to your computer.\n\n");
|
||||
|
||||
/* Show the module name of who caused this */
|
||||
if (GotExtendedCrashInfo) {
|
||||
|
||||
DbgPrint("The problem seems to be caused by the following file: %S\n\n", CurrentSection->Name);
|
||||
}
|
||||
|
||||
/* Find the Bug Code String */
|
||||
KeGetBugMessageText(BugCheckCode, NULL);
|
||||
|
||||
/* Show the techincal Data */
|
||||
DbgPrint("Technical information:\n\n*** STOP: 0x%08lX (0x%p,0x%p,0x%p,0x%p)\n\n",
|
||||
BugCheckCode,
|
||||
BugCheckParameter1,
|
||||
BugCheckParameter2,
|
||||
BugCheckParameter3,
|
||||
BugCheckParameter4);
|
||||
|
||||
/* Show the module name and more data of who caused this */
|
||||
if (GotExtendedCrashInfo) {
|
||||
|
||||
DbgPrint("*** %S - Address 0x%p base at 0x%p, DateStamp 0x%x\n\n",
|
||||
CurrentSection->Name,
|
||||
Address,
|
||||
CurrentSection->Base,
|
||||
0);
|
||||
}
|
||||
|
||||
/* There can only be one Bugcheck per Bootup */
|
||||
if (!InterlockedDecrement(&KeBugCheckCount)) {
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
ULONG i;
|
||||
/* Freeze the other CPUs */
|
||||
for (i = 0; i < KeNumberProcessors; i++) {
|
||||
if (i != KeGetCurrentProcessorNumber()) {
|
||||
|
||||
/* Send the IPI and give them one second to catch up */
|
||||
KiIpiSendRequest(1 << i, IPI_REQUEST_FREEZE);
|
||||
KeStallExecutionProcessor(1000000);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Ke386HaltProcessor();
|
||||
}
|
||||
/*
|
||||
* FIXME:
|
||||
* Use InterlockedOr or InterlockedBitSet.
|
||||
*/
|
||||
InBugCheck |= Mask;
|
||||
if (Tf != NULL)
|
||||
{
|
||||
KiDumpTrapFrame(Tf, BugCheckParameter1, BugCheckParameter2);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Check if we got a Trap Frame */
|
||||
if (Tf) {
|
||||
|
||||
/* Dump it */
|
||||
KiDumpTrapFrame(Tf, BugCheckParameter1, BugCheckParameter2);
|
||||
|
||||
} else {
|
||||
|
||||
/* We can only dump the frames */
|
||||
#if defined(__GNUC__)
|
||||
KeDumpStackFrames((PULONG)__builtin_frame_address(0));
|
||||
KeDumpStackFrames((PULONG)__builtin_frame_address(0));
|
||||
#elif defined(_MSC_VER)
|
||||
__asm push ebp
|
||||
__asm call KeDumpStackFrames
|
||||
__asm add esp, 4
|
||||
__asm push ebp
|
||||
__asm call KeDumpStackFrames
|
||||
__asm add esp, 4
|
||||
#else
|
||||
#error Unknown compiler for inline assembler
|
||||
#endif
|
||||
}
|
||||
MmDumpToPagingFile(BugCheckCode, BugCheckParameter1,
|
||||
BugCheckParameter2, BugCheckParameter3,
|
||||
BugCheckParameter4, Tf);
|
||||
}
|
||||
|
||||
/* Call the Callbacks */;
|
||||
KiDoBugCheckCallbacks();
|
||||
|
||||
if (KdDebuggerEnabled)
|
||||
{
|
||||
Ke386EnableInterrupts();
|
||||
DbgBreakPointNoBugCheck();
|
||||
Ke386DisableInterrupts();
|
||||
/* Dump the BSOD to the Paging File */
|
||||
MmDumpToPagingFile(BugCheckCode,
|
||||
BugCheckParameter1,
|
||||
BugCheckParameter2,
|
||||
BugCheckParameter3,
|
||||
BugCheckParameter4,
|
||||
Tf);
|
||||
|
||||
/* Wake up the Debugger */
|
||||
if (KdDebuggerEnabled) {
|
||||
Ke386EnableInterrupts();
|
||||
DbgBreakPointWithStatus(DBG_STATUS_BUGCHECK_SECOND);
|
||||
Ke386DisableInterrupts();
|
||||
}
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/*
|
||||
* FIXME:
|
||||
* Send an ipi to all other processors which halt them too.
|
||||
*/
|
||||
Ke386HaltProcessor();
|
||||
}
|
||||
/* Halt this CPU now */
|
||||
for (;;) Ke386HaltProcessor();
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID STDCALL
|
||||
KeBugCheckEx(ULONG BugCheckCode,
|
||||
ULONG BugCheckParameter1,
|
||||
ULONG BugCheckParameter2,
|
||||
ULONG BugCheckParameter3,
|
||||
ULONG BugCheckParameter4)
|
||||
/*
|
||||
*
|
||||
* FUNCTION: Brings the system down in a controlled manner when an
|
||||
* inconsistency that might otherwise cause corruption has been detected
|
||||
* ARGUMENTS:
|
||||
|
@ -202,23 +447,34 @@ KeBugCheckEx(ULONG BugCheckCode,
|
|||
* BugCheckParameter[1-4] = Additional information about bug
|
||||
* RETURNS: Doesn't
|
||||
*/
|
||||
VOID
|
||||
STDCALL
|
||||
KeBugCheckEx(ULONG BugCheckCode,
|
||||
ULONG BugCheckParameter1,
|
||||
ULONG BugCheckParameter2,
|
||||
ULONG BugCheckParameter3,
|
||||
ULONG BugCheckParameter4)
|
||||
{
|
||||
KeBugCheckWithTf(BugCheckCode, BugCheckParameter1, BugCheckParameter2,
|
||||
BugCheckParameter3, BugCheckParameter4, NULL);
|
||||
/* Call the Trap Frame version without a Trap Frame */
|
||||
KeBugCheckWithTf(BugCheckCode,
|
||||
BugCheckParameter1,
|
||||
BugCheckParameter2,
|
||||
BugCheckParameter3,
|
||||
BugCheckParameter4,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID STDCALL
|
||||
KeBugCheck(ULONG BugCheckCode)
|
||||
/*
|
||||
*
|
||||
* FUNCTION: Brings the system down in a controlled manner when an
|
||||
* inconsistency that might otherwise cause corruption has been detected
|
||||
* ARGUMENTS:
|
||||
* BugCheckCode = Specifies the reason for the bug check
|
||||
* RETURNS: Doesn't
|
||||
*/
|
||||
VOID STDCALL
|
||||
KeBugCheck(ULONG BugCheckCode)
|
||||
{
|
||||
KeBugCheckEx(BugCheckCode, 0, 0, 0, 0);
|
||||
}
|
||||
|
|
|
@ -257,19 +257,6 @@ ExRaiseHardError (
|
|||
UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
KeDeregisterBugCheckReasonCallback(
|
||||
IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord
|
||||
)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
|
@ -283,20 +270,4 @@ KeGetRecommendedSharedDataAlignment(
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
KeRegisterBugCheckReasonCallback(
|
||||
IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord,
|
||||
IN PKBUGCHECK_REASON_CALLBACK_ROUTINE CallbackRoutine,
|
||||
IN KBUGCHECK_CALLBACK_REASON Reason,
|
||||
IN PUCHAR Component
|
||||
)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id:$
|
||||
/* $Id$
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -34,10 +34,10 @@ DbgBreakPoint(VOID)
|
|||
* @implemented
|
||||
*/
|
||||
#if defined(__GNUC__)
|
||||
__asm__(".globl _DbgBreakPointNoBugCheck@0\n\t"
|
||||
"_DbgBreakPointNoBugCheck@0:\n\t"
|
||||
"int $3\n\t"
|
||||
"ret\n\t");
|
||||
__asm__(".globl _DbgBreakPointNoBugCheck@0\n\t"
|
||||
"_DbgBreakPointNoBugCheck@0:\n\t"
|
||||
"int $3\n\t"
|
||||
"ret\n\t");
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
|
@ -355,7 +355,7 @@ KeInit2(VOID)
|
|||
{
|
||||
PKPCR Pcr = KeGetCurrentKPCR();
|
||||
|
||||
KeInitializeBugCheck();
|
||||
KiInitializeBugCheck();
|
||||
KeInitializeDispatcher();
|
||||
KiInitializeSystemClock();
|
||||
|
||||
|
|
|
@ -178,11 +178,7 @@ KiAcquireSpinLock(PKSPIN_LOCK SpinLock)
|
|||
* FIXME: This depends on gcc assembling this test to a single load from
|
||||
* the spinlock's value.
|
||||
*/
|
||||
if (*SpinLock >= 2)
|
||||
{
|
||||
DbgPrint("Lock %x has bad value %x\n", SpinLock, *SpinLock);
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
ASSERT(*SpinLock == 0 || 1);
|
||||
|
||||
while ((i = InterlockedExchangeUL(SpinLock, 1)) == 1)
|
||||
{
|
||||
|
@ -199,7 +195,7 @@ KiAcquireSpinLock(PKSPIN_LOCK SpinLock)
|
|||
#endif
|
||||
#else
|
||||
DbgPrint("Spinning on spinlock %x current value %x\n", SpinLock, i);
|
||||
KEBUGCHECK(0);
|
||||
KEBUGCHECKEX(SPIN_LOCK_ALREADY_OWNED, (ULONG)SpinLock, 0, 0, 0);
|
||||
#endif /* CONFIG_SMP */
|
||||
}
|
||||
}
|
||||
|
@ -227,7 +223,7 @@ KiReleaseSpinLock(PKSPIN_LOCK SpinLock)
|
|||
if (*SpinLock != 1)
|
||||
{
|
||||
DbgPrint("Releasing unacquired spinlock %x\n", SpinLock);
|
||||
KEBUGCHECK(0);
|
||||
KEBUGCHECKEX(SPIN_LOCK_NOT_OWNED, (ULONG)SpinLock, 0, 0, 0);
|
||||
}
|
||||
(void)InterlockedExchangeUL(SpinLock, 0);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue