test: debug.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# debug.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1989-1993  Microsoft Corporation
    00004
    00005 Module Name:
    00006
    00007     stubs.c
    00008
    00009 Abstract:
    00010
    00011     This module implements kernel debugger synchronization routines.
    00012
    00013 Author:
    00014
    00015     Ken Reneris (kenr) 30-Aug-1990
    00016
    00017 Environment:
    00018
    00019     Kernel mode only.
    00020
    00021 Revision History:
    00022
    00023 --*/
    00024
    00025 #include "ki.h"
    00026
    00027 #define IDBG    1
    00028
    00029
    00030 #define FrozenState(a)  (a & 0xF)
    00031
    00032 // state
    00033 #define RUNNING                 0x00
    00034 #define TARGET_FROZEN           0x02
    00035 #define TARGET_THAW             0x03
    00036 #define FREEZE_OWNER            0x04
    00037
    00038 // flags (bits)
    00039 #define FREEZE_ACTIVE           0x20
    00040
    00041
    00042 //
    00043 // Define local storage to save the old IRQL.
    00044 //
    00045
    00046 KIRQL KiOldIrql;
    00047
    00048 #ifndef NT_UP
    00049 PKPRCB KiFreezeOwner;
    00050 #endif
    00051
    00052
    00053
    00054 BOOLEAN
    00055 KeFreezeExecution (
    00056     IN PKTRAP_FRAME TrapFrame,
    00057     IN PKEXCEPTION_FRAME ExceptionFrame
    00058     )
    00059
    00060 /*++
    00061
    00062 Routine Description:
    00063
    00064     This function freezes the execution of all other processors in the host
    00065     configuration and then returns to the caller.
    00066
    00067 Arguments:
    00068
    00069     TrapFrame - Supplies a pointer to a trap frame that describes the
    00070         trap.
    00071
    00072     ExceptionFrame - Supplies a pointer to an exception frame that
    00073         describes the trap.
    00074
    00075 Return Value:
    00076
    00077     Previous interrupt enable.
    00078
    00079 --*/
    00080
    00081 {
    00082
    00083     BOOLEAN Enable;
    00084
    00085 #if !defined(NT_UP)
    00086
    00087     BOOLEAN Flag;
    00088     PKPRCB Prcb;
    00089     ULONG TargetSet;
    00090     ULONG BitNumber;
    00091     KIRQL OldIrql;
    00092
    00093 #if IDBG
    00094
    00095     ULONG Count = 30000;
    00096
    00097 #endif
    00098 #endif
    00099
    00100     //
    00101     // Disable interrupts.
    00102     //
    00103
    00104     Enable = KiDisableInterrupts();
    00105     KiFreezeFlag = FREEZE_FROZEN;
    00106
    00107 #if !defined(NT_UP)
    00108     //
    00109     // Raise IRQL to HIGH_LEVEL.
    00110     //
    00111
    00112     KeRaiseIrql(HIGH_LEVEL, &OldIrql);
    00113
    00114     if (FrozenState(KeGetCurrentPrcb()->IpiFrozen) == FREEZE_OWNER) {
    00115         //
    00116         // This processor already owns the freeze lock.
    00117         // Return without trying to re-acquire lock or without
    00118         // trying to IPI the other processors again
    00119         //
    00120
    00121         return Enable;
    00122     }
    00123
    00124
    00125     //
    00126     // Try to acquire the KiFreezeExecutionLock before sending the request.
    00127     // To prevent deadlock from occurring, we need to accept and process
    00128     // incoming FreexeExecution requests while we are waiting to acquire
    00129     // the FreezeExecutionFlag.
    00130     //
    00131
    00132     while (KiTryToAcquireSpinLock (&KiFreezeExecutionLock) == FALSE) {
    00133
    00134         //
    00135         // FreezeExecutionLock is busy.  Another processor may be trying
    00136         // to IPI us - go service any IPI.
    00137         //
    00138
    00139         KiRestoreInterrupts(Enable);
    00140         Flag = KiIpiServiceRoutine((PVOID)TrapFrame, (PVOID)ExceptionFrame);
    00141         KiDisableInterrupts();
    00142
    00143 #if IDBG
    00144
    00145         if (Flag != FALSE) {
    00146             Count = 30000;
    00147             continue;
    00148         }
    00149
    00150         KeStallExecutionProcessor (100);
    00151         if (!Count--) {
    00152             Count = 30000;
    00153             if (KiTryToAcquireSpinLock (&KiFreezeLockBackup) == TRUE) {
    00154                 KiFreezeFlag |= FREEZE_BACKUP;
    00155                 break;
    00156             }
    00157         }
    00158
    00159 #endif
    00160
    00161     }
    00162
    00163     //
    00164     // After acquiring the lock flag, we send Freeze request to each processor
    00165     // in the system (other than us) and wait for it to become frozen.
    00166     //
    00167
    00168     Prcb = KeGetCurrentPrcb();  // Do this after spinlock is acquired.
    00169     TargetSet = KeActiveProcessors & ~(1 << Prcb->Number);
    00170     if (TargetSet) {
    00171
    00172 #if IDBG
    00173         Count = 400;
    00174 #endif
    00175
    00176         KiFreezeOwner = Prcb;
    00177         Prcb->IpiFrozen = FREEZE_OWNER | FREEZE_ACTIVE;
    00178         Prcb->SkipTick  = TRUE;
    00179         KiIpiSend((KAFFINITY) TargetSet, IPI_FREEZE);
    00180
    00181         while (TargetSet != 0) {
    00182             BitNumber = KeFindFirstSetRightMember(TargetSet);
    00183             ClearMember(BitNumber, TargetSet);
    00184             Prcb = KiProcessorBlock[BitNumber];
    00185
    00186 #if IDBG
    00187
    00188             while (Prcb->IpiFrozen != TARGET_FROZEN) {
    00189                 if (Count == 0) {
    00190                     KiFreezeFlag |= FREEZE_SKIPPED_PROCESSOR;
    00191                     break;
    00192                 }
    00193
    00194                 KeStallExecutionProcessor (10000);
    00195                 Count--;
    00196             }
    00197
    00198 #else
    00199
    00200             while (Prcb->IpiFrozen != TARGET_FROZEN) {
    00201                 KeYieldProcessor();
    00202             }
    00203 #endif
    00204
    00205         }
    00206     }
    00207
    00208     //
    00209     // Save the old IRQL and return whether interrupts were previous enabled.
    00210     //
    00211
    00212     KiOldIrql = OldIrql;
    00213
    00214 #endif      // !defined(NT_UP)
    00215
    00216     return Enable;
    00217 }
    00218
    00219 VOID
    00220 KiFreezeTargetExecution (
    00221     IN PKTRAP_FRAME TrapFrame,
    00222     IN PKEXCEPTION_FRAME ExceptionFrame
    00223     )
    00224
    00225 /*++
    00226
    00227 Routine Description:
    00228
    00229     This function freezes the execution of the current running processor.
    00230     If a trapframe is supplied to current state is saved into the prcb
    00231     for the debugger.
    00232
    00233 Arguments:
    00234
    00235     TrapFrame - Supplies a pointer to the trap frame that describes the
    00236         trap.
    00237
    00238     ExceptionFrame - Supplies a pointer to the exception frame that
    00239         describes the trap.
    00240
    00241 Return Value:
    00242
    00243     None.
    00244
    00245 --*/
    00246
    00247 {
    00248
    00249 #if !defined(NT_UP)
    00250
    00251     KIRQL OldIrql;
    00252     PKPRCB Prcb;
    00253     BOOLEAN Enable;
    00254     KCONTINUE_STATUS Status;
    00255     EXCEPTION_RECORD ExceptionRecord;
    00256
    00257     Enable = KiDisableInterrupts();
    00258     KeRaiseIrql(HIGH_LEVEL, &OldIrql);
    00259
    00260     Prcb = KeGetCurrentPrcb();
    00261     Prcb->IpiFrozen = TARGET_FROZEN;
    00262     Prcb->SkipTick  = TRUE;
    00263
    00264     if (TrapFrame != NULL) {
    00265         KiSaveProcessorState(TrapFrame, ExceptionFrame);
    00266     }
    00267
    00268     //
    00269     // Sweep the data cache in case this is a system crash and the bug
    00270     // check code is attempting to write a crash dump file.
    00271     //
    00272
    00273     KeSweepCurrentDcache();
    00274
    00275     //
    00276     //  Wait for person requesting us to freeze to
    00277     //  clear our frozen flag
    00278     //
    00279
    00280     while (FrozenState(Prcb->IpiFrozen) == TARGET_FROZEN) {
    00281         if (Prcb->IpiFrozen & FREEZE_ACTIVE) {
    00282
    00283             //
    00284             // This processor has been made the active processor
    00285             //
    00286             if (TrapFrame) {
    00287                 RtlZeroMemory (&ExceptionRecord, sizeof ExceptionRecord);
    00288                 ExceptionRecord.ExceptionCode = STATUS_WAKE_SYSTEM_DEBUGGER;
    00289                 ExceptionRecord.ExceptionRecord  = &ExceptionRecord;
    00290                 ExceptionRecord.ExceptionAddress =
    00291                     (PVOID)CONTEXT_TO_PROGRAM_COUNTER (&Prcb->ProcessorState.ContextFrame);
    00292
    00293                 Status = (KiDebugSwitchRoutine) (
    00294                             &ExceptionRecord,
    00295                             &Prcb->ProcessorState.ContextFrame,
    00296                             FALSE
    00297                             );
    00298
    00299             } else {
    00300                 Status = ContinueError;
    00301             }
    00302
    00303             //
    00304             // If status is anything other then, continue with next
    00305             // processor then reselect master
    00306             //
    00307
    00308             if (Status != ContinueNextProcessor) {
    00309                 Prcb->IpiFrozen &= ~FREEZE_ACTIVE;
    00310                 KiFreezeOwner->IpiFrozen |= FREEZE_ACTIVE;
    00311             }
    00312         }
    00313         KeYieldProcessor();
    00314     }
    00315
    00316     if (TrapFrame != NULL) {
    00317         KiRestoreProcessorState(TrapFrame, ExceptionFrame);
    00318     }
    00319
    00320     Prcb->IpiFrozen = RUNNING;
    00321
    00322     KeFlushCurrentTb();
    00323     KeSweepCurrentIcache();
    00324
    00325     KeLowerIrql(OldIrql);
    00326     KiRestoreInterrupts(Enable);
    00327 #endif      // !define(NT_UP)
    00328
    00329     return;
    00330 }
    00331
    00332
    00333 KCONTINUE_STATUS
    00334 KeSwitchFrozenProcessor (
    00335     IN ULONG ProcessorNumber
    00336     )
    00337 {
    00338 #if !defined(NT_UP)
    00339     PKPRCB TargetPrcb, CurrentPrcb;
    00340
    00341     //
    00342     // If Processor number is out of range, reselect current processor
    00343     //
    00344
    00345     if (ProcessorNumber >= (ULONG) KeNumberProcessors) {
    00346         return ContinueProcessorReselected;
    00347     }
    00348
    00349     TargetPrcb = KiProcessorBlock[ProcessorNumber];
    00350     CurrentPrcb = KeGetCurrentPrcb();
    00351
    00352     //
    00353     // Move active flag to correct processor.
    00354     //
    00355
    00356     CurrentPrcb->IpiFrozen &= ~FREEZE_ACTIVE;
    00357     TargetPrcb->IpiFrozen  |= FREEZE_ACTIVE;
    00358
    00359     //
    00360     // If this processor is frozen in KiFreezeTargetExecution, return to it
    00361     //
    00362
    00363     if (FrozenState(CurrentPrcb->IpiFrozen) == TARGET_FROZEN) {
    00364         return ContinueNextProcessor;
    00365     }
    00366
    00367     //
    00368     // This processor must be FREEZE_OWNER, wait to be reselected as the
    00369     // active processor
    00370     //
    00371
    00372     if (FrozenState(CurrentPrcb->IpiFrozen) != FREEZE_OWNER) {
    00373         return ContinueError;
    00374     }
    00375
    00376     while (!(CurrentPrcb->IpiFrozen & FREEZE_ACTIVE)) {
    00377         KeYieldProcessor();
    00378     }
    00379
    00380 #endif  // !defined(NT_UP)
    00381
    00382     //
    00383     // Reselect this processor
    00384     //
    00385
    00386     return ContinueProcessorReselected;
    00387 }
    00388
    00389
    00390 VOID
    00391 KeThawExecution (
    00392     IN BOOLEAN Enable
    00393     )
    00394
    00395 /*++
    00396
    00397 Routine Description:
    00398
    00399     This function thaws the execution of all other processors in the host
    00400     configuration and then returns to the caller. It is intended for use by
    00401     the kernel debugger.
    00402
    00403 Arguments:
    00404
    00405     Enable - Supplies the previous interrupt enable that is to be restored
    00406         after having thawed the execution of all other processors.
    00407
    00408 Return Value:
    00409
    00410     None.
    00411
    00412 --*/
    00413
    00414 {
    00415 #if !defined(NT_UP)
    00416
    00417     KIRQL OldIrql;
    00418     ULONG TargetSet;
    00419     ULONG BitNumber;
    00420     ULONG Flag;
    00421     PKPRCB Prcb;
    00422
    00423     //
    00424     // Before releasing FreezeExecutionLock clear any all targets IpiFrozen
    00425     // flag.
    00426     //
    00427
    00428     KeGetCurrentPrcb()->IpiFrozen = RUNNING;
    00429
    00430     TargetSet = KeActiveProcessors & ~(1 << KeGetCurrentPrcb()->Number);
    00431     while (TargetSet != 0) {
    00432         BitNumber = KeFindFirstSetRightMember(TargetSet);
    00433         ClearMember(BitNumber, TargetSet);
    00434         Prcb = KiProcessorBlock[BitNumber];
    00435 #if IDBG
    00436         //
    00437         // If the target processor was not forzen, then don't wait
    00438         // for target to unfreeze.
    00439         //
    00440
    00441         if (FrozenState(Prcb->IpiFrozen) != TARGET_FROZEN) {
    00442             Prcb->IpiFrozen = RUNNING;
    00443             continue;
    00444         }
    00445 #endif
    00446
    00447         Prcb->IpiFrozen = TARGET_THAW;
    00448         while (Prcb->IpiFrozen == TARGET_THAW) {
    00449             KeYieldProcessor();
    00450         }
    00451     }
    00452
    00453     //
    00454     // Capture the previous IRQL before releasing the freeze lock.
    00455     //
    00456
    00457     OldIrql = KiOldIrql;
    00458
    00459 #if IDBG
    00460
    00461     Flag = KiFreezeFlag;
    00462     KiFreezeFlag = 0;
    00463
    00464     if ((Flag & FREEZE_BACKUP) != 0) {
    00465         KiReleaseSpinLock(&KiFreezeLockBackup);
    00466     } else {
    00467         KiReleaseSpinLock(&KiFreezeExecutionLock);
    00468     }
    00469
    00470 #else
    00471
    00472     KiFreezeFlag = 0;
    00473     KiReleaseSpinLock(&KiFreezeExecutionLock);
    00474
    00475 #endif
    00476 #endif  // !defined (NT_UP)
    00477
    00478
    00479     //
    00480     // Flush the current TB, instruction cache, and data cache.
    00481     //
    00482
    00483     KeFlushCurrentTb();
    00484     KeSweepCurrentIcache();
    00485     KeSweepCurrentDcache();
    00486
    00487     //
    00488     // Lower IRQL and restore interrupt enable
    00489     //
    00490
    00491 #if !defined(NT_UP)
    00492     KeLowerIrql(OldIrql);
    00493 #endif
    00494     KiRestoreInterrupts(Enable);
    00495     return;
    00496 }
    00497
    00498 VOID
    00499 KeReturnToFirmware (
    00500     IN FIRMWARE_REENTRY Routine
    00501     )
    00502
    00503 /*++
    00504
    00505 Routine Description:
    00506
    00507     This routine will thaw all other processors in an MP environment to cause
    00508     them to return to do a return to firmware with the supplied parameter.
    00509
    00510     It will then call HalReturnToFirmware itself.
    00511
    00512     N.B. It is assumed that we are in the environment of the kernel debugger
    00513     or a crash dump.
    00514
    00515
    00516 Arguments:
    00517
    00518     Routine - What to invoke on return to firmware.
    00519
    00520 Return Value:
    00521
    00522     None.
    00523
    00524 --*/
    00525
    00526 {
    00527
    00528     //
    00529     // Just get the interface in now.  When intel and kenr come up with the
    00530     // right stuff we can fill this in.
    00531     //
    00532
    00533     HalReturnToFirmware(Routine);
    00534
    00535 }
    00536
    00537 VOID
    00538 KiPollFreezeExecution(
    00539     VOID
    00540     )
    00541
    00542 /*++
    00543
    00544 Routine Description:
    00545
    00546     This routine is called from code that is spinning with interrupts
    00547     disabled, waiting for something to happen, when there is some
    00548     (possibly extremely small) chance that that thing will not happen
    00549     because a system freeze has been initiated.
    00550
    00551     N.B. Interrupts are disabled.
    00552
    00553 Arguments:
    00554
    00555     None.
    00556
    00557 Return Value:
    00558
    00559     None.
    00560
    00561 --*/
    00562
    00563 {
    00564     //
    00565     // Check to see if a freeze is pending for this processor.
    00566     //
    00567
    00568     PKPRCB Prcb = KeGetCurrentPrcb();
    00569
    00570     if ((Prcb->RequestSummary & IPI_FREEZE) != 0) {
    00571
    00572         //
    00573         // Clear the freeze request and freeze this processor.
    00574         //
    00575
    00576         InterlockedExchangeAdd((PLONG)&Prcb->RequestSummary, -(IPI_FREEZE));
    00577         KiFreezeTargetExecution(NULL, NULL);
    00578
    00579     } else {
    00580
    00581         //
    00582         // No freeze pending, assume this processor is spinning.
    00583         //
    00584
    00585         KeYieldProcessor();
    00586     }
    00587 }