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.

213 lines
7.1 KiB

  1. /*++
  2. Module Name:
  3. apcuser.c
  4. Abstract:
  5. This module implements the machine dependent code necessary to initialize
  6. a user mode APC.
  7. Author:
  8. William K. Cheung 26-Oct-1995
  9. based on MIPS version by David N. Cutler (davec) 23-Apr-1990
  10. Environment:
  11. Kernel mode only, IRQL APC_LEVEL.
  12. Revision History:
  13. --*/
  14. #include "ki.h"
  15. #include "kxia64.h"
  16. VOID
  17. KiSaveHigherFPVolatile (
  18. PVOID
  19. );
  20. VOID
  21. KiInitializeUserApc (
  22. IN PKEXCEPTION_FRAME ExceptionFrame,
  23. IN PKTRAP_FRAME TrapFrame,
  24. IN PKNORMAL_ROUTINE NormalRoutine,
  25. IN PVOID NormalContext,
  26. IN PVOID SystemArgument1,
  27. IN PVOID SystemArgument2
  28. )
  29. /*++
  30. Routine Description:
  31. This function is called to initialize the context for a user mode APC.
  32. Arguments:
  33. ExceptionFrame - Supplies a pointer to an exception frame.
  34. TrapFrame - Supplies a pointer to a trap frame.
  35. NormalRoutine - Supplies a pointer to the user mode APC routine.
  36. NormalContext - Supplies a pointer to the user context for the APC
  37. routine.
  38. SystemArgument1 - Supplies the first system supplied value.
  39. SystemArgument2 - Supplies the second system supplied value.
  40. Return Value:
  41. None.
  42. --*/
  43. {
  44. CONTEXT ContextRecord;
  45. EXCEPTION_RECORD ExceptionRecord;
  46. LONG Length;
  47. ULONGLONG UserStack;
  48. PULONGLONG Arguments;
  49. //
  50. // Move the user mode state from the trap and exception frames to the
  51. // context frame. Do not caputere the upper floating point registers.
  52. //
  53. C_ASSERT((CONTEXT_CONTROL | CONTEXT_LOWER_FLOATING_POINT | CONTEXT_INTEGER | CONTEXT_IA32_CONTROL | CONTEXT_HIGHER_FLOATING_POINT) == CONTEXT_FULL);
  54. ContextRecord.ContextFlags = CONTEXT_CONTROL | CONTEXT_LOWER_FLOATING_POINT | CONTEXT_INTEGER | CONTEXT_IA32_CONTROL;
  55. //
  56. // Push the user RSE state back out to user mode.
  57. //
  58. KeFlushUserRseState (TrapFrame);
  59. KeContextFromKframes(TrapFrame, ExceptionFrame, &ContextRecord);
  60. //
  61. // Transfer the context information to the user stack, initialize the
  62. // APC routine parameters, and modify the trap frame so execution will
  63. // continue in user mode at the user mode APC dispatch routine.
  64. //
  65. // We build the following structure on the user stack:
  66. //
  67. // | |
  68. // |-------------------------------|
  69. // | |
  70. // | Interrupted user's |
  71. // | stack frame |
  72. // | |
  73. // | |
  74. // |-------------------------------|
  75. // | Slack Space due to the |
  76. // | 16-byte stack alignment |
  77. // | - - - - - - - - - - - - - - - |
  78. // | NormalRoutine |
  79. // | SystemArgument2 |
  80. // | SystemArgument1 |
  81. // | NormalContext |
  82. // | - - - - - - - - - - - - - - - |
  83. // | Context Frame |
  84. // | Filled in with state |
  85. // | of interrupted user |
  86. // | program |
  87. // | - - - - - - - - - - - - - - - |
  88. // | Stack Scratch Area |
  89. // |-------------------------------|
  90. // | |
  91. try {
  92. PPLABEL_DESCRIPTOR Plabel = (PPLABEL_DESCRIPTOR) KeUserApcDispatcher;
  93. //
  94. // Compute total length of 4 arguments, context record, and
  95. // stack scratch area.
  96. //
  97. // Compute the new 16-byte aligned user stack pointer.
  98. //
  99. Length = (4 * sizeof(ULONGLONG) + CONTEXT_LENGTH +
  100. STACK_SCRATCH_AREA + 15) & (~15);
  101. UserStack = (ContextRecord.IntSp & (~15)) - Length;
  102. Arguments = (PULONGLONG)(UserStack + STACK_SCRATCH_AREA + CONTEXT_LENGTH);
  103. //
  104. // Probe user stack area for writeability and then transfer the
  105. // context record to the user stack.
  106. //
  107. ProbeForWriteSmallStructure((PCHAR)UserStack, Length, sizeof(QUAD));
  108. RtlCopyMemory((PVOID)(UserStack+STACK_SCRATCH_AREA),
  109. &ContextRecord, FIELD_OFFSET(CONTEXT, FltF32));
  110. RtlCopyMemory((PVOID)(UserStack + STACK_SCRATCH_AREA + FIELD_OFFSET(CONTEXT, StFPSR)),
  111. &ContextRecord.StFPSR, sizeof(CONTEXT) - FIELD_OFFSET(CONTEXT, StFPSR));
  112. //
  113. // Set the address of the user APC routine, the APC parameters, the
  114. // interrupt frame set, the new global pointer, and the new stack
  115. // pointer in the current trap frame. The four APC parameters are
  116. // passed via the scratch registers t0 thru t3.
  117. // Set the continuation address so control will be transfered to
  118. // the user APC dispatcher.
  119. //
  120. *Arguments++ = (ULONGLONG)NormalContext; // 1st argument
  121. *Arguments++ = (ULONGLONG)SystemArgument1; // 2nd argument
  122. *Arguments++ = (ULONGLONG)SystemArgument2; // 3rd argument
  123. *Arguments++ = (ULONGLONG)NormalRoutine; // 4th argument
  124. *(PULONGLONG)UserStack = Plabel->GlobalPointer; // user apc dispatcher gp
  125. TrapFrame->IntNats = 0; // sanitize integer Nats
  126. TrapFrame->IntSp = UserStack; // stack pointer
  127. TrapFrame->StIIP = Plabel->EntryPoint; // entry point from plabel
  128. TrapFrame->StIPSR &= ~(0x3ULL << PSR_RI); // start at bundle boundary
  129. TrapFrame->RsPFS &= 0xffffffc000000000i64; // set the initial frame
  130. TrapFrame->StIFS &= 0xffffffc000000000i64; // set the initial frame
  131. // size of KeUserApcDispatcher
  132. // to be zero.
  133. TrapFrame->StFPSR = USER_FPSR_INITIAL;
  134. //
  135. // If an exception occurs, then copy the exception information to an
  136. // exception record and handle the exception.
  137. //
  138. } except (KiCopyInformation(&ExceptionRecord,
  139. (GetExceptionInformation())->ExceptionRecord)) {
  140. //
  141. // Lower the IRQL to PASSIVE_LEVEL, set the exception address to
  142. // the current program address, and raise an exception by calling
  143. // the exception dispatcher.
  144. //
  145. // N.B. The IRQL is lowered to PASSIVE_LEVEL to allow APC interrupts
  146. // during the dispatching of the exception. The current thread
  147. // will be terminated during the dispatching of the exception,
  148. // but lowering of the IRQL is required to enable the debugger
  149. // to obtain the context of the current thread.
  150. //
  151. KeLowerIrql(PASSIVE_LEVEL);
  152. ExceptionRecord.ExceptionAddress = (PVOID)(TrapFrame->StIIP);
  153. KiDispatchException(&ExceptionRecord,
  154. ExceptionFrame,
  155. TrapFrame,
  156. UserMode,
  157. TRUE);
  158. }
  159. return;
  160. }