Source code of Windows XP (NT5)
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.

203 lines
6.2 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.
  52. //
  53. ContextRecord.ContextFlags = CONTEXT_FULL;
  54. //
  55. // Push the user RSE state back out to user mode.
  56. //
  57. KeFlushUserRseState (TrapFrame);
  58. KiSaveHigherFPVolatile(GET_HIGH_FLOATING_POINT_REGISTER_SAVEAREA(KeGetCurrentThread()->StackBase));
  59. TrapFrame->StIPSR &= ~(1i64 << PSR_MFH);
  60. KeContextFromKframes(TrapFrame, ExceptionFrame, &ContextRecord);
  61. //
  62. // Transfer the context information to the user stack, initialize the
  63. // APC routine parameters, and modify the trap frame so execution will
  64. // continue in user mode at the user mode APC dispatch routine.
  65. //
  66. // We build the following structure on the user stack:
  67. //
  68. // | |
  69. // |-------------------------------|
  70. // | |
  71. // | Interrupted user's |
  72. // | stack frame |
  73. // | |
  74. // | |
  75. // |-------------------------------|
  76. // | Slack Space due to the |
  77. // | 16-byte stack alignment |
  78. // | - - - - - - - - - - - - - - - |
  79. // | NormalRoutine |
  80. // | SystemArgument2 |
  81. // | SystemArgument1 |
  82. // | NormalContext |
  83. // | - - - - - - - - - - - - - - - |
  84. // | Context Frame |
  85. // | Filled in with state |
  86. // | of interrupted user |
  87. // | program |
  88. // | - - - - - - - - - - - - - - - |
  89. // | Stack Scratch Area |
  90. // |-------------------------------|
  91. // | |
  92. try {
  93. USHORT LocalFrameSize;
  94. PPLABEL_DESCRIPTOR Plabel = (PPLABEL_DESCRIPTOR) KeUserApcDispatcher;
  95. //
  96. // Compute total length of 4 arguments, context record, and
  97. // stack scratch area.
  98. //
  99. // Compute the new 16-byte aligned user stack pointer.
  100. //
  101. Length = (4 * sizeof(ULONGLONG) + CONTEXT_LENGTH +
  102. STACK_SCRATCH_AREA + 15) & (~15);
  103. UserStack = (ContextRecord.IntSp & (~15)) - Length;
  104. Arguments = (PULONGLONG)(UserStack + STACK_SCRATCH_AREA + CONTEXT_LENGTH);
  105. //
  106. // Probe user stack area for writeability and then transfer the
  107. // context record to the user stack.
  108. //
  109. ProbeForWriteSmallStructure((PCHAR)UserStack, Length, sizeof(QUAD));
  110. RtlCopyMemory((PVOID)(UserStack+STACK_SCRATCH_AREA),
  111. &ContextRecord, sizeof(CONTEXT));
  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. // Set the address of the exception to the current program address
  142. // and raise the exception by calling the exception dispatcher.
  143. //
  144. ExceptionRecord.ExceptionAddress = (PVOID)(TrapFrame->StIIP);
  145. KiDispatchException(&ExceptionRecord,
  146. ExceptionFrame,
  147. TrapFrame,
  148. UserMode,
  149. TRUE);
  150. }
  151. return;
  152. }