00001 ;++
00002 ;
00003 ;   
Copyright (c) 1989  Microsoft Corporation
00004 ;
00005 ;   Module 
Name:
00006 ;
00007 ;       kimacro.inc
00008 ;
00009 ;   Abstract:
00010 ;
00011 ;       This module contains 
the macros used by kernel assembler code.
00012 ;       It includes 
macros to manipulate interrupts, support system
00013 ;       entry and 
exit for syscalls, faults, and interrupts, and
00014 ;       manipulate floating point state.
00015 ;
00016 ;   Author:
00017 ;
00018 ;       Shie-Lin (shielint) 24-Jan-1990
00019 ;
00020 ;   Revision 
History:
00021 ;
00022 ;       BryanWi 17-Aug-90
00023 ;           Replace GENERATE_MACHINE... and 
RESTORE... with ENTER_...
00024 ;           and EXIT_ALL 
macros.
00025 ;
00026 ;--
00027 
00028 ;++
00029 ;
00030 ;   These constants are used by 
the fpo directives in 
this file.
00031 ;   This directive causes 
the assembler to output a .debug$f segment
00032 ;   in 
the obj 
file.  The segment will contain 1 fpo record 
for each
00033 ;   directive present during assembly.
00034 ;
00035 ;   Although 
the assembler will accept all valid values, 
the value of 7
00036 ;   in 
the FPO_REGS field indicates to 
the debugger that a trap frame 
is
00037 ;   generated by 
the function.  The value of 7 can be used because 
the
00038 ;   C/C++ compiler puts a maximum value of 3 in 
the field.
00039 ;
00040 FPO_LOCALS      equ     0         ; 32 bits, size of locals in dwords
00041 FPO_PARAMS      equ     0         ; 32 bits, size of parameters in dwords
00042 FPO_PROLOG      equ     0         ; 12 bits, 0-4095, # of bytes in prolog
00043 FPO_REGS        equ     0         ; 3 bits, 0-7, # regs saved in prolog
00044 FPO_USE_EBP     equ     0         ; 1 bit, 0-1, 
is ebp used?
00045 FPO_TRAPFRAME   equ     1         ; 2 bits, 0=fpo, 1=trap frame, 2=tss
00046 ;
00047 ;--
00048 
00049 
00050 ;++
00051 ;
00052 ;   POLL_DEBUGGER
00053 ;
00054 ;   Macro 
Description:
00055 ;
00056 ;       Call 
the debugger so 
it can check 
for control-
c.  If 
it finds
00057 ;       
it, 
it will report our iret address as address of 
break-in.
00058 ;
00059 ;       N.B. This macro should be used when all 
the caller's registers
00060 ;            have been restored. (Otherwise, 
the kernel debugger 
register
00061 ;            dump will not have correct state.)  The 
only exception 
is
00062 ;            fs.  This 
is because Kd may need to access PCR or PRCB.
00063 ;
00064 ;   Arguments:
00065 ;
00066 ;       There MUST be an iret frame on 
the stack when 
this macro
00067 ;       
is invoked.
00068 ;
00069 ;   Exit:
00070 ;
00071 ;       Debugger will iret 
for us, so we don'
t usually 
return from
00072 ;       
this macro, but remember that 
it generates nothing 
for non-DEVL
00073 ;       kernels.
00074 ;--
00075 
00076 POLL_DEBUGGER   macro
00077 local   a, b, c_
00078 
00079 
if  DEVL
00080         EXTRNP   _DbgBreakPointWithStatus,1
00081         stdCall _KdPollBreakIn
00082         or      al,al
00083         jz      
short c_
00084         stdCall _DbgBreakPointWithStatus,<
DBG_STATUS_CONTROL_C>
00085 c_:
00086 endif   ; DEVL
00087 endm
00088 
00089 ;++
00090 ;
00091 ;   ASSERT_FS
00092 ;
00093 ;   Try to 
catch funky condition wherein we get 
FS=r3 value 
while
00094 ;   running in kernel mode.
00095 ;
00096 ;--
00097 
00098 ASSERT_FS   macro
00099 local   a,b
00100 
00101 
if DBG
00102         EXTRNP   _KeBugCheck,1
00103 
00104         mov     bx,fs
00105         cmp     bx,KGDT_R0_PCR
00106         jnz     
short a
00107 
00108         cmp     dword ptr fs:[0], 0
00109         jne     
short b
00110 
00111 a:
00112         stdCall   _KeBugCheck,<-1>
00113 align 4
00114 b:
00115 endif
00116 endm
00117 
00118 
00119 
00120 ;++
00121 ;
00122 ;
00123 ;   
Copy data from various places into base of TrapFrame, net effect
00124 ;   
is to allow dbg KB command to trace accross trap frame, and to
00125 ;   allow user to find arguments to system calls.
00126 ;
00127 ;   USE ebx and edi.
00128 ;--
00129 
00130 SET_DEBUG_DATA  macro
00131 
00132 ife FPO
00133 
00134 ;
00135 ; This macro 
is used by ENTER_SYSTEM_CALL, ENTER_TRAP and ENTER_INTERRUPT
00136 ; and 
is used at 
the end of above 
macros.  It 
is safe to destroy ebx, edi.
00137 ;
00138 
00139         mov     ebx,[ebp]+TsEbp
00140         mov     edi,[ebp]+TsEip
00141         mov     [ebp]+TsDbgArgPointer,edx
00142         mov     [ebp]+TsDbgArgMark,0BADB0D00h
00143         mov     [ebp]+TsDbgEbp,ebx
00144         mov     [ebp]+TsDbgEip,edi
00145 endif
00146 
00147 endm
00148 
00149 
00150 ;++
00151 ;
00152 ;   ENTER_DR_ASSIST     EnterLabel, ExitLabel, NoAbiosAssist, NoV86Assist
00153 ;
00154 ;   Macro 
Description:
00155 ;
00156 ;       Jumped to by ENTER_ 
macros to deal with DR 
register work,
00157 ;       abios work and v86 work.  The 
main purpose of 
this macro 
is
00158 ;       that interrupt/trap/systemCall EnterMacros can jump here to
00159 ;       deal with some special cases such that most of 
the times 
the
00160 ;       
main ENTER_ execution flow can proceed without being branched.
00161 ;
00162 ;       If (previousmode == usermode) {
00163 ;           save DR* in trapframe
00164 ;           load DR* from Prcb
00165 ;       }
00166 ;
00167 ;   Arguments:
00168 ;       EnterLabel - label to emit
00169 ;       ExitLabel - label to branch to when done
00170 ;
00171 ;   Entry-conditions:
00172 ;     Dr work:
00173 ;       DebugActive == 
TRUE
00174 ;       (esi)->Thread object
00175 ;       (esp)->base of trap frame
00176 ;       (ebp)->base of trap frame
00177 ;
00178 ;     Abios work:
00179 ;     v86 work:
00180 ;
00181 ;   Exit-conditions:
00182 ;     Dr work:
00183 ;       Interrupts match input state (
this routine doesn't change IEF)
00184 ;       (esp)->base of trap frame
00185 ;       (ebp)->base of trap frame
00186 ;       Preserves entry eax, edx
00187 ;     Abios work:
00188 ;     v86 work:
00189 ;
00190 ;--
00191 
00192 ENTER_DR_ASSIST macro   EnterLabel, ExitLabel, NoAbiosAssist, NoV86Assist, V86R
00193         local   a,b
00194 
00195         
public  Dr_&EnterLabel
00196 align 4
00197 Dr_&EnterLabel:
00198 
00199 ;
00200 ; 
Test if we came from user-mode.  If not, 
do nothing.
00201 ;
00202 
00203         test    dword ptr [ebp]+TsEFlags,EFLAGS_V86_MASK
00204         jnz     
short a
00205 
00206         test    dword ptr [ebp]+TsSegCs,MODE_MASK
00207         jz      Dr_&ExitLabel          ; called from kmode, go 
continue
00208 
00209 
00210 ;
00211 ; Save user-mode Dr* regs in TrapFrame
00212 ;
00213 ; We are safe to destroy ebx, ecx, edi because in ENTER_INTERRUPT and
00214 ; ENTER_TRAP these registers are saved already.  In ENTER_SYSTEMCALL
00215 ; ebx, edi 
is saved and ecx 
is don'
t-care.
00216 ;
00217 
00218 a:      mov     ebx,dr0
00219         mov     ecx,dr1
00220         mov     edi,dr2
00221         mov     [ebp]+TsDr0,ebx
00222         mov     [ebp]+TsDr1,ecx
00223         mov     [ebp]+TsDr2,edi
00224         mov     ebx,dr3
00225         mov     ecx,dr6
00226         mov     edi,dr7
00227         mov     [ebp]+TsDr3,ebx
00228         mov     [ebp]+TsDr6,ecx
00229         mov     ebx,0
00230         mov     [ebp]+TsDr7,edi
00231 
00232 ;
00233 ; Make Dr7 safe before loading junk from save area
00234 ;
00235         mov     dr7,ebx
00236 
00237 ;
00238 ; Load KernelDr* into processor
00239 ;
00240 
00241         mov     edi,dword ptr fs:[
PcPrcb]
00242         mov     ebx,[edi].PbProcessorState.PsSpecialRegisters.SrKernelDr0
00243         mov     ecx,[edi].PbProcessorState.PsSpecialRegisters.SrKernelDr1
00244         mov     dr0,ebx
00245         mov     dr1,ecx
00246         mov     ebx,[edi].PbProcessorState.PsSpecialRegisters.SrKernelDr2
00247         mov     ecx,[edi].PbProcessorState.PsSpecialRegisters.SrKernelDr3
00248         mov     dr2,ebx
00249         mov     dr3,ecx
00250         mov     ebx,[edi].PbProcessorState.PsSpecialRegisters.SrKernelDr6
00251         mov     ecx,[edi].PbProcessorState.PsSpecialRegisters.SrKernelDr7
00252         mov     dr6,ebx
00253         mov     dr7,ecx
00254 
00255 ifnb <V86R>
00256         test    dword ptr [ebp]+TsEFlags,EFLAGS_V86_MASK
00257         jz      
short b
00258         jmp     Dr_&V86R
00259 endif
00260 b:
00261         jmp     Dr_&ExitLabel
00262 
00263 
00264 ifb <NoAbiosAssist>
00265 
00266         
public  Abios_&EnterLabel
00267 align 4
00268 Abios_&EnterLabel:
00269 
00270 ;
00271 ;   INTERRUPT_STACK16_TO_STACK32
00272 ;
00273 ;       This macro remaps current 32bit stack to 16bit stack at interrupt
00274 ;       time.
00275 ;
00276 ;   Arguments:
00277 ;
00278 ;       (esp)->trap frame.
00279 ;       (eax)->Entry Esp.
00280 ;
00281 
00282         mov     eax, [esp].TsErrCode    ; (eax) = Entry Esp
00283         mov     ecx, KGDT_R0_DATA
00284         mov     edx, esp
00285         shl     eax, 16
00286         add     edx, fs:[PcstackLimit]
00287         mov     [esp].TsErrCode, eax
00288         mov     ss, cx
00289         mov     esp, edx                ; Interrupts are off
00290         mov     ebp, edx
00291         jmp     Abios_&ExitLabel
00292 
00293 endif   ; NoAbiosAssist
00294 
00295 ifb <NoV86Assist>
00296 
00297         
public  V86_&EnterLabel
00298 align 4
00299 V86_&EnterLabel:
00300 
00301 ;
00302 ;   Move 
the V86 segment registers to 
the correct place in 
the frame
00303 ;
00304         mov     eax,dword ptr [ebp].TsV86Fs
00305         mov     ebx,dword ptr [ebp].TsV86Gs
00306         mov     ecx,dword ptr [ebp].TsV86Es
00307         mov     edx,dword ptr [ebp].TsV86Ds
00308         mov     [ebp].TsSegFs,ax
00309         mov     [ebp].TsSegGs,bx
00310         mov     [ebp].TsSegEs,cx
00311         mov     [ebp].TsSegDs,dx
00312         jmp     V86_&ExitLabel
00313 
00314 endif   ; NoV86Assist
00315 
00316         endm
00317 
00318 ;++
00319 ;
00320 ;   ENTER_SYSCALL       AssistLabel, TagetLabel, NoFSLoad
00321 ;
00322 ;   Macro 
Description:
00323 ;
00324 ;       Build 
the frame and set registers needed by a system call.
00325 ;
00326 ;       Save:
00327 ;           Errorpad,
00328 ;           Non-
volatile regs,
00329 ;           
FS,
00330 ;           ExceptionList,
00331 ;           PreviousMode
00332 ;
00333 ;       Don'
t Save:
00334 ;           
Volatile regs
00335 ;           Seg regs
00336 ;           Floating point state
00337 ;
00338 ;       Set:
00339 ;           
FS,
00340 ;           ExceptionList,
00341 ;           PreviousMode,
00342 ;           Direction
00343 ;
00344 ;   Arguments:
00345 ;       AssistLabel - label ENTER_ASSIST macro 
is at
00346 ;       TargetLabel - label to emit 
for ENTER_ASSIST to jump to
00347 ;       NoFSLoad    - Don'
t set 
FS(it is already set to KGDT_R0_PCR at entry).
00348 ;
00349 ;   Exit-conditions:
00350 ;       Interrupts match input state (
this routine doesn't change IEF)
00351 ;       (esp)->base of trap frame
00352 ;       (ebp)->base of trap frame
00353 ;       Preserves entry eax, edx
00354 ;
00355 ;   Note:
00356 ;       The DS: reference to PreviousMode 
is *required* 
for correct
00357 ;       functioning of lazy selector loads.  If you remove 
this use
00358 ;       of DS:, put a DS: override on something.
00359 ;
00360 ;--
00361 
00362 ENTER_SYSCALL macro     AssistLabel, TargetLabel, NoFSLoad
00363 
00364 
00365 .FPO ( FPO_LOCALS, FPO_PARAMS, FPO_PROLOG, FPO_REGS, FPO_USE_EBP, FPO_TRAPFRAME )
00366 
00367 ifdef KERNELONLY
00368 
00369 ;
00370 ; Construct trap frame.
00371 ;
00372 ; N.B. The initial part of the trap frame is constructed by pushing values
00373 ;      on the stack. If the format of the trap frame is changed, then the
00374 ;      following code must alos be changed.
00375 ;
00376 
00377         push    0                       ; put pad dword for error on stack
00378         push    ebp                     ; save the non-volatile registers
00379         push    ebx                     ;
00380         push    esi                     ;
00381         push    edi                     ;
00382 ifb <NoFSLoad>
00383         push    fs                      ; save and set FS to PCR.
00384         mov     ebx,KGDT_R0_PCR         ; set PCR segment number
00385         mov     fs,bx                   ;
00386 else 
00387         ; FS already contains KGDT_R0_PCR(entry via PentiumPro fast system call)
00388         push    KGDT_R3_TEB OR RPL_MASK
00389 endif  ; NoFSLoad
00390 
00391 ;
00392 ; Save the old exception list in trap frame and initialize a new empty
00393 ; exception list.
00394 ;
00395 
00396         push    PCR[PcExceptionList]    ; save old exception list
00397         mov     PCR[PcExceptionList],EXCEPTION_CHAIN_END ; set new empty list
00398 
00399 ;
00400 ; Save the old previous mode in trap frame, allocate remainder of trap frame,
00401 ; and set the new previous mode.
00402 ;
00403 
00404         mov     esi,PCR[PcPrcbData+PbCurrentThread] ; get current thread address
00405         push    [esi]+ThPreviousMode    ; save old previous mode
00406         sub     esp,TsPreviousPreviousMode ; allocate remainder of trap frame
00407         mov     ebx,[esp+TsSegCS]       ; compute new previous mode
00408         and     ebx,MODE_MASK           ;
00409         mov     [esi]+ThPreviousMode,bl ; set new previous mode
00410 
00411 ;
00412 ; Save the old trap frame address and set the new trap frame address.
00413 ;
00414 
00415         mov     ebp,esp                 ; set trap frame address
00416         mov     ebx,[esi].ThTrapFrame   ; save current trap frame address
00417         mov     [ebp].TsEdx,ebx         ;
00418         mov     [esi].ThTrapFrame,ebp   ; set new trap frame address
00419         cld                             ; make sure direction is forward
00420 
00421         SET_DEBUG_DATA                  ; Note this destroys edi
00422 
00423         test    byte ptr [esi]+ThDebugActive,-1 ; test if debugging active
00424         jnz     Dr_&AssistLabel         ; if nz, debugging is active on thread
00425 
00426 Dr_&TargetLabel:                        ;
00427         sti                             ; enable interrupts
00428 
00429 else
00430         %out    ENTER_SYSCAL outside of kernel
00431         .err
00432 endif
00433         endm
00434 
00435 ;++
00436 ;
00437 ;   ENTER_INTERRUPT     AssistLabel, TargetLabel
00438 ;
00439 ;   Macro Description:
00440 ;
00441 ;       Build the frame and set registers needed by an interrupt.
00442 ;
00443 ;       Save:
00444 ;           Errorpad,
00445 ;           Non-volatile regs,
00446 ;           FS,
00447 ;           ExceptionList,
00448 ;           PreviousMode
00449 ;           Volatile regs
00450 ;           Seg regs from V86 mode
00451 ;           DS, ES, GS
00452 ;
00453 ;       Don't Save:
00454 ;           Floating point state
00455 ;
00456 ;       Set:
00457 ;           FS,
00458 ;           ExceptionList,
00459 ;           Direction,
00460 ;           DS, ES
00461 ;
00462 ;       Don't Set:
00463 ;           PreviousMode
00464 ;
00465 ;   Arguments:
00466 ;       AssistLabel - label ENTER_ASSIST macro is at
00467 ;       TargetLabel - label to emit for ENTER_ASSIST to jump to
00468 ;
00469 ;   Exit-conditions:
00470 ;       Interrupts match input state (this routine doesn't change IEF)
00471 ;       (esp)->base of trap frame
00472 ;       (ebp)->base of trap frame
00473 ;       Preserves entry eax, ecx, edx
00474 ;
00475 ;--
00476 
00477 ENTER_INTERRUPT macro   AssistLabel, TargetLabel, PassParm
00478         local b
00479 
00480 .FPO ( FPO_LOCALS+2, FPO_PARAMS, FPO_PROLOG, FPO_REGS, FPO_USE_EBP, FPO_TRAPFRAME )
00481 
00482 ;
00483 ;   Fill in parts of frame we care about
00484 ;
00485 
00486 ifb <PassParm>
00487         push    esp                 ; Use Error code field to save 16bit esp
00488 endif
00489         push    ebp                 ; Save the non-volatile registers
00490         push    ebx
00491         push    esi
00492         push    edi
00493 
00494         sub     esp, TsEdi
00495         mov     ebp,esp
00496 
00497         mov     [esp]+TsEax, eax    ; Save volatile registers
00498         mov     [esp]+TsEcx, ecx
00499         mov     [esp]+TsEdx, edx
00500 if DBG
00501         mov     dword ptr [esp]+TsPreviousPreviousMode, -1 ; ThPreviousMode not pushed on interrupt
00502 endif
00503 
00504         test    dword ptr [esp].TsEflags,EFLAGS_V86_MASK
00505         jnz     V86_&AssistLabel
00506 
00507         cmp     word ptr [esp]+TsSegCs, KGDT_R0_CODE
00508         jz      
short @f
00509 
00510         mov     [esp]+TsSegFs, fs  ; Save and set FS to PCR.
00511         mov     [esp]+TsSegDs, ds
00512         mov     [esp]+TsSegEs, es
00513         mov     [esp]+TsSegGs, gs
00514 
00515 V86_&TargetLabel:
00516         mov     ebx,KGDT_R0_PCR
00517         mov     eax,KGDT_R3_DATA OR RPL_MASK
00518         mov     fs, bx
00519         mov     ds, ax
00520         mov     es, ax
00521 @@:
00522         mov     ebx, fs:[PcExceptionList] ;Save, set ExceptionList
00523         mov     fs:[PcExceptionList],EXCEPTION_CHAIN_END
00524         mov     [esp]+TsExceptionList, ebx
00525 
00526 ifnb <PassParm>
00527         lea     eax, [esp].TsErrCode
00528         lea     ecx, [esp].TsEip    ; Move eax to EIP field
00529         mov     ebx, ss:[eax]       ; (ebx) = parameter to pass
00530         mov     ss:[eax], ecx       ; save 16bit esp
00531 endif
00532 
00533 ;
00534 ; Remap ABIOS 16 bit stack to 32 bit stack, if necessary.
00535 ;
00536 
00537         cmp     esp, 10000h
00538         jb      Abios_&AssistLabel
00539 
00540         mov     dword ptr [esp].TsErrCode, 0 ; Indicate no remapping.
00541 Abios_&TargetLabel:
00542 
00543 ;
00544 ; end of Abios stack checking
00545 ;
00546 
00547         cld
00548 
00549 ifnb <PassParm>
00550         push    ebx                 ; push parameter as argument
00551 endif
00552 
00553 
00554         SET_DEBUG_DATA
00555 
00556         test    byte ptr PCR[PcDebugActive], -1
00557         jnz     Dr_&AssistLabel
00558 
00559 Dr_&TargetLabel:
00560 
00561         endm
00562 
00563 ;++
00564 ;
00565 ;   ENTER_INTERRUPT_FORCE_STATE   AssistLabel, TargetLabel
00566 ;
00567 ;   Macro Description:
00568 ;
00569 ;       Build the frame and set registers needed by an interrupt.
00570 ;
00571 ;       This macro is the same as ENTER_INTERRUPT except that it forces the
00572 ;       needed state and does not save previous state.  
00573 ;
00574 ;       This macro is currently only used by HalpApicRebootService which does not 
00575 ;       return;
00576 ;
00577 ;       Save:
00578 ;           Errorpad,
00579 ;           Non-volatile regs,
00580 ;           ExceptionList,
00581 ;           PreviousMode
00582 ;           Volatile regs
00583 ;           Seg regs from V86 mode
00584 ;
00585 ;       Don't Save:
00586 ;           FS,
00587 ;           DS, ES, GS
00588 ;           Floating point state
00589 ;
00590 ;       Set:
00591 ;           FS,
00592 ;           ExceptionList,
00593 ;           Direction,
00594 ;           DS, ES
00595 ;
00596 ;       Don't Set:
00597 ;           PreviousMode
00598 ;
00599 ;   Arguments:
00600 ;       AssistLabel - label ENTER_ASSIST macro is at
00601 ;       TargetLabel - label to emit for ENTER_ASSIST to jump to
00602 ;
00603 ;   Exit-conditions:
00604 ;       Interrupts match input state (this routine doesn't change IEF)
00605 ;       (esp)->base of trap frame
00606 ;       (ebp)->base of trap frame
00607 ;       Preserves entry eax, ecx, edx
00608 ;
00609 ;--
00610 
00611 ENTER_INTERRUPT_FORCE_STATE macro   AssistLabel, TargetLabel, PassParm
00612         local b
00613 
00614 .FPO ( FPO_LOCALS+2, FPO_PARAMS, FPO_PROLOG, FPO_REGS, FPO_USE_EBP, FPO_TRAPFRAME )
00615 
00616 ;
00617 ;   Fill in parts of frame we care about
00618 ;
00619 
00620 ifb <PassParm>
00621         push    esp                 ; Use Error code field to save 16bit esp
00622 endif
00623         push    ebp                 ; Save the non-volatile registers
00624         push    ebx
00625         push    esi
00626         push    edi
00627 
00628         sub     esp, TsEdi
00629         mov     ebp,esp
00630 
00631         mov     [esp]+TsEax, eax    ; Save volatile registers
00632         mov     [esp]+TsEcx, ecx
00633         mov     [esp]+TsEdx, edx
00634 if DBG
00635         mov     dword ptr [esp]+TsPreviousPreviousMode, -1 ; ThPreviousMode not pushed on interrupt
00636 endif
00637 
00638         test    dword ptr [esp].TsEflags,EFLAGS_V86_MASK
00639         jnz     V86_&AssistLabel
00640 
00641 V86_&TargetLabel:
00642         mov     ebx,KGDT_R0_PCR
00643         mov     eax,KGDT_R3_DATA OR RPL_MASK
00644         mov     fs, bx
00645         mov     ds, ax
00646         mov     es, ax
00647 @@:
00648         mov     ebx, fs:[PcExceptionList] ;Save, set ExceptionList
00649         mov     fs:[PcExceptionList],EXCEPTION_CHAIN_END
00650         mov     [esp]+TsExceptionList, ebx
00651 
00652 ifnb <PassParm>
00653         lea     eax, [esp].TsErrCode
00654         lea     ecx, [esp].TsEip    ; Move eax to EIP field
00655         mov     ebx, ss:[eax]       ; (ebx) = parameter to pass
00656         mov     ss:[eax], ecx       ; save 16bit esp
00657 endif
00658 
00659 ;
00660 ; Remap ABIOS 16 bit stack to 32 bit stack, if necessary.
00661 ;
00662 
00663         cmp     esp, 10000h
00664         jb      Abios_&AssistLabel
00665 
00666         mov     dword ptr [esp].TsErrCode, 0 ; Indicate no remapping.
00667 Abios_&TargetLabel:
00668 
00669 ;
00670 ; end of Abios stack checking
00671 ;
00672 
00673         cld
00674 
00675 ifnb <PassParm>
00676         push    ebx                 ; push parameter as argument
00677 endif
00678 
00679 
00680         SET_DEBUG_DATA
00681 
00682         test    byte ptr PCR[PcDebugActive], -1
00683         jnz     Dr_&AssistLabel
00684 
00685 Dr_&TargetLabel:
00686 
00687         endm
00688 
00689 ;++
00690 ;
00691 ;   ENTER_TRAP      AssistLabel, TargetLabel
00692 ;
00693 ;   Macro Description:
00694 ;
00695 ;       Build the frame and set registers needed by a trap or exception.
00696 ;
00697 ;       Save:
00698 ;           Non-volatile regs,
00699 ;           FS,
00700 ;           ExceptionList,
00701 ;           PreviousMode,
00702 ;           Volatile regs
00703 ;           Seg Regs from V86 mode
00704 ;           DS, ES, GS
00705 ;
00706 ;       Don't Save:
00707 ;           Floating point state
00708 ;
00709 ;       Set:
00710 ;           FS,
00711 ;           Direction,
00712 ;           DS, ES
00713 ;
00714 ;       Don't Set:
00715 ;           PreviousMode,
00716 ;           ExceptionList
00717 ;
00718 ;   Arguments:
00719 ;       AssistLabel - label ENTER_ASSIST macro is at
00720 ;       TargetLabel - label to emit for ENTER_ASSIST to jump to
00721 ;
00722 ;   Exit-conditions:
00723 ;       Interrupts match input state (this routine doesn't change IEF)
00724 ;       (esp)->base of trap frame
00725 ;       (ebp)->base of trap frame
00726 ;       Preserves entry eax
00727 ;
00728 ;--
00729 
00730 ENTER_TRAP macro    AssistLabel, TargetLabel
00731         local b
00732 
00733 .FPO ( FPO_LOCALS, FPO_PARAMS, FPO_PROLOG, FPO_REGS, FPO_USE_EBP, FPO_TRAPFRAME )
00734 
00735 ;
00736 ;   Fill in parts of frame we care about
00737 ;
00738 
00739 if DBG
00740 ifndef  _Ki16BitStackException
00741     EXTRNP   _Ki16BitStackException
00742 endif
00743 endif ; DBG
00744 
00745         mov     word ptr [esp+2], 0 ; Clear upper word of ErrorCode
00746 
00747         push    ebp                 ; Save the non-volatile registers
00748         push    ebx
00749         push    esi
00750         push    edi
00751 
00752         push    fs                  ; Save and set FS to PCR.
00753         mov     ebx,KGDT_R0_PCR
00754         mov     fs,bx
00755         mov     ebx, fs:[PcExceptionList] ;Save ExceptionList
00756         push    ebx
00757 if DBG
00758         push    -1                  ; Don't need to save ThPreviousMode from trap
00759 else
00760         sub     esp, 4              ; pad dword
00761 endif
00762         push    eax                 ; Save the volatile registers
00763         push    ecx
00764         push    edx
00765 
00766         push    ds                  ; Save segments
00767         push    es
00768         push    gs
00769 
00770 ;
00771 ;   Skip allocate reset of trap frame and Set up DS/ES, they may be trash
00772 ;
00773 
00774         mov     ax,KGDT_R3_DATA OR RPL_MASK
00775         sub     esp,TsSegGs
00776         mov     ds,ax
00777         mov     es,ax
00778 
00779 if DBG
00780 ;
00781 ; The code here check if the exception occurred in ring 0
00782 ; ABIOS code. If yes, this is a fatal condition.  We will
00783 ; put out message and bugcheck.
00784 ;
00785 
00786         cmp     esp, 10000h             ; Is the trap in abios?
00787         jb      _Ki16BitStackException       ; if b, yes, switch stack and bugcheck.
00788 
00789 endif ; DBG
00790 
00791         mov     ebp,esp
00792         test    dword ptr [esp].TsEflags,EFLAGS_V86_MASK
00793         jnz     V86_&AssistLabel
00794 
00795 V86_&TargetLabel:
00796 
00797         cld
00798         SET_DEBUG_DATA
00799 
00800         test    byte ptr PCR[PcDebugActive], -1
00801         jnz     Dr_&AssistLabel
00802 
00803 Dr_&TargetLabel:
00804 
00805         endm
00806 ;++
00807 ;
00808 ;   EXIT_ALL    NoRestoreSegs, NoRestoreVolatiles, NoPreviousMode
00809 ;
00810 ;   Macro Description:
00811 ;
00812 ;       Load a syscall frame back into the machine.
00813 ;
00814 ;       Restore:
00815 ;           Volatile regs, IF NoRestoreVolatiles blank
00816 ;           NoPreviousMode,
00817 ;           ExceptionList,
00818 ;           FS,
00819 ;           Non-volatile regs
00820 ;
00821 ;       If the frame is a kernel mode frame, AND esp has been edited,
00822 ;       then TsSegCs will have a special value.  Test for that value
00823 ;       and execute special code for that case.
00824 ;
00825 ;       N.B. This macro generates an IRET!  (i.e. It exits!)
00826 ;
00827 ;   Arguments:
00828 ;
00829 ;       NoRestoreSegs - non-blank if DS, ES, GS are NOT to be restored
00830 ;
00831 ;       NoRestoreVolatiles - non-blank if Volatile regs are NOT to be restored
00832 ;
00833 ;       NoPreviousMode - if nb pop ThPreviousMode
00834 ;
00835 ;   Entry-conditions:
00836 ;
00837 ;       (esp)->base of trap frame
00838 ;       (ebp)->Base of trap frame
00839 ;
00840 ;   Exit-conditions:
00841 ;
00842 ;       Does not exit, returns.
00843 ;       Preserves eax, ecx, edx, IFF NoRestoreVolatiles is set
00844 ;
00845 ;--
00846 
00847 ?adjesp = 0
00848 ?RestoreAll = 1
00849 
00850 EXIT_ALL macro  NoRestoreSegs, NoRestoreVolatiles, NoPreviousMode
00851 local   a, b, f, x
00852 local   Abios_ExitHelp, Abios_ExitHelp_Target1, Abios_ExitHelp_Target2
00853 local   Dr_ExitHelp, Dr_ExitHelp_Target, V86_ExitHelp, V86_ExitHelp_Target
00854 local   Db_NotATrapFrame, Db_A, Db_NotValidEntry, NonFlatPm_Target
00855 
00856 ;
00857 ; Sanity check some values and setup globals for macro
00858 ;
00859 
00860 ?adjesp = TsSegGs
00861 ?RestoreAll = 1
00862 
00863 ifnb <NoRestoreSegs>
00864     ?RestoreAll = 0
00865     ?adjesp = ?adjesp + 12
00866 endif
00867 
00868 ifnb <NoRestoreVolatiles>
00869     if ?RestoreAll eq 1
00870         %out "EXIT_ALL NoRestoreVolatiles requires NoRestoreSegs"
00871         .err
00872     endif
00873     ?adjesp = ?adjesp + 12
00874 endif
00875 
00876 ifb <NoPreviousMode>
00877 ifndef KERNELONLY
00878         %out    EXIT_ALL can not restore previousmode outside kernel
00879         .err
00880 endif
00881 endif
00882 
00883 ; All callers are responsible for getting here with interrupts disabled.
00884 
00885 if DBG
00886         pushfd
00887         pop     edx
00888 
00889         test    edx, EFLAGS_INTERRUPT_MASK
00890         jnz     Db_NotValidEntry
00891 
00892         cmp     esp, ebp                    ; make sure esp = ebp
00893         jne     Db_NotValidEntry
00894 
00895 ; Make sure BADB0D00 sig is present.  If not this isn't a trap frame!
00896 Db_A:   sub     [esp]+TsDbgArgMark,0BADB0D00h
00897         jne     Db_NotATrapFrame
00898 endif
00899 
00900         ASSERT_FS
00901 
00902         mov     edx, [esp]+TsExceptionList
00903 if DBG
00904         or      edx, edx
00905         jnz     
short @f
00906     
int 3
00907 @@:
00908 endif
00909         mov     ebx, fs:[PcDebugActive]     ; (ebx) = DebugActive flag
00910         mov     fs:[PcExceptionList], edx   ; Restore ExceptionList
00911 
00912 ifb <NoPreviousMode>
00913         mov     ecx, [esp]+TsPreviousPreviousMode ; Restore PreviousMode
00914 if DBG
00915         cmp     ecx, -1     ; temporary debugging code
00916         jne     @f          ; to make sure no one tries to pop ThPreviousMode
00917     
int 3                   ; when it wasn't saved
00918 @@:
00919 endif
00920         mov     esi,fs:[PcPrcbData+PbCurrentThread]
00921         mov     [esi]+ThPreviousMode,cl
00922 else
00923 if DBG
00924         mov     ecx, [esp]+TsPreviousPreviousMode
00925         cmp     ecx, -1     ; temporary debugging code
00926         je     @f           ; to make sure no one pushed ThPreviousMode and
00927     
int 3                   ; is now exiting without restoreing it
00928 @@:
00929 endif
00930 endif
00931 
00932         test    ebx, 0fh
00933         jnz     Dr_ExitHelp
00934 
00935 Dr_ExitHelp_Target:
00936 
00937         test    dword ptr [esp].TsEflags,EFLAGS_V86_MASK
00938         jnz     V86_ExitHelp
00939 
00940         test    word ptr [esp]+TsSegCs,FRAME_EDITED
00941         jz      b                           ; Edited frame pop out.
00942 
00943 
00944 if ?RestoreAll eq 0
00945 .errnz MODE_MASK-1
00946         cmp     word ptr [esp]+TsSegCs,KGDT_R3_CODE OR RPL_MASK ; set/clear ZF
00947         bt      word ptr [esp]+TsSegCs,0    ; test MODE_MASK      set/clear CF
00948         cmc                                 ;       (CF=1 and ZF=0)
00949         ja      f                           ; jmp if CF=0 and ZF=0
00950 endif
00951 ifb <NoRestoreVolatiles>
00952 ifb <NoRestoreSegs>                         ; must restore eax before any
00953         mov     eax, [esp].TsEax            ; selectors! (see trap0e handler)
00954 endif
00955 endif
00956 
00957 ifb <NoRestoreVolatiles>
00958         mov     edx, [ebp]+TsEdx            ; Restore volitales
00959         mov     ecx, [ebp]+TsEcx
00960 ifb <NoRestoreSegs>
00961 else
00962         mov     eax, [ebp]+TsEax
00963 endif
00964 endif   ; NoRestoreVolatiles
00965 
00966         cmp     word ptr [ebp]+TsSegCs, KGDT_R0_CODE
00967         jz      
short @f
00968 
00969 ifb <NoRestoreSegs>
00970         lea     esp, [ebp]+TsSegGs
00971         pop     gs                          ; Restore Segs
00972         pop     es
00973         pop     ds
00974 endif
00975 NonFlatPm_Target:
00976         lea     esp, [ebp]+TsSegFs
00977         pop     fs
00978 @@:
00979 V86_ExitHelp_Target:
00980 
00981         lea     esp, [ebp]+TsEdi            ; Skip PreMode, ExceptList and fs
00982 
00983         pop     edi                         ; restore non-volatiles
00984         pop     esi
00985         pop     ebx
00986         pop     ebp
00987 
00988 ;
00989 ; Esp MUST point to the Error Code on the stack.  Because we use it to
00990 ; store the entering esp.
00991 ;
00992 
00993         cmp     word ptr [esp+8], 80h ; check for abios code segment?
00994         ja      Abios_ExitHelp
00995 
00996 Abios_ExitHelp_Target1:
00997 
00998         add     esp, 4              ; remove error code from trap frame
00999 
01000 Abios_ExitHelp_Target2:
01001 
01002 ;
01003 ; End of ABIOS stack check
01004 ;
01005 
01006 ifnb <NoRestoreVolatiles>
01007 
01008         test  _KeFeatureBits, KF_FAST_SYSCALL
01009         jz      @f
01010 
01011         ;; If returning to kernel mode, use iretd
01012         test    dword ptr [esp+4], MODE_MASK
01013         jz      @f                  ; Return to kmode. use iretd
01014 
01015         ;; If returning to V86 mode, use iretd
01016         test    dword ptr [esp+8], EFLAGS_V86_MASK
01017         jnz     @f                  ; Return to user V86 mode
01018 
01019         pop     edx                 ; pop EIP
01020         add     esp, 8              ; Remove CS & Eflags
01021         pop     ecx                 ; pop ESP
01022 
01023         sti                         ; sysexit does not reload flags
01024         
01025 
01026         SYSEXIT_INSTR
01027 
01028 @@:
01029 endif  ;; <NoRestoreVolatiles>
01030 
01031         iretd                       ; return
01032 
01033 if DBG
01034 Db_NotATrapFrame:
01035         add     [esp]+TsDbgArgMark,0BADB0D00h   ; put back the orig value
01036 Db_NotValidEntry:
01037         
int 3
01038         jmp     Db_A
01039 endif
01040 
01041 ;
01042 ;   EXIT_HELPER
01043 ;
01044 ;       if (PreviousMode == UserMode) {
01045 ;           DR* regs = TF.Dr* regs
01046 ;       }
01047 ;
01048 ;   Entry-Conditions:
01049 ;
01050 ;       DebugActive == 
TRUE
01051 ;       (ebp)->TrapFrame
01052 ;
01053 ;--
01054 
01055 align dword
01056 Dr_ExitHelp:
01057 
01058         test    dword ptr [ebp]+TsEFlags,EFLAGS_V86_MASK
01059         jnz     
short x
01060 
01061         test    dword ptr [ebp]+TsSegCs,MODE_MASK
01062         jz      Dr_ExitHelp_Target
01063 
01064 x:      mov     ebx,0
01065         mov     esi,[ebp]+TsDr0
01066         mov     edi,[ebp]+TsDr1
01067         mov     dr7,ebx
01068         mov     dr0,esi
01069         mov     ebx,[ebp]+TsDr2
01070         mov     dr1,edi
01071         mov     dr2,ebx
01072         mov     esi,[ebp]+TsDr3
01073         mov     edi,[ebp]+TsDr6
01074         mov     ebx,[ebp]+TsDr7
01075         mov     dr3,esi
01076         mov     dr6,edi
01077         mov     dr7,ebx
01078 
01079         jmp     Dr_ExitHelp_Target
01080 
01081 align dword
01082 Abios_ExitHelp:
01083 
01084 ;
01085 ;   INTERRUPT_STACK32_TO_STACK16
01086 ;
01087 ;       This macro remaps current 32bit stack to 16bit stack at interrupt
01088 ;       time.
01089 ;
01090 ;   Arguments:
01091 ;
01092 ;       (esp)->TsEip.
01093 ;
01094 ;
01095 ; PERFNOTE shielint We should check 
if there 
is any other H/
W interrupt
01096 ;          pending.  If yes, don'
t switch back to 16 bit stack.  This way
01097 ;          we can get better performance.
01098 ;
01099 
01100         cmp     word ptr [esp+2], 0     ; (esp+2) = Low word of error code
01101         jz      Abios_ExitHelp_Target1
01102         cmp     word ptr [esp], 0       ; (esp) = High word of error code
01103         jnz     Abios_ExitHelp_Target1
01104 
01105         shr     dword ptr [esp], 16
01106         mov     word ptr [esp + 2], 
KGDT_STACK16
01107         lss     sp, dword ptr [esp]
01108         movzx   esp, sp
01109         jmp     Abios_ExitHelp_Target2
01110 
01111 ;
01112 ;   Restore volatiles 
for V86 mode, and 
move seg regs
01113 ;
01114 
01115 align dword
01116 V86_ExitHelp:
01117 
01118         add     esp,TsEdx
01119         pop     edx
01120         pop     ecx
01121         pop     eax
01122         jmp     V86_ExitHelp_Target
01123 
01124 ;
01125 
if ?RestoreAll eq 0
01126 ;
01127 ;   Restore segs and volatiles 
for non-flat R3 PM (VDM in PM)
01128 ;
01129 
01130 f:      mov     eax,[esp].TsEax     ; restore eax before any selectors
01131                                         ; (see trap0e handler)
01132         add     esp,TsSegGs
01133 
01134         pop     gs
01135         pop     es
01136         pop     
ds
01137 
01138         pop     edx
01139         pop     ecx
01140         jmp     NonFlatPm_Target
01141 
01142 endif   ; not ?RestoreAll
01143 
01144 
01145 ;
01146 ;   TsSegCs contains 
the special value that means 
the frame was edited
01147 ;   in a way that affected esp, AND 
it's a kernel mode frame.
01148 ;   (Special value 
is null selector except 
for RPL.)
01149 ;
01150 ;   Put back 
the real CS.
01151 ;   push eflags, eip onto target stack
01152 ;   restore
01153 ;   
switch to target stack
01154 ;   iret
01155 ;
01156 
01157 b:      mov     ebx,[esp]+TsTempSegCs
01158         mov     [esp]+TsSegCs,ebx
01159 
01160 ;
01161 ;   There 
is no instruction that will load esp with an arbitrary value
01162 ;   (i.e. one 
out of a frame) and 
do a 
return, 
if no privledge transition
01163 ;   
is occuring.  Therefore, 
if we are returning to kernel mode, and
01164 ;   esp has been edited, we must 
"emulate" a kind of iretd.
01165 ;
01166 ;   We 
do this by logically pushing 
the eip,cs,eflags onto 
the new
01167 ;   logical stack, loading that stack, and doing an iretd.  This
01168 ;   requires that 
the new logical stack 
is at least 1 dword higher
01169 ;   than 
the unedited esp would have been.  (i.e.  It 
is not legal
01170 ;   to edit esp to have a 
new value < 
the old value.)
01171 ;
01172 ;   
KeContextToKframes enforces 
this rule.
01173 ;
01174 
01175 ;
01176 ;   Compute 
new logical stack address
01177 ;
01178 
01179         mov     ebx,[esp]+TsTempEsp
01180         sub     ebx,12
01181         mov     [esp]+TsErrCode,ebx
01182 
01183 ;
01184 ;   
Copy eip,cs,eflags to 
new stack.  note we 
do this high to 
low
01185 ;
01186 
01187         mov     esi,[esp]+TsEflags
01188         mov     [ebx+8],esi
01189         mov     esi,[esp]+TsSegCs
01190         mov     [ebx+4],esi
01191         mov     esi,[esp]+TsEip
01192         mov     [ebx],esi
01193 
01194 ;
01195 ;   Do a standard restore sequence.
01196 ;
01197 ;   Observe that RestoreVolatiles 
is honored.  Editing a 
volatile
01198 ;   
register has no effect when returning from a system call.
01199 ;
01200 ifb     <NoRestoreVolatiles>
01201         mov     eax,[esp].TsEax
01202 endif
01203 ;        add     esp,TsSegGs
01204 ;
01205 ;ifb     <NoRestoreSegs>
01206 ;        pop     gs
01207 ;        pop     es
01208 ;        pop     
ds
01209 ;
else
01210 ;        add     esp,12
01211 ;endif
01212 
01213 ifb     <NoRestoreVolatiles>
01214         mov     edx, [esp]+TsEdx
01215         mov     ecx, [esp]+TsEcx
01216 endif
01217 
01218 ;ifnb <NoPreviousMode>
01219 ;        add     esp, 4              ; Skip previous mode
01220 ;
else
01221 ;        pop     ebx                 ; Restore PreviousMode
01222 ;        mov     esi,fs:[PcPrcbData+
PbCurrentThread]
01223 ;        mov     ss:[esi]+ThPreviousMode,bl
01224 ;endif
01225 ;
01226 ;       pop     ebx
01227 ;
01228 ;       mov     fs:[PcExceptionList], ebx ;Restore ExceptionList
01229 ;       pop     fs
01230 
01231         add     esp, TsEdi
01232         pop     edi                 ; restore non-volatiles
01233         pop     esi
01234         pop     ebx
01235         pop     ebp
01236 
01237 ;
01238 ;   (esp)->TsErrCode, where we saved 
the new esp
01239 ;
01240 
01241         mov     esp,[esp]           ; Do 
move not push to avoid increment
01242         iretd
01243 
01244         endm
01245 
01246 
01247 ;++
01248 ;
01249 ;   INTERRUPT_EXIT
01250 ;
01251 ;   Macro 
Description:
01252 ;
01253 ;       This macro 
is executed on 
return from an interrupt vector service
01254 ;       service routine.  Its function 
is to restore privileged processor
01255 ;       state, and 
continue thread execution. If 
control is returning to
01256 ;       user mode and there 
is a user  APC pending, then APC level interupt
01257 ;       will be requested and 
control is transfered to 
the user APC delivery
01258 ;       routine, 
if no higher level interrupt pending.
01259 ;
01260 ;   Arguments:
01261 ;
01262 ;       (TOS)   = previous irql
01263 ;       (TOS+4) = irq vector to eoi
01264 ;       (TOS+8 ...) = machine_state frame
01265 ;       (ebp)-> machine state frame (trap frame)
01266 ;
01267 ;--
01268 
01269 INTERRUPT_EXIT     macro    DebugCheck
01270 local   a
01271 
01272 ifnb <DebugCheck>
01273         POLL_DEBUGGER
01274 endif
01275 
if DBG                                          ; save current eip 
for
01276 a:      mov     esi, offset a                   ; debugging bad trap frames
01277 endif
01278 
01279 ifdef __imp_Kei386EoiHelper@0
01280         cli
01281         call    _HalEndSystemInterrupt@8
01282         jmp     dword ptr [__imp_Kei386EoiHelper@0]
01283 
01284 
else
01285         cli
01286         call    dword ptr [__imp__HalEndSystemInterrupt@8]
01287         jmp     Kei386EoiHelper@0
01288 endif
01289 endm
01290 
01291 
01292 ;++
01293 ;
01294 ;   SPURIOUS_INTERRUPT_EXIT
01295 ;
01296 ;   Macro 
Description:
01297 ;
01298 ;       To 
exit an interrupt without performing 
the EOI.
01299 ;
01300 ;   Arguments:
01301 ;
01302 ;       (TOS) = machine_state frame
01303 ;       (ebp)-> machine state frame (trap frame)
01304 ;
01305 ;--
01306 
01307 SPURIOUS_INTERRUPT_EXIT  macro
01308 local   a
01309 
if DBG                                          ; save current eip 
for
01310 a:      mov     esi, offset a                   ; debugging bad trap frames
01311 endif
01312 ifdef __imp_Kei386EoiHelper@0
01313         jmp     dword ptr [__imp_Kei386EoiHelper@0]
01314 
else
01315         jmp     Kei386EoiHelper@0
01316 endif
01317 endm
01318 
01319 ;++
01320 ;
01321 ;   ENTER_TRAPV86
01322 ;
01323 ;   Macro 
Description:
01324 ;
01325 ;       Construct trap frame 
for v86 mode traps.
01326 ;
01327 ;--
01328 
01329 ENTER_TRAPV86 macro DRENTER,V86ENTER,LOADES
01330         sub     esp, TsErrCode
01331         mov     word ptr [esp].TsErrCode + 2, 0
01332         mov     [esp].TsEbx, ebx
01333         mov     [esp].TsEax, eax
01334         mov     [esp].TsEbp, ebp
01335         mov     [esp].TsEsi, esi
01336         mov     [esp].TsEdi, edi
01337         mov     ebx, KGDT_R0_PCR
01338         mov     eax, KGDT_R3_DATA OR RPL_MASK
01339         mov     [esp].TsEcx, ecx
01340         mov     [esp].TsEdx, edx
01341 
if DBG
01342         mov     [esp].TsPreviousPreviousMode, -1
01343         mov     [esp]+TsDbgArgMark, 0BADB0D00h
01344 endif
01345         mov     fs, bx
01346         mov     
ds, ax
01347 ifnb <LOADES>
01348         mov     es, ax
01349 endif
01350         mov     ebp, esp
01351         cld                             ; CHECKIT_SUDEEP ; 
do we really need 
it
01352         test    byte ptr PCR[PcDebugActive], -1
01353         jnz     Dr_&DRENTER
01354 
01355 Dr_&V86ENTER:
01356 endm
01357 
01358 
01359 ;
01360 ; Taken from ntos\vdm\i386\vdmtb.inc
01361 ;
01362 
01363 FIXED_NTVDMSTATE_LINEAR_PC_AT equ 0714H
01364 FIXED_NTVDMSTATE_LINEAR_PC_98 equ 0614H
01365 MACHINE_TYPE_MASK equ 0ff00H
01366 
VDM_VIRTUAL_INTERRUPTS  equ 0200H
01367 
01368 ;++
01369 ;
01370 ;   EXIT_TRAPV86
01371 ;
01372 ;   Macro 
Description:
01373 ;
01374 ;       
if UserApc 
is pending deliver 
it
01375 ;       
if User Context 
is v86 mode
01376 ;          Exit from kernel (does not 
return)
01377 ;       
else
01378 ;          
return (expected to execute EXIT_ALL)
01379 ;--
01380 
01381 EXIT_TRAPV86 macro
01382         local w, x, y, z
01383 
01384 z:      mov     ebx, PCR[PcPrcbData+
PbCurrentThread]
01385         mov     byte ptr [ebx]+ThAlerted, 0
01386         cmp     byte ptr [ebx]+ThApcState.AsUserApcPending, 0
01387         jne     
short w
01388 
01389         ;
01390         ; Kernel 
exit to V86 mode
01391         ;
01392 
01393         add     esp,TsEdx
01394         pop     edx
01395         pop     ecx
01396         pop     eax
01397         test    byte ptr PCR[PcDebugActive], -1
01398         jnz     
short x
01399 y:
01400         add     esp,12              ; unused fields
01401         pop     edi
01402         pop     esi
01403         pop     ebx
01404         pop     ebp
01405         add     esp,4               ; clear error code
01406         iretd
01407 
01408 x:      mov     esi,[ebp]+TsDr0
01409         mov     edi,[ebp]+TsDr1
01410         mov     ebx,[ebp]+TsDr2
01411         mov     dr0,esi
01412         mov     dr1,edi
01413         mov     dr2,ebx
01414         mov     esi,[ebp]+TsDr3
01415         mov     edi,[ebp]+TsDr6
01416         mov     ebx,[ebp]+TsDr7
01417         mov     dr3,esi
01418         mov     dr6,edi
01419         mov     dr7,ebx
01420         jmp     
short y
01421 
01422 w:
01423         ;
01424         ; Dispatch user mode APC
01425         ; The APC routine runs with interrupts on and at APC level
01426         ;
01427 
01428         mov     ecx, 
APC_LEVEL
01429         fstCall KfRaiseIrql
01430         push    eax                              ; Save OldIrql
01431         sti
01432 
01433         stdCall _KiDeliverApc, <1, 0, ebp>       ; ebp - Trap frame
01434                                                  ; 0 - Null exception frame
01435                                                  ; 1 - Previous mode
01436 
01437         pop     ecx                              ; (TOS) = OldIrql
01438         fstCall KfLowerIrql
01439 
01440         cli
01441 
01442         ;
01443         ; UserApc may have changed to vdm Monitor context (user flat 32)
01444         ; If 
it has cannot use 
the v86 
only kernel 
exit
01445         ;
01446 
01447         test    dword ptr [ebp]+TsEFlags,EFLAGS_V86_MASK
01448         jnz     
short z
01449 
01450         ; Exit to 
do EXIT_ALL
01451 endm