1
0

dispatch.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /*++
  2. Copyright (c) 2012 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. dispatch.c
  9. Abstract:
  10. This module implements interrupt dispatch functionality for x86 processors.
  11. Author:
  12. Evan Green 27-Aug-2012
  13. Environment:
  14. Kernel
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include <minoca/kernel/kernel.h>
  20. #include <minoca/kernel/kdebug.h>
  21. #include <minoca/kernel/x86.h>
  22. //
  23. // ---------------------------------------------------------------- Definitions
  24. //
  25. //
  26. // ----------------------------------------------- Internal Function Prototypes
  27. //
  28. //
  29. // ------------------------------------------------------ Data Type Definitions
  30. //
  31. //
  32. // -------------------------------------------------------------------- Globals
  33. //
  34. //
  35. // ------------------------------------------------------------------ Functions
  36. //
  37. VOID
  38. KeDispatchSingleStepTrap (
  39. PTRAP_FRAME TrapFrame
  40. )
  41. /*++
  42. Routine Description:
  43. This routine dispatches a single step trap.
  44. Arguments:
  45. TrapFrame - Supplies a pointer to the machine state immediately before the
  46. trap.
  47. Return Value:
  48. None.
  49. --*/
  50. {
  51. CYCLE_ACCOUNT PreviousPeriod;
  52. PKTHREAD Thread;
  53. ASSERT(ArAreInterruptsEnabled() == FALSE);
  54. if (IS_TRAP_FRAME_FROM_PRIVILEGED_MODE(TrapFrame) == FALSE) {
  55. PreviousPeriod = KeBeginCycleAccounting(CycleAccountKernel);
  56. ArEnableInterrupts();
  57. Thread = KeGetCurrentThread();
  58. PsSignalThread(Thread, SIGNAL_TRAP, NULL, FALSE);
  59. PsCheckRuntimeTimers(Thread);
  60. PsDispatchPendingSignals(Thread, TrapFrame);
  61. ArDisableInterrupts();
  62. //
  63. // If there is no handler or debugger yet, go into the kernel debugger.
  64. //
  65. if ((Thread->OwningProcess->SignalHandlerRoutine == NULL) &&
  66. (Thread->OwningProcess->DebugData == NULL)) {
  67. KdDebugExceptionHandler(EXCEPTION_SINGLE_STEP, NULL, TrapFrame);
  68. }
  69. KeBeginCycleAccounting(PreviousPeriod);
  70. } else {
  71. //
  72. // Here's something interesting. The sysenter instruction doesn't clear
  73. // the trap flag, so if usermode sets TF and executes sysenter, it
  74. // produces a single step exception in kernel mode. Move to the slow
  75. // system call path (so that eflags gets restored), and move Eip to a
  76. // version that sets TF in the trap frame.
  77. //
  78. if (TrapFrame->Eip == (UINTN)ArSysenterHandlerAsm) {
  79. TrapFrame->Eflags &= ~IA32_EFLAG_TF;
  80. TrapFrame->Eip = (UINTN)ArTrapSystemCallHandlerAsm;
  81. return;
  82. }
  83. KdDebugExceptionHandler(EXCEPTION_SINGLE_STEP, NULL, TrapFrame);
  84. }
  85. return;
  86. }
  87. VOID
  88. KeDispatchNmiTrap (
  89. VOID
  90. )
  91. /*++
  92. Routine Description:
  93. This routine dispatches an NMI interrupt. NMIs are task switches (to avoid
  94. a race with the sysret instruction), so the previous context is saved in a
  95. task structure.
  96. Arguments:
  97. None.
  98. Return Value:
  99. None.
  100. --*/
  101. {
  102. PTSS KernelTask;
  103. CYCLE_ACCOUNT PreviousPeriod;
  104. PPROCESSOR_BLOCK Processor;
  105. TRAP_FRAME TrapFrame;
  106. ASSERT(ArAreInterruptsEnabled() == FALSE);
  107. //
  108. // Do a little detection of nested NMIs, which are currently not supported.
  109. //
  110. Processor = KeGetCurrentProcessorBlock();
  111. Processor->NmiCount += 1;
  112. if (Processor->NmiCount == 2) {
  113. RtlDebugBreak();
  114. }
  115. PreviousPeriod = CycleAccountInvalid;
  116. ArGetKernelTssTrapFrame(&TrapFrame);
  117. if (IS_TRAP_FRAME_FROM_PRIVILEGED_MODE(&TrapFrame) == FALSE) {
  118. PreviousPeriod = KeBeginCycleAccounting(CycleAccountKernel);
  119. }
  120. //
  121. // Switch to the kernel task's CR3 in order to allow peeking at user mode
  122. // addresses if this NMI is for a debugger freeze.
  123. //
  124. KernelTask = Processor->Tss;
  125. if (KernelTask != NULL) {
  126. ArSetCurrentPageDirectory(KernelTask->Cr3);
  127. }
  128. KdNmiHandler(&TrapFrame);
  129. ArSetKernelTssTrapFrame(&TrapFrame);
  130. if (PreviousPeriod != CycleAccountInvalid) {
  131. KeBeginCycleAccounting(PreviousPeriod);
  132. }
  133. Processor->NmiCount -= 1;
  134. return;
  135. }
  136. VOID
  137. KeDispatchDebugServiceTrap (
  138. PTRAP_FRAME TrapFrame
  139. )
  140. /*++
  141. Routine Description:
  142. This routine dispatches a debug service trap.
  143. Arguments:
  144. TrapFrame - Supplies a pointer to the machine state immediately before the
  145. trap.
  146. Return Value:
  147. None.
  148. --*/
  149. {
  150. CYCLE_ACCOUNT PreviousPeriod;
  151. PKTHREAD Thread;
  152. ASSERT(ArAreInterruptsEnabled() == FALSE);
  153. if (IS_TRAP_FRAME_FROM_PRIVILEGED_MODE(TrapFrame) == FALSE) {
  154. PreviousPeriod = KeBeginCycleAccounting(CycleAccountKernel);
  155. ArEnableInterrupts();
  156. Thread = KeGetCurrentThread();
  157. PsSignalThread(Thread, SIGNAL_TRAP, NULL, FALSE);
  158. PsCheckRuntimeTimers(Thread);
  159. PsDispatchPendingSignals(Thread, TrapFrame);
  160. ArDisableInterrupts();
  161. KeBeginCycleAccounting(PreviousPeriod);
  162. } else {
  163. KdDebugExceptionHandler(TrapFrame->Eax,
  164. (PVOID)(TrapFrame->Ecx),
  165. TrapFrame);
  166. }
  167. return;
  168. }
  169. //
  170. // --------------------------------------------------------- Internal Functions
  171. //