summaryrefslogtreecommitdiffstats
path: root/private/mvdm/v86/monitor/i386/fastpm.asm
blob: e42959d049572226299f4601d31a1fcb065887da (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
        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 vdmtb.inc

_TEXT   SEGMENT PARA PUBLIC 'CODE'
        ASSUME  DS:NOTHING, ES:NOTHING, SS:FLAT, FS:NOTHING, GS:NOTHING
_TEXT   ENDS

_DATA   SEGMENT  DWORD PUBLIC 'DATA'
        extrn _VdmTib:Dword

        public _NTVDMpLockPrefixTable
_NTVDMpLockPrefixTable    label dword
        dd offset FLAT:_ntvdmlock1
        dd offset FLAT:_ntvdmlock2
        dd 0

_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

        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
        lea     ebx,_VdmTib

        ; 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

        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 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
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
	lea	ebx,_VdmTib			; get pointer to contexts
        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
        ; return
        iretd
stdENDP _FastLeavePm

_TEXT ends
        end