Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

580 lines
12 KiB

  1. /*++
  2. Copyright (c) 1989-1993 Microsoft Corporation
  3. Module Name:
  4. stubs.c
  5. Abstract:
  6. This module implements kernel debugger synchronization routines.
  7. Author:
  8. Ken Reneris (kenr) 30-Aug-1990
  9. Environment:
  10. Kernel mode only.
  11. Revision History:
  12. --*/
  13. #include "ki.h"
  14. //
  15. // KiDebugRoutine - This is the address of the kernel debugger. Initially
  16. // this is filled with the address of a routine that just returns. If
  17. // the system debugger is present in the system, then it sets this
  18. // location to the address of the system debugger's routine.
  19. //
  20. PKDEBUG_ROUTINE KiDebugRoutine = &KdpStub;
  21. #define IDBG 1
  22. #define FrozenState(a) (a & 0xF)
  23. // state
  24. #define RUNNING 0x00
  25. #define TARGET_FROZEN 0x02
  26. #define TARGET_THAW 0x03
  27. #define FREEZE_OWNER 0x04
  28. //
  29. // Define flags bits.
  30. //
  31. #define FREEZE_ACTIVE 0x20
  32. //
  33. // Define local storage to save the old IRQL.
  34. //
  35. KIRQL KiOldIrql;
  36. #ifndef NT_UP
  37. PKPRCB KiFreezeOwner;
  38. #endif
  39. BOOLEAN
  40. KeFreezeExecution (
  41. IN PKTRAP_FRAME TrapFrame,
  42. IN PKEXCEPTION_FRAME ExceptionFrame
  43. )
  44. /*++
  45. Routine Description:
  46. This function freezes the execution of all other processors in the host
  47. configuration and then returns to the caller.
  48. Arguments:
  49. TrapFrame - Supplies a pointer to a trap frame that describes the
  50. trap.
  51. ExceptionFrame - Supplies a pointer to an exception frame that
  52. describes the trap.
  53. Return Value:
  54. Previous interrupt enable.
  55. --*/
  56. {
  57. BOOLEAN Enable;
  58. #if !defined(NT_UP)
  59. BOOLEAN Flag;
  60. PKPRCB Prcb;
  61. KAFFINITY TargetSet;
  62. ULONG BitNumber;
  63. KIRQL OldIrql;
  64. #if IDBG
  65. ULONG Count = 30000;
  66. #endif
  67. #else
  68. UNREFERENCED_PARAMETER(TrapFrame);
  69. UNREFERENCED_PARAMETER(ExceptionFrame);
  70. #endif
  71. //
  72. // Disable interrupts.
  73. //
  74. Enable = KeDisableInterrupts();
  75. KiFreezeFlag = FREEZE_FROZEN;
  76. //
  77. // Raise IRQL to HIGH_LEVEL.
  78. //
  79. #if !defined(NT_UP)
  80. KeRaiseIrql(HIGH_LEVEL, &OldIrql);
  81. if (FrozenState(KeGetCurrentPrcb()->IpiFrozen) == FREEZE_OWNER) {
  82. //
  83. // This processor already owns the freeze lock.
  84. // Return without trying to re-acquire lock or without
  85. // trying to IPI the other processors again
  86. //
  87. return Enable;
  88. }
  89. //
  90. // Try to acquire the KiFreezeExecutionLock before sending the request.
  91. // To prevent deadlock from occurring, we need to accept and process
  92. // incoming FreexeExecution requests while we are waiting to acquire
  93. // the FreezeExecutionFlag.
  94. //
  95. while (KeTryToAcquireSpinLockAtDpcLevel(&KiFreezeExecutionLock) == FALSE) {
  96. //
  97. // FreezeExecutionLock is busy. Another processor may be trying
  98. // to IPI us - go service any IPI.
  99. //
  100. KeEnableInterrupts(Enable);
  101. Flag = KiIpiServiceRoutine((PVOID)TrapFrame, (PVOID)ExceptionFrame);
  102. KeDisableInterrupts();
  103. #if IDBG
  104. if (Flag != FALSE) {
  105. Count = 30000;
  106. continue;
  107. }
  108. KeStallExecutionProcessor (100);
  109. if (!Count--) {
  110. Count = 30000;
  111. if (KeTryToAcquireSpinLockAtDpcLevel(&KiFreezeLockBackup) == TRUE) {
  112. KiFreezeFlag |= FREEZE_BACKUP;
  113. break;
  114. }
  115. }
  116. #endif
  117. }
  118. //
  119. // After acquiring the lock flag, we send Freeze request to each processor
  120. // in the system (other than us) and wait for it to become frozen.
  121. //
  122. Prcb = KeGetCurrentPrcb(); // Do this after spinlock is acquired.
  123. TargetSet = KeActiveProcessors & ~(AFFINITY_MASK(Prcb->Number));
  124. if (TargetSet) {
  125. #if IDBG
  126. Count = 4000;
  127. #endif
  128. KiFreezeOwner = Prcb;
  129. Prcb->IpiFrozen = FREEZE_OWNER | FREEZE_ACTIVE;
  130. Prcb->SkipTick = TRUE;
  131. KiIpiSend((KAFFINITY) TargetSet, IPI_FREEZE);
  132. while (TargetSet != 0) {
  133. KeFindFirstSetLeftAffinity(TargetSet, &BitNumber);
  134. ClearMember(BitNumber, TargetSet);
  135. Prcb = KiProcessorBlock[BitNumber];
  136. #if IDBG
  137. while (Prcb->IpiFrozen != TARGET_FROZEN) {
  138. if (Count == 0) {
  139. KiFreezeFlag |= FREEZE_SKIPPED_PROCESSOR;
  140. break;
  141. }
  142. KeStallExecutionProcessor (10000);
  143. Count--;
  144. }
  145. #else
  146. while (Prcb->IpiFrozen != TARGET_FROZEN) {
  147. KeYieldProcessor();
  148. }
  149. #endif
  150. }
  151. }
  152. //
  153. // Save the old IRQL.
  154. //
  155. KiOldIrql = OldIrql;
  156. #else
  157. //
  158. // Save the current IRQL.
  159. //
  160. KiOldIrql = KeGetCurrentIrql();
  161. #endif // !defined(NT_UP)
  162. //
  163. // Return whether interrupts were previous enabled.
  164. //
  165. return Enable;
  166. }
  167. VOID
  168. KiFreezeTargetExecution (
  169. IN PKTRAP_FRAME TrapFrame,
  170. IN PKEXCEPTION_FRAME ExceptionFrame
  171. )
  172. /*++
  173. Routine Description:
  174. This function freezes the execution of the current running processor.
  175. If a trapframe is supplied to current state is saved into the prcb
  176. for the debugger.
  177. Arguments:
  178. TrapFrame - Supplies a pointer to the trap frame that describes the
  179. trap.
  180. ExceptionFrame - Supplies a pointer to the exception frame that
  181. describes the trap.
  182. Return Value:
  183. None.
  184. --*/
  185. {
  186. #if !defined(NT_UP)
  187. KIRQL OldIrql;
  188. PKPRCB Prcb;
  189. BOOLEAN Enable;
  190. KCONTINUE_STATUS Status;
  191. EXCEPTION_RECORD ExceptionRecord;
  192. Enable = KeDisableInterrupts();
  193. KeRaiseIrql(HIGH_LEVEL, &OldIrql);
  194. Prcb = KeGetCurrentPrcb();
  195. Prcb->IpiFrozen = TARGET_FROZEN;
  196. Prcb->SkipTick = TRUE;
  197. if (TrapFrame != NULL) {
  198. KiSaveProcessorState(TrapFrame, ExceptionFrame);
  199. }
  200. //
  201. // Sweep the data cache in case this is a system crash and the bug
  202. // check code is attempting to write a crash dump file.
  203. //
  204. KeSweepCurrentDcache();
  205. //
  206. // Wait for person requesting us to freeze to
  207. // clear our frozen flag
  208. //
  209. while (FrozenState(Prcb->IpiFrozen) == TARGET_FROZEN) {
  210. if (Prcb->IpiFrozen & FREEZE_ACTIVE) {
  211. //
  212. // This processor has been made the active processor
  213. //
  214. if (TrapFrame) {
  215. RtlZeroMemory (&ExceptionRecord, sizeof ExceptionRecord);
  216. ExceptionRecord.ExceptionCode = STATUS_WAKE_SYSTEM_DEBUGGER;
  217. ExceptionRecord.ExceptionRecord = &ExceptionRecord;
  218. ExceptionRecord.ExceptionAddress =
  219. (PVOID)CONTEXT_TO_PROGRAM_COUNTER (&Prcb->ProcessorState.ContextFrame);
  220. Status = (KiDebugSwitchRoutine) (
  221. &ExceptionRecord,
  222. &Prcb->ProcessorState.ContextFrame,
  223. FALSE
  224. );
  225. } else {
  226. Status = ContinueError;
  227. }
  228. //
  229. // If status is anything other then, continue with next
  230. // processor then reselect master
  231. //
  232. if (Status != ContinueNextProcessor) {
  233. Prcb->IpiFrozen &= ~FREEZE_ACTIVE;
  234. KiFreezeOwner->IpiFrozen |= FREEZE_ACTIVE;
  235. }
  236. }
  237. KeYieldProcessor();
  238. }
  239. if (TrapFrame != NULL) {
  240. KiRestoreProcessorState(TrapFrame, ExceptionFrame);
  241. }
  242. Prcb->IpiFrozen = RUNNING;
  243. KeFlushCurrentTb();
  244. KeSweepCurrentIcache();
  245. KeLowerIrql(OldIrql);
  246. KeEnableInterrupts(Enable);
  247. #else
  248. UNREFERENCED_PARAMETER(TrapFrame);
  249. UNREFERENCED_PARAMETER(ExceptionFrame);
  250. #endif // !define(NT_UP)
  251. return;
  252. }
  253. KCONTINUE_STATUS
  254. KeSwitchFrozenProcessor (
  255. IN ULONG ProcessorNumber
  256. )
  257. {
  258. #if !defined(NT_UP)
  259. PKPRCB TargetPrcb, CurrentPrcb;
  260. //
  261. // If Processor number is out of range, reselect current processor
  262. //
  263. if (ProcessorNumber >= (ULONG) KeNumberProcessors) {
  264. return ContinueProcessorReselected;
  265. }
  266. TargetPrcb = KiProcessorBlock[ProcessorNumber];
  267. CurrentPrcb = KeGetCurrentPrcb();
  268. //
  269. // Move active flag to correct processor.
  270. //
  271. CurrentPrcb->IpiFrozen &= ~FREEZE_ACTIVE;
  272. TargetPrcb->IpiFrozen |= FREEZE_ACTIVE;
  273. //
  274. // If this processor is frozen in KiFreezeTargetExecution, return to it
  275. //
  276. if (FrozenState(CurrentPrcb->IpiFrozen) == TARGET_FROZEN) {
  277. return ContinueNextProcessor;
  278. }
  279. //
  280. // This processor must be FREEZE_OWNER, wait to be reselected as the
  281. // active processor
  282. //
  283. if (FrozenState(CurrentPrcb->IpiFrozen) != FREEZE_OWNER) {
  284. return ContinueError;
  285. }
  286. while (!(CurrentPrcb->IpiFrozen & FREEZE_ACTIVE)) {
  287. KeYieldProcessor();
  288. }
  289. #else
  290. UNREFERENCED_PARAMETER(ProcessorNumber);
  291. #endif // !defined(NT_UP)
  292. //
  293. // Reselect this processor
  294. //
  295. return ContinueProcessorReselected;
  296. }
  297. VOID
  298. KeThawExecution (
  299. IN BOOLEAN Enable
  300. )
  301. /*++
  302. Routine Description:
  303. This function thaws the execution of all other processors in the host
  304. configuration and then returns to the caller. It is intended for use by
  305. the kernel debugger.
  306. Arguments:
  307. Enable - Supplies the previous interrupt enable that is to be restored
  308. after having thawed the execution of all other processors.
  309. Return Value:
  310. None.
  311. --*/
  312. {
  313. #if !defined(NT_UP)
  314. KIRQL OldIrql;
  315. KAFFINITY TargetSet;
  316. ULONG BitNumber;
  317. ULONG Flag;
  318. PKPRCB Prcb;
  319. //
  320. // Before releasing FreezeExecutionLock clear any all targets IpiFrozen
  321. // flag.
  322. //
  323. KeGetCurrentPrcb()->IpiFrozen = RUNNING;
  324. TargetSet = KeActiveProcessors & ~(AFFINITY_MASK(KeGetCurrentProcessorNumber()));
  325. while (TargetSet != 0) {
  326. KeFindFirstSetLeftAffinity(TargetSet, &BitNumber);
  327. ClearMember(BitNumber, TargetSet);
  328. Prcb = KiProcessorBlock[BitNumber];
  329. #if IDBG
  330. //
  331. // If the target processor was not forzen, then don't wait
  332. // for target to unfreeze.
  333. //
  334. if (FrozenState(Prcb->IpiFrozen) != TARGET_FROZEN) {
  335. Prcb->IpiFrozen = RUNNING;
  336. continue;
  337. }
  338. #endif
  339. Prcb->IpiFrozen = TARGET_THAW;
  340. while (Prcb->IpiFrozen == TARGET_THAW) {
  341. KeYieldProcessor();
  342. }
  343. }
  344. //
  345. // Capture the previous IRQL before releasing the freeze lock.
  346. //
  347. OldIrql = KiOldIrql;
  348. #if IDBG
  349. Flag = KiFreezeFlag;
  350. KiFreezeFlag = 0;
  351. if ((Flag & FREEZE_BACKUP) != 0) {
  352. KiReleaseSpinLock(&KiFreezeLockBackup);
  353. } else {
  354. KiReleaseSpinLock(&KiFreezeExecutionLock);
  355. }
  356. #else
  357. KiFreezeFlag = 0;
  358. KiReleaseSpinLock(&KiFreezeExecutionLock);
  359. #endif
  360. #endif // !defined (NT_UP)
  361. //
  362. // Flush the current TB, instruction cache, and data cache.
  363. //
  364. KeFlushCurrentTb();
  365. KeSweepCurrentIcache();
  366. KeSweepCurrentDcache();
  367. //
  368. // Lower IRQL and restore interrupt enable
  369. //
  370. #if !defined(NT_UP)
  371. KeLowerIrql(OldIrql);
  372. #endif
  373. KeEnableInterrupts(Enable);
  374. return;
  375. }
  376. VOID
  377. KiPollFreezeExecution(
  378. VOID
  379. )
  380. /*++
  381. Routine Description:
  382. This routine is called from code that is spinning with interrupts
  383. disabled, waiting for something to happen, when there is some
  384. (possibly extremely small) chance that that thing will not happen
  385. because a system freeze has been initiated.
  386. N.B. Interrupts are disabled.
  387. Arguments:
  388. None.
  389. Return Value:
  390. None.
  391. --*/
  392. {
  393. //
  394. // Check to see if a freeze is pending for this processor.
  395. //
  396. PKPRCB Prcb = KeGetCurrentPrcb();
  397. if ((Prcb->RequestSummary & IPI_FREEZE) != 0) {
  398. //
  399. // Clear the freeze request and freeze this processor.
  400. //
  401. InterlockedExchangeAdd((PLONG)&Prcb->RequestSummary, -(IPI_FREEZE));
  402. KiFreezeTargetExecution(NULL, NULL);
  403. } else {
  404. //
  405. // No freeze pending, assume this processor is spinning.
  406. //
  407. KeYieldProcessor();
  408. }
  409. }