|
|
title "Miscellaneous support routines" ;++ ; ;Copyright (c) 1991 Microsoft Corporation ; ;Module Name: ; ; vdmmisc.asm ; ;Abstract: ; ; This module contains miscellaneous support touines ; ;Author: ; ; Dave Hastings (daveh) 23-Feb-1992 ; ;Revision History: ; 18-Dec-1992 sudeepb wrote vdmdispatchbop in assembly for performance ; ;-- .386p
.xlist include ks386.inc include callconv.inc include mi386.inc include vdm.inc include vdmtib.inc
page ,132
_PAGE SEGMENT PARA PUBLIC 'CODE' ASSUME DS:NOTHING, ES:NOTHING, SS:NOTHING, FS:NOTHING, GS:NOTHING
EXTRNP _Ki386AdjustEsp0,1 EXTRNP _KeRaiseIrql,2 EXTRNP _KeLowerIrql,1 EXTRNP _KeGetCurrentIrql,0 EXTRNP _KiDispatchException,5 EXTRNP _ObWaitForSingleObject,3 EXTRNP _NtReleaseSemaphore,3 EXTRNP _VdmpIsThreadTerminating, 1 EXTRNP _NtSetEvent,2
extrn _KeI386EFlagsAndMaskV86:DWORD extrn _KeI386EFlagsOrMaskV86:DWORD extrn _MmUserProbeAddress:DWORD
_PAGE ENDS
_DATA SEGMENT DWORD PUBLIC 'DATA' public IcaLockTimeout IcaLockTimeout DWORD 0ff676980h,0ffffffffh ; 1 sec time out in - hundred nanosecs
_DATA ENDS
_PAGE SEGMENT ASSUME DS:FLAT, ES:NOTHING, SS:FLAT, FS:NOTHING, GS:NOTHING
page ,132 subttl "Switch between two contexts" ;++ ; ; Routine Description: ; ; This routine unloads a context from a kframe, and loads a different ; context in it's place. ; ; ASSUMES that Irql is APC level, if it is not this routine ; may produce incorrect trapframes. ; ; Arguments: ; ; esp + 4 = PKTRAP_FRAME TrapFrame ; esp + 8 = PCONTEXT OutGoing ; esp + c = PCONTEXT InComming ; ; Returns: ; ; Nothing ; ; cPublicProc _VdmSwapContexts,3
push ebp mov ebp,esp push esi push edi push ebx
if DBG EXTRNP _DbgBreakPoint, 0
stdcall _KeGetCurrentIrql cmp al, APC_LEVEL je vs05 stdcall _DbgBreakPoint vs05: endif
; ; ; Move context from trap frame to outgoing context ; mov esi,[ebp + 8] mov edi,[ebp + 0ch]
if DBG ; ; Insure that we are really working on a stack frame ; cmp [esi].TsDbgArgMark, 0BADB0D00h jne vscfail endif
test dword ptr [esi].TsEFlags,EFLAGS_V86_MASK jz vs10 ; ; ; Move segment registers ; mov eax,[esi].TsV86Gs mov [edi].CsSegGs,eax mov eax,[esi].TsV86Fs mov [edi].CsSegFs,eax mov eax,[esi].TsV86Es mov [edi].CsSegEs,eax mov eax,[esi].TsV86Ds mov [edi].CsSegDs,eax jmp short vs20 vs10: cmp word ptr [esi].TsSegCs,KGDT_R3_CODE OR RPL_MASK je vs20 ; Flat Mode
mov eax,[esi].TsSegGs mov [edi].CsSegGs,eax mov eax,[esi].TsSegFs mov [edi].CsSegFs,eax mov eax,[esi].TsSegEs mov [edi].CsSegEs,eax mov eax,[esi].TsSegDs mov [edi].CsSegDs,eax vs20: mov eax,[esi].TsSegCs mov [edi].CsSegCs,eax mov eax,[esi].TsHardwareSegSs mov [edi].CsSegSs,eax ; ; Move General Registers ; mov eax,[esi].TsEax mov [edi].CsEax,eax mov eax,[esi].TsEbx mov [edi].CsEbx,eax mov eax,[esi].TsEcx mov [edi].CsEcx,eax mov eax,[esi].TsEdx mov [edi].CsEdx,eax mov eax,[esi].TsEsi mov [edi].CsEsi,eax mov eax,[esi].TsEdi mov [edi].CsEdi,eax ; ; Move Pointer registers ; mov eax,[esi].TsEbp mov [edi].CsEbp,eax mov eax,[esi].TsHardwareEsp mov [edi].CsEsp,eax mov eax,[esi].TsEip mov [edi].CsEip,eax ; ; Move Flags ; mov eax,[esi].TsEFlags mov [edi].CsEFlags,eax ; ; Move incoming context to trap frame ; mov edi,esi mov esi,[ebp + 10h] mov eax,[esi].CsSegCs mov ebx,[esi].CsSegSs test dword ptr [esi].CsEFlags, EFLAGS_V86_MASK jnz vsc05 ; don't worry about v86 segments
or ax, 3 ; RPL 3 only or bx, 3 ; RPL 3 only vsc05: mov [edi].TsSegCs,eax mov [edi].TsHardwareSegSs,ebx ; ; Move General Registers ; mov eax,[esi].CsEax mov [edi].TsEax,eax mov eax,[esi].CsEbx mov [edi].TsEbx,eax mov eax,[esi].CsEcx mov [edi].TsEcx,eax mov eax,[esi].CsEdx mov [edi].TsEdx,eax mov eax,[esi].CsEsi mov [edi].TsEsi,eax mov eax,[esi].CsEdi mov [edi].TsEdi,eax ; ; Move Pointer registers ; mov eax,[esi].CsEbp mov [edi].TsEbp,eax mov eax,[esi].CsEsp mov [edi].TsHardwareEsp,eax mov eax,[esi].CsEip mov [edi].TsEip,eax ; ; Move Flags ; mov eax,[esi].CsEFlags test eax,EFLAGS_V86_MASK jne vsc10
and eax,EFLAGS_USER_SANITIZE or eax,EFLAGS_INTERRUPT_MASK jmp vsc15
vsc10: and eax,_KeI386EFlagsAndMaskV86 or eax,_KeI386EFlagsOrMaskV86 vsc15: mov [edi].TsEFlags,eax
; ; Fix Esp 0 as necessary ; mov esi,[ebp+0ch] xor eax,[esi].CsEFlags mov esi,[ebp + 10h] test eax,EFLAGS_V86_MASK jz vsc20
stdCall _Ki386AdjustEsp0, <edi> test dword ptr [edi].TsEFlags,EFLAGS_V86_MASK jz vsc20 ; ; Move segment registers for vdm ; mov eax,[esi].CsSegGs mov [edi].TsV86Gs,eax mov eax,[esi].CsSegFs mov [edi].TsV86Fs,eax mov eax,[esi].CsSegEs mov [edi].TsV86Es,eax mov eax,[esi].CsSegDs mov [edi].TsV86Ds,eax jmp short vsc30 vsc20: ; ; Move segment registers for monitor ; mov eax,[esi].CsSegGs mov [edi].TsSegGs,eax mov eax,[esi].CsSegFs mov [edi].TsSegFs,eax mov eax,[esi].CsSegEs mov [edi].TsSegEs,eax mov eax,[esi].CsSegDs mov [edi].TsSegDs,eax ; ; We are going back to 32 bit monitor code. Set Trapframe exception list ; to END_OF_CHAIN such that we won't bugcheck in KiExceptionExit. ; mov eax, 0ffffffffh mov [edi].TsExceptionList, eax vsc30: pop ebx pop edi pop esi mov esp,ebp pop ebp stdRET _VdmSwapContexts
if DBG vscfail: int 3 endif
_VdmSwapContexts endp
CriticalSection equ [esp+4]
page , 132 subttl "VdmpEnterCriticalSection"
;++ ; ; NTSTATUS ; VdmpEnterIcaLock( ; IN PRTL_CRITICAL_SECTION pIcaLock ; ) ; ; Routine Description: ; ; This function enters a UserMode critical section, with a fixed Timeout ; of several minutes. ; ; Touching the critical section may cause an exception to be raised which ; the caller must handle, since the critical section may be in UserMode ; memory. ; ; ; Arguments: ; ; CriticalSection - supplies a pointer to a critical section. ; ; Return Value: ; ; STATUS_SUCCESS - wait was satisfied and the thread owns the CS ; STATUS_INVALID_HANDLE - no semaphore available to wait on. ; STATUS_TIMEOUT ; ;
;--
align 16 cPublicProc _VdmpEnterIcaLock,1 cPublicFpo 1,0
mov edx,CriticalSection ; interlocked inc of mov ecx,PCR[PcTeb] mov ecx,TbClientId+4[ecx] ; NtCurrentTeb()->ClientId.UniqueThread
mov eax, STATUS_INVALID_HANDLE cmp dword ptr CsLockSemaphore[edx],0 ; avoid lazy creates jz short Eil20
xor eax,eax ; assume success lock inc dword ptr CsLockCount[edx] ; ... CriticalSection->LockCount jnz short Eil30
; ; Set Curr thread as Owner of CS with recursion count of 1 ; and return SUCCESS ; Eil10: mov CsOwningThread[edx],ecx mov dword ptr CsRecursionCount[edx],1 Eil20: stdRET _VdmpEnterIcaLock
; ; If curr thread already owns CS, ; inc recusrion count and return SUCCESS ; Eil30: cmp CsOwningThread[edx],ecx jne short Eil42 inc dword ptr CsRecursionCount[edx] stdRET _VdmpEnterIcaLock
; ; Another Thread owns the CS so Wait on the lock semaphore, ; Eil40: mov edx, CriticalSection Eil42: xor eax,eax lea ecx, IcaLockTimeout stdCall _ObWaitForSingleObject <CsLockSemaphore[edx], eax, ecx>
mov ecx,PCR[PcTeb] mov ecx,TbClientId+4[ecx] ; NtCurrentTeb()->ClientId.UniqueThread mov edx,CriticalSection
or eax, eax jz short Eil10 ; Take Ownership of CS
; ; If !NT_SUCCESS(Status) return with error. else some other ; less severe error occurred. In that case if thread terminating ; fail. Note: we may wake for user apc's even tho we are non ; alertable, because the vdm hw int dispatching code, and PsThread ; termination code forces these to occur. ; test eax, 080000000h jnz short Eil20 ; exit with Status in eax
Eil50: stdCall _VdmpIsThreadTerminating <ecx> ; check for Term of self or eax, eax jnz short Eil20 ; exit with Status in eax
mov edx, CriticalSection mov eax, CsOwningThread[edx] stdCall _VdmpIsThreadTerminating <eax> ; check for Term of CSOwner or eax, eax jz short Eil40 ; retry jmp short Eil20 ; exit with Status in eax
stdENDP _VdmpEnterIcaLock
page , 132 subttl "VdmpLeaveIcaLock" ;++ ; ; NTSTATUS ; VdmpLeaveIcaLock( ; IN PRTL_CRITICAL_SECTION pIcaLock ; ) ; ; Routine Description: ; ; This function leaves a critical section. ; ; Touching the critical section may cause an exception to be raised which ; the caller must handle, since the critical section may be in UserMode ; memory. ; ; Arguments: ; ; CriticalSection - supplies a pointer to a critical section. ; ; Return Value: ; ; STATUS_SUCCESS ; STATUS_INVALID_OWNER ; or NTSTATUS code from NtReleaseSemaphore ; ;--
align 16 cPublicProc _VdmpLeaveIcaLock,1 cPublicFpo 1,0
mov edx,CriticalSection mov ecx,PCR[PcTeb] mov ecx,TbClientId+4[ecx] ; NtCurrentTeb()->ClientId.UniqueThread
mov eax,STATUS_INVALID_OWNER ; Verify Owner of CritSect cmp ecx,CsOwningThread[edx] jne short Lil10
xor eax,eax ; Assume STATUS_SUCCESS dec dword ptr CsRecursionCount[edx] jnz short Lil30 ; leaving recursion
mov CsOwningThread[edx],eax ; clear owning thread id lock dec dword ptr CsLockCount[edx] ; interlocked dec of LockCount jge short Lil20 ; Thread waiting on LockSemaphore ?
Lil10: stdRET _VdmpLeaveIcaLock
; ; release another thread waiting on the LockSemaphore ; and exit Lil20: stdCall _NtSetEvent, <CsLockSemaphore[edx], 0> stdRET _VdmpLeaveIcaLock
; ; leaving recursion, just dec lock count ; Lil30:
lock dec dword ptr CsLockCount[edx] ; interlocked dec of LockCount stdRET _VdmpLeaveIcaLock
_VdmpLeaveIcaLock endp
_PAGE ends
end
|