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.

228 lines
4.6 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. vdmint21.c
  5. Abstract:
  6. This module implements interfaces that support manipulation of i386
  7. int 21 entry of IDT. These entry points only exist on i386 machines.
  8. Author:
  9. Shie-Lin Tzong (shielint) 26-Dec-1993
  10. Environment:
  11. Kernel mode only.
  12. Revision History:
  13. --*/
  14. #include "ki.h"
  15. #pragma hdrstop
  16. #include "vdmntos.h"
  17. #define IDT_ACCESS_DPL_USER 0x6000
  18. #define IDT_ACCESS_TYPE_386_TRAP 0xF00
  19. #define IDT_ACCESS_TYPE_286_TRAP 0x700
  20. #define IDT_ACCESS_PRESENT 0x8000
  21. #define LDT_MASK 4
  22. //
  23. // External Reference
  24. //
  25. BOOLEAN
  26. Ki386GetSelectorParameters(
  27. IN USHORT Selector,
  28. OUT PULONG Flags,
  29. OUT PULONG Base,
  30. OUT PULONG Limit
  31. );
  32. //
  33. // Define forward referenced function prototypes.
  34. //
  35. VOID
  36. Ki386LoadTargetInt21Entry (
  37. IN PKIPI_CONTEXT SignalDone,
  38. IN PVOID Parameter1,
  39. IN PVOID Parameter2,
  40. IN PVOID Parameter3
  41. );
  42. #define KiLoadInt21Entry() \
  43. KeGetPcr()->IDT[0x21] = PsGetCurrentProcess()->Pcb.Int21Descriptor
  44. NTSTATUS
  45. Ke386SetVdmInterruptHandler (
  46. PKPROCESS Process,
  47. ULONG Interrupt,
  48. USHORT Selector,
  49. ULONG Offset,
  50. BOOLEAN Gate32
  51. )
  52. /*++
  53. Routine Description:
  54. The specified (software) interrupt entry of IDT will be updated to
  55. point to the specified handler. For all threads which belong to the
  56. specified process, their execution processors will be notified to
  57. make the same change.
  58. This function only exists on i386 and i386 compatible processors.
  59. No checking is done on the validity of the interrupt handler.
  60. Arguments:
  61. Process - Pointer to KPROCESS object describing the process for
  62. which the int 21 entry is to be set.
  63. Interrupt - The software interrupt vector which will be updated.
  64. Selector, offset - Specified the address of the new handler.
  65. Gate32 - True if the gate should be 32 bit, false otherwise
  66. Return Value:
  67. NTSTATUS.
  68. --*/
  69. {
  70. KIRQL OldIrql;
  71. BOOLEAN LocalProcessor;
  72. KAFFINITY TargetProcessors;
  73. PKPRCB Prcb;
  74. KIDTENTRY IdtDescriptor;
  75. ULONG Flags, Base, Limit;
  76. //
  77. // Check the validity of the request
  78. // 1. Currently, we support int21 redirection only
  79. // 2. The specified interrupt handler must be in user space.
  80. //
  81. if (Interrupt != 0x21 || Offset >= (ULONG)MM_HIGHEST_USER_ADDRESS ||
  82. !Ki386GetSelectorParameters(Selector, &Flags, &Base, &Limit) ){
  83. return(STATUS_INVALID_PARAMETER);
  84. }
  85. //
  86. // Initialize the contents of the IDT entry
  87. //
  88. IdtDescriptor.Offset = (USHORT)Offset;
  89. IdtDescriptor.Selector = Selector | RPL_MASK | LDT_MASK;
  90. IdtDescriptor.ExtendedOffset = (USHORT)(Offset >> 16);
  91. IdtDescriptor.Access = IDT_ACCESS_DPL_USER | IDT_ACCESS_PRESENT;
  92. if (Gate32) {
  93. IdtDescriptor.Access |= IDT_ACCESS_TYPE_386_TRAP;
  94. } else {
  95. IdtDescriptor.Access |= IDT_ACCESS_TYPE_286_TRAP;
  96. }
  97. //
  98. // Acquire the context swap lock so a context switch will not occur.
  99. //
  100. KiLockContextSwap(&OldIrql);
  101. //
  102. // Set the Ldt fields in the process object
  103. //
  104. Process->Int21Descriptor = IdtDescriptor;
  105. //
  106. // Tell all processors active for this process to reload their LDTs
  107. //
  108. #if !defined(NT_UP)
  109. Prcb = KeGetCurrentPrcb();
  110. TargetProcessors = Process->ActiveProcessors & ~Prcb->SetMember;
  111. if (TargetProcessors != 0) {
  112. KiIpiSendPacket(TargetProcessors,
  113. Ki386LoadTargetInt21Entry,
  114. NULL,
  115. NULL,
  116. NULL);
  117. }
  118. #endif
  119. KiLoadInt21Entry();
  120. #if !defined(NT_UP)
  121. //
  122. // Wait until all of the target processors have finished reloading
  123. // their LDT.
  124. //
  125. if (TargetProcessors != 0) {
  126. KiIpiStallOnPacketTargets(TargetProcessors);
  127. }
  128. #endif
  129. //
  130. // Restore IRQL and unlock the context swap lock.
  131. //
  132. KiUnlockContextSwap(OldIrql);
  133. return STATUS_SUCCESS;
  134. }
  135. #if !defined(NT_UP)
  136. VOID
  137. Ki386LoadTargetInt21Entry (
  138. IN PKIPI_CONTEXT PacketContext,
  139. IN PVOID Parameter1,
  140. IN PVOID Parameter2,
  141. IN PVOID Parameter3
  142. )
  143. /*++
  144. Routine Description:
  145. Reload local Ldt register and clear signal bit in TargetProcessor mask
  146. Arguments:
  147. Argument - pointer to a ipi packet structure.
  148. ReadyFlag - Pointer to flag to be set once LDTR has been reloaded
  149. Return Value:
  150. none.
  151. --*/
  152. {
  153. //
  154. // Set the int 21 entry of IDT from currently active process object
  155. //
  156. KiLoadInt21Entry();
  157. KiIpiSignalPacketDone(PacketContext);
  158. return;
  159. }
  160. #endif