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.

485 lines
12 KiB

  1. title "Miscellaneous support routines"
  2. ;++
  3. ;
  4. ;Copyright (c) 1991 Microsoft Corporation
  5. ;
  6. ;Module Name:
  7. ;
  8. ; vdmmisc.asm
  9. ;
  10. ;Abstract:
  11. ;
  12. ; This module contains miscellaneous support touines
  13. ;
  14. ;Author:
  15. ;
  16. ; Dave Hastings (daveh) 23-Feb-1992
  17. ;
  18. ;Revision History:
  19. ; 18-Dec-1992 sudeepb wrote vdmdispatchbop in assembly for performance
  20. ;
  21. ;--
  22. .386p
  23. .xlist
  24. include ks386.inc
  25. include callconv.inc
  26. include mi386.inc
  27. include vdm.inc
  28. include vdmtib.inc
  29. page ,132
  30. _PAGE SEGMENT PARA PUBLIC 'CODE'
  31. ASSUME DS:NOTHING, ES:NOTHING, SS:NOTHING, FS:NOTHING, GS:NOTHING
  32. EXTRNP _Ki386AdjustEsp0,1
  33. EXTRNP _KeRaiseIrql,2
  34. EXTRNP _KeLowerIrql,1
  35. EXTRNP _KeGetCurrentIrql,0
  36. EXTRNP _KiDispatchException,5
  37. EXTRNP _ObWaitForSingleObject,3
  38. EXTRNP _NtReleaseSemaphore,3
  39. EXTRNP _VdmpIsThreadTerminating, 1
  40. EXTRNP _NtSetEvent,2
  41. extrn _KeI386EFlagsAndMaskV86:DWORD
  42. extrn _KeI386EFlagsOrMaskV86:DWORD
  43. extrn _MmUserProbeAddress:DWORD
  44. _PAGE ENDS
  45. _DATA SEGMENT DWORD PUBLIC 'DATA'
  46. public IcaLockTimeout
  47. IcaLockTimeout DWORD 0ff676980h,0ffffffffh ; 1 sec time out in - hundred nanosecs
  48. _DATA ENDS
  49. _PAGE SEGMENT
  50. ASSUME DS:FLAT, ES:NOTHING, SS:FLAT, FS:NOTHING, GS:NOTHING
  51. page ,132
  52. subttl "Switch between two contexts"
  53. ;++
  54. ;
  55. ; Routine Description:
  56. ;
  57. ; This routine unloads a context from a kframe, and loads a different
  58. ; context in it's place.
  59. ;
  60. ; ASSUMES that Irql is APC level, if it is not this routine
  61. ; may produce incorrect trapframes.
  62. ;
  63. ; Arguments:
  64. ;
  65. ; esp + 4 = PKTRAP_FRAME TrapFrame
  66. ; esp + 8 = PCONTEXT OutGoing
  67. ; esp + c = PCONTEXT InComming
  68. ;
  69. ; Returns:
  70. ;
  71. ; Nothing
  72. ;
  73. ;
  74. cPublicProc _VdmSwapContexts,3
  75. push ebp
  76. mov ebp,esp
  77. push esi
  78. push edi
  79. push ebx
  80. if DBG
  81. EXTRNP _DbgBreakPoint, 0
  82. stdcall _KeGetCurrentIrql
  83. cmp al, APC_LEVEL
  84. je vs05
  85. stdcall _DbgBreakPoint
  86. vs05:
  87. endif
  88. ;
  89. ;
  90. ; Move context from trap frame to outgoing context
  91. ;
  92. mov esi,[ebp + 8]
  93. mov edi,[ebp + 0ch]
  94. if DBG
  95. ;
  96. ; Insure that we are really working on a stack frame
  97. ;
  98. cmp [esi].TsDbgArgMark, 0BADB0D00h
  99. jne vscfail
  100. endif
  101. test dword ptr [esi].TsEFlags,EFLAGS_V86_MASK
  102. jz vs10
  103. ;
  104. ;
  105. ; Move segment registers
  106. ;
  107. mov eax,[esi].TsV86Gs
  108. mov [edi].CsSegGs,eax
  109. mov eax,[esi].TsV86Fs
  110. mov [edi].CsSegFs,eax
  111. mov eax,[esi].TsV86Es
  112. mov [edi].CsSegEs,eax
  113. mov eax,[esi].TsV86Ds
  114. mov [edi].CsSegDs,eax
  115. jmp short vs20
  116. vs10:
  117. cmp word ptr [esi].TsSegCs,KGDT_R3_CODE OR RPL_MASK
  118. je vs20 ; Flat Mode
  119. mov eax,[esi].TsSegGs
  120. mov [edi].CsSegGs,eax
  121. mov eax,[esi].TsSegFs
  122. mov [edi].CsSegFs,eax
  123. mov eax,[esi].TsSegEs
  124. mov [edi].CsSegEs,eax
  125. mov eax,[esi].TsSegDs
  126. mov [edi].CsSegDs,eax
  127. vs20:
  128. mov eax,[esi].TsSegCs
  129. mov [edi].CsSegCs,eax
  130. mov eax,[esi].TsHardwareSegSs
  131. mov [edi].CsSegSs,eax
  132. ;
  133. ; Move General Registers
  134. ;
  135. mov eax,[esi].TsEax
  136. mov [edi].CsEax,eax
  137. mov eax,[esi].TsEbx
  138. mov [edi].CsEbx,eax
  139. mov eax,[esi].TsEcx
  140. mov [edi].CsEcx,eax
  141. mov eax,[esi].TsEdx
  142. mov [edi].CsEdx,eax
  143. mov eax,[esi].TsEsi
  144. mov [edi].CsEsi,eax
  145. mov eax,[esi].TsEdi
  146. mov [edi].CsEdi,eax
  147. ;
  148. ; Move Pointer registers
  149. ;
  150. mov eax,[esi].TsEbp
  151. mov [edi].CsEbp,eax
  152. mov eax,[esi].TsHardwareEsp
  153. mov [edi].CsEsp,eax
  154. mov eax,[esi].TsEip
  155. mov [edi].CsEip,eax
  156. ;
  157. ; Move Flags
  158. ;
  159. mov eax,[esi].TsEFlags
  160. mov [edi].CsEFlags,eax
  161. ;
  162. ; Move incoming context to trap frame
  163. ;
  164. mov edi,esi
  165. mov esi,[ebp + 10h]
  166. mov eax,[esi].CsSegCs
  167. mov ebx,[esi].CsSegSs
  168. test dword ptr [esi].CsEFlags, EFLAGS_V86_MASK
  169. jnz vsc05 ; don't worry about v86 segments
  170. or ax, 3 ; RPL 3 only
  171. or bx, 3 ; RPL 3 only
  172. vsc05: mov [edi].TsSegCs,eax
  173. mov [edi].TsHardwareSegSs,ebx
  174. ;
  175. ; Move General Registers
  176. ;
  177. mov eax,[esi].CsEax
  178. mov [edi].TsEax,eax
  179. mov eax,[esi].CsEbx
  180. mov [edi].TsEbx,eax
  181. mov eax,[esi].CsEcx
  182. mov [edi].TsEcx,eax
  183. mov eax,[esi].CsEdx
  184. mov [edi].TsEdx,eax
  185. mov eax,[esi].CsEsi
  186. mov [edi].TsEsi,eax
  187. mov eax,[esi].CsEdi
  188. mov [edi].TsEdi,eax
  189. ;
  190. ; Move Pointer registers
  191. ;
  192. mov eax,[esi].CsEbp
  193. mov [edi].TsEbp,eax
  194. mov eax,[esi].CsEsp
  195. mov [edi].TsHardwareEsp,eax
  196. mov eax,[esi].CsEip
  197. mov [edi].TsEip,eax
  198. ;
  199. ; Move Flags
  200. ;
  201. mov eax,[esi].CsEFlags
  202. test eax,EFLAGS_V86_MASK
  203. jne vsc10
  204. and eax,EFLAGS_USER_SANITIZE
  205. or eax,EFLAGS_INTERRUPT_MASK
  206. jmp vsc15
  207. vsc10: and eax,_KeI386EFlagsAndMaskV86
  208. or eax,_KeI386EFlagsOrMaskV86
  209. vsc15: mov [edi].TsEFlags,eax
  210. ;
  211. ; Fix Esp 0 as necessary
  212. ;
  213. mov esi,[ebp+0ch]
  214. xor eax,[esi].CsEFlags
  215. mov esi,[ebp + 10h]
  216. test eax,EFLAGS_V86_MASK
  217. jz vsc20
  218. stdCall _Ki386AdjustEsp0, <edi>
  219. test dword ptr [edi].TsEFlags,EFLAGS_V86_MASK
  220. jz vsc20
  221. ;
  222. ; Move segment registers for vdm
  223. ;
  224. mov eax,[esi].CsSegGs
  225. mov [edi].TsV86Gs,eax
  226. mov eax,[esi].CsSegFs
  227. mov [edi].TsV86Fs,eax
  228. mov eax,[esi].CsSegEs
  229. mov [edi].TsV86Es,eax
  230. mov eax,[esi].CsSegDs
  231. mov [edi].TsV86Ds,eax
  232. jmp short vsc30
  233. vsc20:
  234. ;
  235. ; Move segment registers for monitor
  236. ;
  237. mov eax,[esi].CsSegGs
  238. mov [edi].TsSegGs,eax
  239. mov eax,[esi].CsSegFs
  240. mov [edi].TsSegFs,eax
  241. mov eax,[esi].CsSegEs
  242. mov [edi].TsSegEs,eax
  243. mov eax,[esi].CsSegDs
  244. mov [edi].TsSegDs,eax
  245. ;
  246. ; We are going back to 32 bit monitor code. Set Trapframe exception list
  247. ; to END_OF_CHAIN such that we won't bugcheck in KiExceptionExit.
  248. ;
  249. mov eax, 0ffffffffh
  250. mov [edi].TsExceptionList, eax
  251. vsc30:
  252. pop ebx
  253. pop edi
  254. pop esi
  255. mov esp,ebp
  256. pop ebp
  257. stdRET _VdmSwapContexts
  258. if DBG
  259. vscfail: int 3
  260. endif
  261. _VdmSwapContexts endp
  262. CriticalSection equ [esp+4]
  263. page , 132
  264. subttl "VdmpEnterCriticalSection"
  265. ;++
  266. ;
  267. ; NTSTATUS
  268. ; VdmpEnterIcaLock(
  269. ; IN PRTL_CRITICAL_SECTION pIcaLock
  270. ; )
  271. ;
  272. ; Routine Description:
  273. ;
  274. ; This function enters a UserMode critical section, with a fixed Timeout
  275. ; of several minutes.
  276. ;
  277. ; Touching the critical section may cause an exception to be raised which
  278. ; the caller must handle, since the critical section may be in UserMode
  279. ; memory.
  280. ;
  281. ;
  282. ; Arguments:
  283. ;
  284. ; CriticalSection - supplies a pointer to a critical section.
  285. ;
  286. ; Return Value:
  287. ;
  288. ; STATUS_SUCCESS - wait was satisfied and the thread owns the CS
  289. ; STATUS_INVALID_HANDLE - no semaphore available to wait on.
  290. ; STATUS_TIMEOUT
  291. ;
  292. ;
  293. ;--
  294. align 16
  295. cPublicProc _VdmpEnterIcaLock,1
  296. cPublicFpo 1,0
  297. mov edx,CriticalSection ; interlocked inc of
  298. mov ecx,PCR[PcTeb]
  299. mov ecx,TbClientId+4[ecx] ; NtCurrentTeb()->ClientId.UniqueThread
  300. mov eax, STATUS_INVALID_HANDLE
  301. cmp dword ptr CsLockSemaphore[edx],0 ; avoid lazy creates
  302. jz short Eil20
  303. xor eax,eax ; assume success
  304. lock inc dword ptr CsLockCount[edx] ; ... CriticalSection->LockCount
  305. jnz short Eil30
  306. ;
  307. ; Set Curr thread as Owner of CS with recursion count of 1
  308. ; and return SUCCESS
  309. ;
  310. Eil10:
  311. mov CsOwningThread[edx],ecx
  312. mov dword ptr CsRecursionCount[edx],1
  313. Eil20:
  314. stdRET _VdmpEnterIcaLock
  315. ;
  316. ; If curr thread already owns CS,
  317. ; inc recusrion count and return SUCCESS
  318. ;
  319. Eil30:
  320. cmp CsOwningThread[edx],ecx
  321. jne short Eil42
  322. inc dword ptr CsRecursionCount[edx]
  323. stdRET _VdmpEnterIcaLock
  324. ;
  325. ; Another Thread owns the CS so Wait on the lock semaphore,
  326. ;
  327. Eil40:
  328. mov edx, CriticalSection
  329. Eil42:
  330. xor eax,eax
  331. lea ecx, IcaLockTimeout
  332. stdCall _ObWaitForSingleObject <CsLockSemaphore[edx], eax, ecx>
  333. mov ecx,PCR[PcTeb]
  334. mov ecx,TbClientId+4[ecx] ; NtCurrentTeb()->ClientId.UniqueThread
  335. mov edx,CriticalSection
  336. or eax, eax
  337. jz short Eil10 ; Take Ownership of CS
  338. ;
  339. ; If !NT_SUCCESS(Status) return with error. else some other
  340. ; less severe error occurred. In that case if thread terminating
  341. ; fail. Note: we may wake for user apc's even tho we are non
  342. ; alertable, because the vdm hw int dispatching code, and PsThread
  343. ; termination code forces these to occur.
  344. ;
  345. test eax, 080000000h
  346. jnz short Eil20 ; exit with Status in eax
  347. Eil50:
  348. stdCall _VdmpIsThreadTerminating <ecx> ; check for Term of self
  349. or eax, eax
  350. jnz short Eil20 ; exit with Status in eax
  351. mov edx, CriticalSection
  352. mov eax, CsOwningThread[edx]
  353. stdCall _VdmpIsThreadTerminating <eax> ; check for Term of CSOwner
  354. or eax, eax
  355. jz short Eil40 ; retry
  356. jmp short Eil20 ; exit with Status in eax
  357. stdENDP _VdmpEnterIcaLock
  358. page , 132
  359. subttl "VdmpLeaveIcaLock"
  360. ;++
  361. ;
  362. ; NTSTATUS
  363. ; VdmpLeaveIcaLock(
  364. ; IN PRTL_CRITICAL_SECTION pIcaLock
  365. ; )
  366. ;
  367. ; Routine Description:
  368. ;
  369. ; This function leaves a critical section.
  370. ;
  371. ; Touching the critical section may cause an exception to be raised which
  372. ; the caller must handle, since the critical section may be in UserMode
  373. ; memory.
  374. ;
  375. ; Arguments:
  376. ;
  377. ; CriticalSection - supplies a pointer to a critical section.
  378. ;
  379. ; Return Value:
  380. ;
  381. ; STATUS_SUCCESS
  382. ; STATUS_INVALID_OWNER
  383. ; or NTSTATUS code from NtReleaseSemaphore
  384. ;
  385. ;--
  386. align 16
  387. cPublicProc _VdmpLeaveIcaLock,1
  388. cPublicFpo 1,0
  389. mov edx,CriticalSection
  390. mov ecx,PCR[PcTeb]
  391. mov ecx,TbClientId+4[ecx] ; NtCurrentTeb()->ClientId.UniqueThread
  392. mov eax,STATUS_INVALID_OWNER ; Verify Owner of CritSect
  393. cmp ecx,CsOwningThread[edx]
  394. jne short Lil10
  395. xor eax,eax ; Assume STATUS_SUCCESS
  396. dec dword ptr CsRecursionCount[edx]
  397. jnz short Lil30 ; leaving recursion
  398. mov CsOwningThread[edx],eax ; clear owning thread id
  399. lock dec dword ptr CsLockCount[edx] ; interlocked dec of LockCount
  400. jge short Lil20 ; Thread waiting on LockSemaphore ?
  401. Lil10:
  402. stdRET _VdmpLeaveIcaLock
  403. ;
  404. ; release another thread waiting on the LockSemaphore
  405. ; and exit
  406. Lil20:
  407. stdCall _NtSetEvent, <CsLockSemaphore[edx], 0>
  408. stdRET _VdmpLeaveIcaLock
  409. ;
  410. ; leaving recursion, just dec lock count
  411. ;
  412. Lil30:
  413. lock dec dword ptr CsLockCount[edx] ; interlocked dec of LockCount
  414. stdRET _VdmpLeaveIcaLock
  415. _VdmpLeaveIcaLock endp
  416. _PAGE ends
  417. end