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

title "Fast Protected Mode services"
;++
;
; Copyright (c) 1989 Microsoft Corporation
;
; Module Name:
;
; fastpm.asm
;
; Abstract:
;
; This module implements a fast entry to and exit from protected mode
;
; Author:
;
; Dave Hastings (daveh) 26-Jul-91
;
;--
.386p
include ks386.inc
include callconv.inc
include bop.inc
include vint.inc
include vdmtib.inc
_TEXT SEGMENT PARA PUBLIC 'CODE'
ASSUME DS:NOTHING, ES:NOTHING, SS:FLAT, FS:NOTHING, GS:NOTHING
_TEXT ENDS
_DATA SEGMENT DWORD PUBLIC 'DATA'
public _NTVDMpLockPrefixTable
_NTVDMpLockPrefixTable label dword
dd offset FLAT:_ntvdmlock1
dd offset FLAT:_ntvdmlock2
dd 0
ClientPMStack df ?
ClientPMEntry df ?
_DATA ENDS
_TEXT SEGMENT
; Interrupt type definitions
CPU_YODA_INT equ 4
BIT_CPU_YODA_INT equ 0
CPU_HW_RESET equ 0
BIT_CPU_HW_RESET equ 1
CPU_TIMER_TICK equ 1
BIT_CPU_TIMER_TICK equ 2
CPU_HW_INT equ 3
BIT_CPU_HW_INT equ 3
assume DS:NOTHING
cPublicProc _VdmTrapcHandler, 0
;
; On entry, [ebx]->VdmContext
;
;
; zero higher 16bit of esp. (The Iretd in kernel trap handler puts higher 16bit
; of kernel esp back to our user mode esp even though the higher 16bit of
; TrapFrame.HardwareEsp is zeroed.
;
and esp, 0ffffh
;@@:
;
; Note, here we use app's stack to do the far return
;
push [ebx].VtVdmContext.CsSegCs
push [ebx].VtVdmContext.CsEip
mov ebx, [ebx].VtVdmContext.CsEbx
retf
stdENDP _VdmTrapcHandler
page ,132
subttl "FastEnterPm"
;++
;
; Routine Description:
;
; This routine is a faster way to enter 16 bit vdm protected mode.
; Instead of making a system call, we just save the 32 bit state
; into the VdmTib, restore the Vdm state from the VdmTib, and do
; a far return to the application.
;
; Arguments:
;
; ss:sp + 4 = pointer to VdmTib
;
; Returns:
;
; nothing.
;
assume DS:FLAT
cPublicProc _FastEnterPm,0
push ebp
mov ebp,esp ; set up stack frame
push ebx ; free up reg for pointer
mov ebx, KGDT_R3_TEB OR RPL_MASK
mov fs, ebx
mov ebx, fs:[PcTeb]
mov ebx, dword ptr [ebx].TeVdm
; translate the interrupt flag to the virtual interrupt flag
test [ebx].VtVdmContext.CsEFlags,dword ptr EFLAGS_INTERRUPT_MASK
jz fe10
_ntvdmlock1:
lock or dword ptr ds:FIXED_NTVDMSTATE_LINEAR,dword ptr VDM_VIRTUAL_INTERRUPTS
test dword ptr ds:FIXED_NTVDMSTATE_LINEAR,dword ptr VDM_INTERRUPT_PENDING
jz fe20
; set up event info for an interrupt acknowlege
mov word ptr [ebx].VtEventInfo.EiEvent,VdmIntAck
mov word ptr [ebx].VtEventInfo.EiInstructionSize,0
mov word ptr [ebx].VtEventInfo.EiIntAckInfo,0
pop ebx
mov esp,ebp
pop ebp
stdRET _FastEnterPm
fe10:
_ntvdmlock2:
lock and dword ptr ds:FIXED_NTVDMSTATE_LINEAR, NOT VDM_VIRTUAL_INTERRUPTS
fe20:
mov [ebx].VtMonitorContext.CsEax,eax
mov eax,[ebp - 4]
mov [ebx].VtMonitorContext.CsEbx,eax
mov [ebx].VtMonitorContext.CsEcx,ecx
mov [ebx].VtMonitorContext.CsEdx,edx
mov [ebx].VtMonitorContext.CsEsi,esi
mov [ebx].VtMonitorContext.CsEdi,edi
mov eax,[ebp]
mov [ebx].VtMonitorContext.CsEbp,eax
mov eax,ebp
add eax,8 ; pop ebp and ret addr
mov [ebx].VtMonitorContext.CsEsp,eax
mov eax,[ebp + 4]
mov [ebx].VtMonitorContext.CsEip,eax
mov eax,cs
mov [ebx].VtMonitorContext.CsSegCs,eax
mov eax,ss
mov [ebx].VtMonitorContext.CsSegSs,eax
mov eax,ds
mov [ebx].VtMonitorContext.CsSegDs,eax
mov eax,es
mov [ebx].VtMonitorContext.CsSegEs,eax
mov eax,fs
mov [ebx].VtMonitorContext.CsSegFs,eax
mov eax,gs
mov [ebx].VtMonitorContext.CsSegGs,eax
pushfd
pop eax
mov [ebx].VtMonitorContext.CsEflags,eax
test [ebx].VtVdmContext.CsEflags, EFLAGS_TF_MASK ; debugging?
jz fe_atomic ; no, return the robust way
;
; Beginning STACK-BASED return
;
; The following code transitions us back to client code in protect mode
; using the client's stack. This is not a good thing to do in general
; since this is not how things worked on win31. But it is necessary if
; we are setting the trap flag in the EFLAGS register in order to break
; on the correct instruction.
;
mov eax,[ebx].VtVdmContext.CsSegSs
mov es,eax
mov edi,[ebx].VtVdmContext.CsEsp ; es:edi -> stack
lar eax,eax
test eax,400000h ; big?
jnz fe30
movzx edi,di
fe30: mov eax,[ebx].VtVdmContext.CsEflags
sub edi,4
mov es:[edi],eax ; push Eflags
mov eax,[ebx].VtVdmContext.CsSegCs
sub edi,4
mov es:[edi],eax ; push cs
mov eax,[ebx].VtVdmContext.CsEip
sub edi,4
mov es:[edi],eax ; push ip
sub edi,4
mov eax,[ebx].VtVdmContext.CsEbp ; push ebp
mov es:[edi],eax
fe40: push es
push edi ; push ss:esp for lss esp
mov eax,esp ; save sp for pushad
; simulate pushad
push dword ptr [ebx].VtVdmContext.CsEax
push dword ptr [ebx].VtVdmContext.CsEcx
push dword ptr [ebx].VtVdmContext.CsEdx
push dword ptr [ebx].VtVdmContext.CsEbx
push eax
push ebp ; save pointer to stack frame
push dword ptr [ebx].VtVdmContext.CsEsi
push dword ptr [ebx].VtVdmContext.CsEdi
; push seg regs
push dword ptr [ebx].VtVdmContext.CsSegFs
push dword ptr [ebx].VtVdmContext.CsSegGs
push dword ptr [ebx].VtVdmContext.CsSegDs
push dword ptr [ebx].VtVdmContext.CsSegEs
; set up VDM seg regs
pop es
pop ds
pop gs ; pop es,fs,gs of invalid selectors are trapped in ntoskrnl,
pop fs ; and handled by setting to zero
; set up VDM general regs
popad
; set up vdm stack
lss esp,[ebp - 12]
; restore ebp
pop ebp
; return to VDM
iretd
;
; Beginning STACK-LESS return
;
; WARNING:
; The following code does the final dispatch to the Client code.
; It uses STATIC data to hold CS, EIP, SS, ESP. THAT MAKES THIS CODE
; NON-REENTRANT. For correct operation, the rest of this code in this
; routine must execute to completion before coming back through. All
; ntvdm support code must honor this arrangement.
;
; The reason this code has this restriction is to avoid using the
; client's stack. Originally, this routine built a stack frame on the
; client stack, and IRET'd to it. This breaks some DPMI applications,
; either at a point where they have a transient condition with an invalid
; stack pointer, or because they expect unused stack space to be left
; alone by the system.
;
fe_atomic:
mov eax,[ebx].VtVdmContext.CsSegCs
mov word ptr ClientPmEntry+4, ax
mov eax,[ebx].VtVdmContext.CsEip
mov dword ptr ClientPmEntry, eax
mov eax,[ebx].VtVdmContext.CsSegSs
mov word ptr ClientPmStack+4, ax
mov eax,[ebx].VtVdmContext.CsEsp ; es:edi -> stack
mov dword ptr ClientPmStack, eax
mov eax,esp ; save sp for pushad
; simulate pushad
push dword ptr [ebx].VtVdmContext.CsEax
push dword ptr [ebx].VtVdmContext.CsEcx
push dword ptr [ebx].VtVdmContext.CsEdx
push dword ptr [ebx].VtVdmContext.CsEbx
push eax
push dword ptr [ebx].VtVdmContext.CsEbp
push dword ptr [ebx].VtVdmContext.CsEsi
push dword ptr [ebx].VtVdmContext.CsEdi
; push seg regs
push dword ptr [ebx].VtVdmContext.CsSegFs
push dword ptr [ebx].VtVdmContext.CsSegGs
push dword ptr [ebx].VtVdmContext.CsSegDs
push dword ptr [ebx].VtVdmContext.CsSegEs
push dword ptr [ebx].VtVdmContext.CsEflags
popfd
; set up VDM seg regs
pop es
pop ds
pop gs ; pop fs,gs of invalid selectors are trapped in ntoskrnl,
pop fs ; and handled by setting to zero
; set up VDM general regs
popad
lss esp, cs:ClientPMStack
jmp fword ptr cs:ClientPMEntry
stdENDP _FastEnterPm
page ,132
subttl "GetFastBopEntry"
;++
;
; Routine Description:
;
; This routine supplies the address of the routine that segmented
; protected mode code should call to switch to flat mode.
;
; Arguments:
;
; esp + 4 = pointer to VdmTib->VdmContext
;
; Returns:
;
; nothing.
;
assume DS:FLAT
cPublicProc _GetFastBopEntryAddress,1
push ebp
mov ebp,esp
push ebx
push eax
mov ebx,[ebp + 8]
mov [ebx].CsSegEs,cs
mov eax,offset FLAT:_FastLeavePm
mov word ptr [ebx].CsEbx,ax
shr eax,16
mov word ptr [ebx].CsEdx,ax
pop eax
pop ebx
mov esp,ebp
pop ebp
stdRET _GetFastBopEntryAddress
stdENDP _GetFastBopEntryAddress
page ,132
subttl "FastLeavePm"
;++
;
; Routine Description:
;
; This routine switches from the VDM context to the monitor context.
;
; Arguments:
;
; none
;
; Returns:
;
; executing with monitor context
;
assume DS:Nothing,ES:Nothing,SS:Nothing
ALIGN 16
cPublicProc _FastLeavePm,0
push ebx
mov bx,ds
push bx ; so push and pop size same
mov bx,KGDT_R3_DATA OR RPL_MASK
mov ds,bx
assume ds:FLAT
push fs
mov ebx, KGDT_R3_TEB OR RPL_MASK
mov fs, bx
mov ebx, fs:[PcTeb]
mov ebx, dword ptr [ebx].TeVdm
pop fs
pushfd
mov dword ptr [ebx].VtVdmContext.CsEax,eax
pop eax
mov dword ptr [ebx].VtVdmContext.CsEFlags,eax
pop ax
mov word ptr [ebx].VtVdmContext.CsSegDs,ax
pop eax
mov dword ptr [ebx].VtVdmContext.CsEbx,eax
mov dword ptr [ebx].VtVdmContext.CsEcx,ecx
mov dword ptr [ebx].VtVdmContext.CsEdx,edx
mov dword ptr [ebx].VtVdmContext.CsEsi,esi
mov dword ptr [ebx].VtVdmContext.CsEdi,edi
mov dword ptr [ebx].VtVdmContext.CsEbp,ebp
mov word ptr [ebx].VtVdmContext.CsSegEs,es
mov word ptr [ebx].VtVdmContext.CsSegFs,fs
mov word ptr [ebx].VtVdmContext.CsSegGs,gs
pop eax
mov dword ptr [ebx].VtVdmContext.CsEip,eax
pop eax
mov word ptr [ebx].VtVdmContext.CsSegCs,ax
mov dword ptr [ebx].VtVdmContext.CsEsp,esp
mov word ptr [ebx].VtVdmContext.CsSegSs,ss
; switch Stacks
.errnz (CsEsp + 4 - CsSegSS)
lss esp, [ebx].VtMonitorContext.CsEsp
; Now running on Monitor stack
; set up event info
mov word ptr [ebx].VtEventInfo.EiEvent,VdmBop
mov dword ptr [ebx].VtEventInfo.EiInstructionSize,BOP_SIZE
mov ax,[ebx].VtVdmContext.CsSegCs
mov es,ax
; BUGBUG 16 or 32 bit !!!!!
mov di,[ebx].VtVdmContext.CsEip
mov al,byte ptr es:[di]
movzx eax,al
mov [ebx].VtEventInfo.EiBopNumber,eax
sub di,2
mov word ptr [ebx].VtVdmContext.CsEip,di ; set up bop bias
; set up for IRET
push dword ptr [ebx].VtMonitorContext.CsEFlags
push dword ptr [ebx].VtMonitorContext.CsSegCs
push dword ptr [ebx].VtMonitorContext.CsEip
; simulate pushad
mov eax,esp
push dword ptr [ebx].VtMonitorContext.CsEax
push dword ptr [ebx].VtMonitorContext.CsEcx
push dword ptr [ebx].VtMonitorContext.CsEdx
push dword ptr [ebx].VtMonitorContext.CsEbx
push eax
push dword ptr [ebx].VtMonitorContext.CsEbp
push dword ptr [ebx].VtMonitorContext.CsEsi
push dword ptr [ebx].VtMonitorContext.CsEdi
; push seg regs
push dword ptr [ebx].VtMonitorContext.CsSegFs
push dword ptr [ebx].VtMonitorContext.CsSegGs
push dword ptr [ebx].VtMonitorContext.CsSegDs
push dword ptr [ebx].VtMonitorContext.CsSegEs
test ds:FIXED_NTVDMSTATE_LINEAR,dword ptr VDM_VIRTUAL_INTERRUPTS
jz fl10
or [ebx].VtVdmContext.CsEFlags,dword ptr EFLAGS_INTERRUPT_MASK
jmp fl20
fl10: and dword ptr [ebx].VtVdmContext.CsEFlags, NOT EFLAGS_INTERRUPT_MASK
fl20:
; set up Monitor seg regs
pop es
pop ds
pop gs
pop fs
; set up Monitor general regs
popad
xor eax,eax ; indicate success
; clear the NT bit in EFLAGS and return with iret
pushfd
and dword ptr [esp], 0ffffbfffH
popfd
iretd
stdENDP _FastLeavePm
_TEXT ends
end