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.

473 lines
14 KiB

  1. title "Fast Protected Mode services"
  2. ;++
  3. ;
  4. ; Copyright (c) 1989 Microsoft Corporation
  5. ;
  6. ; Module Name:
  7. ;
  8. ; fastpm.asm
  9. ;
  10. ; Abstract:
  11. ;
  12. ; This module implements a fast entry to and exit from protected mode
  13. ;
  14. ; Author:
  15. ;
  16. ; Dave Hastings (daveh) 26-Jul-91
  17. ;
  18. ;--
  19. .386p
  20. include ks386.inc
  21. include callconv.inc
  22. include bop.inc
  23. include vint.inc
  24. include vdmtib.inc
  25. _TEXT SEGMENT PARA PUBLIC 'CODE'
  26. ASSUME DS:NOTHING, ES:NOTHING, SS:FLAT, FS:NOTHING, GS:NOTHING
  27. _TEXT ENDS
  28. _DATA SEGMENT DWORD PUBLIC 'DATA'
  29. public _NTVDMpLockPrefixTable
  30. _NTVDMpLockPrefixTable label dword
  31. dd offset FLAT:_ntvdmlock1
  32. dd offset FLAT:_ntvdmlock2
  33. dd 0
  34. ClientPMStack df ?
  35. ClientPMEntry df ?
  36. _DATA ENDS
  37. _TEXT SEGMENT
  38. ; Interrupt type definitions
  39. CPU_YODA_INT equ 4
  40. BIT_CPU_YODA_INT equ 0
  41. CPU_HW_RESET equ 0
  42. BIT_CPU_HW_RESET equ 1
  43. CPU_TIMER_TICK equ 1
  44. BIT_CPU_TIMER_TICK equ 2
  45. CPU_HW_INT equ 3
  46. BIT_CPU_HW_INT equ 3
  47. assume DS:NOTHING
  48. cPublicProc _VdmTrapcHandler, 0
  49. ;
  50. ; On entry, [ebx]->VdmContext
  51. ;
  52. ;
  53. ; zero higher 16bit of esp. (The Iretd in kernel trap handler puts higher 16bit
  54. ; of kernel esp back to our user mode esp even though the higher 16bit of
  55. ; TrapFrame.HardwareEsp is zeroed.
  56. ;
  57. and esp, 0ffffh
  58. ;@@:
  59. ;
  60. ; Note, here we use app's stack to do the far return
  61. ;
  62. push [ebx].VtVdmContext.CsSegCs
  63. push [ebx].VtVdmContext.CsEip
  64. mov ebx, [ebx].VtVdmContext.CsEbx
  65. retf
  66. stdENDP _VdmTrapcHandler
  67. page ,132
  68. subttl "FastEnterPm"
  69. ;++
  70. ;
  71. ; Routine Description:
  72. ;
  73. ; This routine is a faster way to enter 16 bit vdm protected mode.
  74. ; Instead of making a system call, we just save the 32 bit state
  75. ; into the VdmTib, restore the Vdm state from the VdmTib, and do
  76. ; a far return to the application.
  77. ;
  78. ; Arguments:
  79. ;
  80. ; ss:sp + 4 = pointer to VdmTib
  81. ;
  82. ; Returns:
  83. ;
  84. ; nothing.
  85. ;
  86. assume DS:FLAT
  87. cPublicProc _FastEnterPm,0
  88. push ebp
  89. mov ebp,esp ; set up stack frame
  90. push ebx ; free up reg for pointer
  91. mov ebx, KGDT_R3_TEB OR RPL_MASK
  92. mov fs, ebx
  93. mov ebx, fs:[PcTeb]
  94. mov ebx, dword ptr [ebx].TeVdm
  95. ; translate the interrupt flag to the virtual interrupt flag
  96. test [ebx].VtVdmContext.CsEFlags,dword ptr EFLAGS_INTERRUPT_MASK
  97. jz fe10
  98. _ntvdmlock1:
  99. lock or dword ptr ds:FIXED_NTVDMSTATE_LINEAR,dword ptr VDM_VIRTUAL_INTERRUPTS
  100. test dword ptr ds:FIXED_NTVDMSTATE_LINEAR,dword ptr VDM_INTERRUPT_PENDING
  101. jz fe20
  102. ; set up event info for an interrupt acknowlege
  103. mov word ptr [ebx].VtEventInfo.EiEvent,VdmIntAck
  104. mov word ptr [ebx].VtEventInfo.EiInstructionSize,0
  105. mov word ptr [ebx].VtEventInfo.EiIntAckInfo,0
  106. pop ebx
  107. mov esp,ebp
  108. pop ebp
  109. stdRET _FastEnterPm
  110. fe10:
  111. _ntvdmlock2:
  112. lock and dword ptr ds:FIXED_NTVDMSTATE_LINEAR, NOT VDM_VIRTUAL_INTERRUPTS
  113. fe20:
  114. mov [ebx].VtMonitorContext.CsEax,eax
  115. mov eax,[ebp - 4]
  116. mov [ebx].VtMonitorContext.CsEbx,eax
  117. mov [ebx].VtMonitorContext.CsEcx,ecx
  118. mov [ebx].VtMonitorContext.CsEdx,edx
  119. mov [ebx].VtMonitorContext.CsEsi,esi
  120. mov [ebx].VtMonitorContext.CsEdi,edi
  121. mov eax,[ebp]
  122. mov [ebx].VtMonitorContext.CsEbp,eax
  123. mov eax,ebp
  124. add eax,8 ; pop ebp and ret addr
  125. mov [ebx].VtMonitorContext.CsEsp,eax
  126. mov eax,[ebp + 4]
  127. mov [ebx].VtMonitorContext.CsEip,eax
  128. mov eax,cs
  129. mov [ebx].VtMonitorContext.CsSegCs,eax
  130. mov eax,ss
  131. mov [ebx].VtMonitorContext.CsSegSs,eax
  132. mov eax,ds
  133. mov [ebx].VtMonitorContext.CsSegDs,eax
  134. mov eax,es
  135. mov [ebx].VtMonitorContext.CsSegEs,eax
  136. mov eax,fs
  137. mov [ebx].VtMonitorContext.CsSegFs,eax
  138. mov eax,gs
  139. mov [ebx].VtMonitorContext.CsSegGs,eax
  140. pushfd
  141. pop eax
  142. mov [ebx].VtMonitorContext.CsEflags,eax
  143. test [ebx].VtVdmContext.CsEflags, EFLAGS_TF_MASK ; debugging?
  144. jz fe_atomic ; no, return the robust way
  145. ;
  146. ; Beginning STACK-BASED return
  147. ;
  148. ; The following code transitions us back to client code in protect mode
  149. ; using the client's stack. This is not a good thing to do in general
  150. ; since this is not how things worked on win31. But it is necessary if
  151. ; we are setting the trap flag in the EFLAGS register in order to break
  152. ; on the correct instruction.
  153. ;
  154. mov eax,[ebx].VtVdmContext.CsSegSs
  155. mov es,eax
  156. mov edi,[ebx].VtVdmContext.CsEsp ; es:edi -> stack
  157. lar eax,eax
  158. test eax,400000h ; big?
  159. jnz fe30
  160. movzx edi,di
  161. fe30: mov eax,[ebx].VtVdmContext.CsEflags
  162. sub edi,4
  163. mov es:[edi],eax ; push Eflags
  164. mov eax,[ebx].VtVdmContext.CsSegCs
  165. sub edi,4
  166. mov es:[edi],eax ; push cs
  167. mov eax,[ebx].VtVdmContext.CsEip
  168. sub edi,4
  169. mov es:[edi],eax ; push ip
  170. sub edi,4
  171. mov eax,[ebx].VtVdmContext.CsEbp ; push ebp
  172. mov es:[edi],eax
  173. fe40: push es
  174. push edi ; push ss:esp for lss esp
  175. mov eax,esp ; save sp for pushad
  176. ; simulate pushad
  177. push dword ptr [ebx].VtVdmContext.CsEax
  178. push dword ptr [ebx].VtVdmContext.CsEcx
  179. push dword ptr [ebx].VtVdmContext.CsEdx
  180. push dword ptr [ebx].VtVdmContext.CsEbx
  181. push eax
  182. push ebp ; save pointer to stack frame
  183. push dword ptr [ebx].VtVdmContext.CsEsi
  184. push dword ptr [ebx].VtVdmContext.CsEdi
  185. ; push seg regs
  186. push dword ptr [ebx].VtVdmContext.CsSegFs
  187. push dword ptr [ebx].VtVdmContext.CsSegGs
  188. push dword ptr [ebx].VtVdmContext.CsSegDs
  189. push dword ptr [ebx].VtVdmContext.CsSegEs
  190. ; set up VDM seg regs
  191. pop es
  192. pop ds
  193. pop gs ; pop es,fs,gs of invalid selectors are trapped in ntoskrnl,
  194. pop fs ; and handled by setting to zero
  195. ; set up VDM general regs
  196. popad
  197. ; set up vdm stack
  198. lss esp,[ebp - 12]
  199. ; restore ebp
  200. pop ebp
  201. ; return to VDM
  202. iretd
  203. ;
  204. ; Beginning STACK-LESS return
  205. ;
  206. ; WARNING:
  207. ; The following code does the final dispatch to the Client code.
  208. ; It uses STATIC data to hold CS, EIP, SS, ESP. THAT MAKES THIS CODE
  209. ; NON-REENTRANT. For correct operation, the rest of this code in this
  210. ; routine must execute to completion before coming back through. All
  211. ; ntvdm support code must honor this arrangement.
  212. ;
  213. ; The reason this code has this restriction is to avoid using the
  214. ; client's stack. Originally, this routine built a stack frame on the
  215. ; client stack, and IRET'd to it. This breaks some DPMI applications,
  216. ; either at a point where they have a transient condition with an invalid
  217. ; stack pointer, or because they expect unused stack space to be left
  218. ; alone by the system.
  219. ;
  220. fe_atomic:
  221. mov eax,[ebx].VtVdmContext.CsSegCs
  222. mov word ptr ClientPmEntry+4, ax
  223. mov eax,[ebx].VtVdmContext.CsEip
  224. mov dword ptr ClientPmEntry, eax
  225. mov eax,[ebx].VtVdmContext.CsSegSs
  226. mov word ptr ClientPmStack+4, ax
  227. mov eax,[ebx].VtVdmContext.CsEsp ; es:edi -> stack
  228. mov dword ptr ClientPmStack, eax
  229. mov eax,esp ; save sp for pushad
  230. ; simulate pushad
  231. push dword ptr [ebx].VtVdmContext.CsEax
  232. push dword ptr [ebx].VtVdmContext.CsEcx
  233. push dword ptr [ebx].VtVdmContext.CsEdx
  234. push dword ptr [ebx].VtVdmContext.CsEbx
  235. push eax
  236. push dword ptr [ebx].VtVdmContext.CsEbp
  237. push dword ptr [ebx].VtVdmContext.CsEsi
  238. push dword ptr [ebx].VtVdmContext.CsEdi
  239. ; push seg regs
  240. push dword ptr [ebx].VtVdmContext.CsSegFs
  241. push dword ptr [ebx].VtVdmContext.CsSegGs
  242. push dword ptr [ebx].VtVdmContext.CsSegDs
  243. push dword ptr [ebx].VtVdmContext.CsSegEs
  244. push dword ptr [ebx].VtVdmContext.CsEflags
  245. popfd
  246. ; set up VDM seg regs
  247. pop es
  248. pop ds
  249. pop gs ; pop fs,gs of invalid selectors are trapped in ntoskrnl,
  250. pop fs ; and handled by setting to zero
  251. ; set up VDM general regs
  252. popad
  253. lss esp, cs:ClientPMStack
  254. jmp fword ptr cs:ClientPMEntry
  255. stdENDP _FastEnterPm
  256. page ,132
  257. subttl "GetFastBopEntry"
  258. ;++
  259. ;
  260. ; Routine Description:
  261. ;
  262. ; This routine supplies the address of the routine that segmented
  263. ; protected mode code should call to switch to flat mode.
  264. ;
  265. ; Arguments:
  266. ;
  267. ; esp + 4 = pointer to VdmTib->VdmContext
  268. ;
  269. ; Returns:
  270. ;
  271. ; nothing.
  272. ;
  273. assume DS:FLAT
  274. cPublicProc _GetFastBopEntryAddress,1
  275. push ebp
  276. mov ebp,esp
  277. push ebx
  278. push eax
  279. mov ebx,[ebp + 8]
  280. mov [ebx].CsSegEs,cs
  281. mov eax,offset FLAT:_FastLeavePm
  282. mov word ptr [ebx].CsEbx,ax
  283. shr eax,16
  284. mov word ptr [ebx].CsEdx,ax
  285. pop eax
  286. pop ebx
  287. mov esp,ebp
  288. pop ebp
  289. stdRET _GetFastBopEntryAddress
  290. stdENDP _GetFastBopEntryAddress
  291. page ,132
  292. subttl "FastLeavePm"
  293. ;++
  294. ;
  295. ; Routine Description:
  296. ;
  297. ; This routine switches from the VDM context to the monitor context.
  298. ;
  299. ; Arguments:
  300. ;
  301. ; none
  302. ;
  303. ; Returns:
  304. ;
  305. ; executing with monitor context
  306. ;
  307. assume DS:Nothing,ES:Nothing,SS:Nothing
  308. ALIGN 16
  309. cPublicProc _FastLeavePm,0
  310. push ebx
  311. mov bx,ds
  312. push bx ; so push and pop size same
  313. mov bx,KGDT_R3_DATA OR RPL_MASK
  314. mov ds,bx
  315. assume ds:FLAT
  316. push fs
  317. mov ebx, KGDT_R3_TEB OR RPL_MASK
  318. mov fs, bx
  319. mov ebx, fs:[PcTeb]
  320. mov ebx, dword ptr [ebx].TeVdm
  321. pop fs
  322. pushfd
  323. mov dword ptr [ebx].VtVdmContext.CsEax,eax
  324. pop eax
  325. mov dword ptr [ebx].VtVdmContext.CsEFlags,eax
  326. pop ax
  327. mov word ptr [ebx].VtVdmContext.CsSegDs,ax
  328. pop eax
  329. mov dword ptr [ebx].VtVdmContext.CsEbx,eax
  330. mov dword ptr [ebx].VtVdmContext.CsEcx,ecx
  331. mov dword ptr [ebx].VtVdmContext.CsEdx,edx
  332. mov dword ptr [ebx].VtVdmContext.CsEsi,esi
  333. mov dword ptr [ebx].VtVdmContext.CsEdi,edi
  334. mov dword ptr [ebx].VtVdmContext.CsEbp,ebp
  335. mov word ptr [ebx].VtVdmContext.CsSegEs,es
  336. mov word ptr [ebx].VtVdmContext.CsSegFs,fs
  337. mov word ptr [ebx].VtVdmContext.CsSegGs,gs
  338. pop eax
  339. mov dword ptr [ebx].VtVdmContext.CsEip,eax
  340. pop eax
  341. mov word ptr [ebx].VtVdmContext.CsSegCs,ax
  342. mov dword ptr [ebx].VtVdmContext.CsEsp,esp
  343. mov word ptr [ebx].VtVdmContext.CsSegSs,ss
  344. ; switch Stacks
  345. .errnz (CsEsp + 4 - CsSegSS)
  346. lss esp, [ebx].VtMonitorContext.CsEsp
  347. ; Now running on Monitor stack
  348. ; set up event info
  349. mov word ptr [ebx].VtEventInfo.EiEvent,VdmBop
  350. mov dword ptr [ebx].VtEventInfo.EiInstructionSize,BOP_SIZE
  351. mov ax,[ebx].VtVdmContext.CsSegCs
  352. mov es,ax
  353. ; BUGBUG 16 or 32 bit !!!!!
  354. mov di,[ebx].VtVdmContext.CsEip
  355. mov al,byte ptr es:[di]
  356. movzx eax,al
  357. mov [ebx].VtEventInfo.EiBopNumber,eax
  358. sub di,2
  359. mov word ptr [ebx].VtVdmContext.CsEip,di ; set up bop bias
  360. ; set up for IRET
  361. push dword ptr [ebx].VtMonitorContext.CsEFlags
  362. push dword ptr [ebx].VtMonitorContext.CsSegCs
  363. push dword ptr [ebx].VtMonitorContext.CsEip
  364. ; simulate pushad
  365. mov eax,esp
  366. push dword ptr [ebx].VtMonitorContext.CsEax
  367. push dword ptr [ebx].VtMonitorContext.CsEcx
  368. push dword ptr [ebx].VtMonitorContext.CsEdx
  369. push dword ptr [ebx].VtMonitorContext.CsEbx
  370. push eax
  371. push dword ptr [ebx].VtMonitorContext.CsEbp
  372. push dword ptr [ebx].VtMonitorContext.CsEsi
  373. push dword ptr [ebx].VtMonitorContext.CsEdi
  374. ; push seg regs
  375. push dword ptr [ebx].VtMonitorContext.CsSegFs
  376. push dword ptr [ebx].VtMonitorContext.CsSegGs
  377. push dword ptr [ebx].VtMonitorContext.CsSegDs
  378. push dword ptr [ebx].VtMonitorContext.CsSegEs
  379. test ds:FIXED_NTVDMSTATE_LINEAR,dword ptr VDM_VIRTUAL_INTERRUPTS
  380. jz fl10
  381. or [ebx].VtVdmContext.CsEFlags,dword ptr EFLAGS_INTERRUPT_MASK
  382. jmp fl20
  383. fl10: and dword ptr [ebx].VtVdmContext.CsEFlags, NOT EFLAGS_INTERRUPT_MASK
  384. fl20:
  385. ; set up Monitor seg regs
  386. pop es
  387. pop ds
  388. pop gs
  389. pop fs
  390. ; set up Monitor general regs
  391. popad
  392. xor eax,eax ; indicate success
  393. ; clear the NT bit in EFLAGS and return with iret
  394. pushfd
  395. and dword ptr [esp], 0ffffbfffH
  396. popfd
  397. iretd
  398. stdENDP _FastLeavePm
  399. _TEXT ends
  400. end