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.

192 lines
4.2 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. alignem.c
  5. Abstract:
  6. This module contains the code that is executed when a misaligned
  7. data reference must be "emulated".
  8. Author:
  9. Forrest C. Foltz (forrestf) 05-Feb-2000
  10. Environment:
  11. Kernel mode only.
  12. Revision History:
  13. --*/
  14. #include "ki.h"
  15. //
  16. // Flags used in KTHREAD.AlignmentEmulationFlags
  17. //
  18. #define AFE_EMULATING_ALIGNMENT_FAULT 0x01
  19. #define AFE_TF_FLAG_WAS_SET 0x02
  20. BOOLEAN
  21. KiEmulateReference (
  22. IN OUT PEXCEPTION_RECORD ExceptionRecord,
  23. IN OUT PKEXCEPTION_FRAME ExceptionFrame,
  24. IN OUT PKTRAP_FRAME TrapFrame
  25. )
  26. /*++
  27. Routine Description:
  28. This function is called to emulate an unaligned data reference to an
  29. address in the user part of the address space.
  30. On AMD64, this function doesn't actually perform an emulation. Instead,
  31. it:
  32. - Turns off the alignment check (AC) bit in EFLAGS
  33. - Turns on the single step (TF) bit in EFLAGS
  34. Arguments:
  35. ExceptionRecord - Supplies a pointer to an exception record.
  36. ExceptionFrame - Supplies a pointer to an exception frame.
  37. TrapFrame - Supplies a pointer to a trap frame.
  38. Return Value:
  39. A value of TRUE is returned if the data reference is successfully
  40. emulated. Otherwise, a value of FALSE is returned.
  41. --*/
  42. {
  43. PKTHREAD thread;
  44. //
  45. // Indicate that we are in the middle of alignment fault emulation.
  46. //
  47. // After the instruction is executed and the trap 1 handler is invoked,
  48. // KiEmulateReferenceComplete() (following) will restore the normal
  49. // state.
  50. //
  51. thread = KeGetCurrentThread();
  52. ASSERT(thread->AlignmentEmulationFlags == 0);
  53. thread->AlignmentEmulationFlags = AFE_EMULATING_ALIGNMENT_FAULT;
  54. //
  55. // Record whether the single-step flag was set when we took
  56. // the fault.
  57. //
  58. if ((TrapFrame->EFlags & EFLAGS_TF_MASK) != 0) {
  59. thread->AlignmentEmulationFlags |= AFE_TF_FLAG_WAS_SET;
  60. }
  61. //
  62. // Turn off the AC flag and turn on the TF flag
  63. //
  64. TrapFrame->EFlags =
  65. (TrapFrame->EFlags & ~EFLAGS_AC_MASK) | EFLAGS_TF_MASK;
  66. return TRUE;
  67. }
  68. BOOLEAN
  69. KiEmulateReferenceComplete (
  70. IN OUT PKTRAP_FRAME TrapFrame
  71. )
  72. /*++
  73. Routine Description:
  74. This routine is called from the single-step (trap01) handler. It's
  75. purpose is to determine whether an alignment fault emulation has just
  76. completed and if so, restore the cpu state to the non-emulating state.
  77. Arguments:
  78. TrapFrame - Supplies a pointer to a trap frame.
  79. Return Value:
  80. A value of TRUE is returned when the trap should be forwarded to the
  81. exception dispatcher. FALSE indicates that execution may be resumed
  82. immediately upon returning from this routine.
  83. --*/
  84. {
  85. PKTHREAD thread;
  86. UCHAR emulationFlags;
  87. thread = KeGetCurrentThread();
  88. //
  89. // Check if we are currently emulating an alignment fault at this address.
  90. //
  91. emulationFlags = thread->AlignmentEmulationFlags;
  92. if ((emulationFlags & AFE_EMULATING_ALIGNMENT_FAULT) == 0) {
  93. //
  94. // This single-step wasn't the result of any alignment emulation that
  95. // we're doing, so indicate that the debug exception dispatcher
  96. // should be called.
  97. //
  98. return TRUE;
  99. }
  100. //
  101. // Clear the emulation flags in the thread, we've got a local copy.
  102. //
  103. thread->AlignmentEmulationFlags = 0;
  104. //
  105. // This single-step is the indication that an alignment emulation has
  106. // just completed. Restore the AC and TF flags.
  107. //
  108. if ((emulationFlags & AFE_TF_FLAG_WAS_SET) == 0) {
  109. //
  110. // The TF flag was not set when the alignment fault was first
  111. // encountered, so clear it now. Also set the AC flag. Indicate
  112. // that this trap 01 need not be forwarded any further.
  113. //
  114. TrapFrame->EFlags =
  115. (TrapFrame->EFlags | EFLAGS_AC_MASK) & ~EFLAGS_TF_MASK;
  116. return FALSE;
  117. } else {
  118. //
  119. // The TF flag was set when the alignment fault was first
  120. // encountered. Leave it set, restore the AC flag, and indicate
  121. // that this trap 01 should be forwarded to the exception dispatcher.
  122. //
  123. TrapFrame->EFlags |= EFLAGS_AC_MASK;
  124. return TRUE;
  125. }
  126. }