summaryrefslogtreecommitdiff
path: root/v4.0/src/MEMM/MEMM/EM386LL.ASM
diff options
context:
space:
mode:
Diffstat (limited to 'v4.0/src/MEMM/MEMM/EM386LL.ASM')
-rw-r--r--v4.0/src/MEMM/MEMM/EM386LL.ASM397
1 files changed, 397 insertions, 0 deletions
diff --git a/v4.0/src/MEMM/MEMM/EM386LL.ASM b/v4.0/src/MEMM/MEMM/EM386LL.ASM
new file mode 100644
index 0000000..3408eaa
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/EM386LL.ASM
@@ -0,0 +1,397 @@
1
2
3page 58,132
4;******************************************************************************
5 title EM386LL - 386 routine to emulate 386 LOADALL
6;******************************************************************************
7;
8; (C) Copyright MICROSOFT Corp. 1986
9;
10; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11;
12; Module: EM386LL - 386 routine to emulate 386 LOADALL
13;
14; Version: 0.04
15;
16; Date: April 11,1986
17;
18; Author:
19;
20;******************************************************************************
21;
22; Change log:
23;
24; DATE REVISION DESCRIPTION
25; -------- -------- -------------------------------------------------------
26; 04/16/86 Original
27; 05/12/86 A Cleanup and segment reorganization
28; 06/28/86 0.02 Name change from MEMM386 to MEMM
29; 06/29/86 0.02 Fixed error handler call. Error handler called
30; only on attempt to set VM bit in EFLAGS
31; 06/30/86 0.02 Jmp to error routine (instead of calling)
32; 07/03/86 0.03 Removed logic to enable A20 line watch
33; 07/05/86 0.04 JumpReal in R_CODE
34; 07/06/86 0.04 Changed assume to DGROUP
35; 07/08/86 0.04 added DB67 NOPs to avoid B1 errata
36;
37;******************************************************************************
38;
39; Functional Description:
40;
41; 386 LOADALL is emulated by building a buffer for a
42; 386 LOADALL from the client's 386 LOADALL buffer and executing the 386
43; LOADALL.
44;
45; check DR6/DR7 for addresses > 1meg ?
46;
47;******************************************************************************
48.lfcond ; list false conditionals
49.386p
50 page
51;******************************************************************************
52; P U B L I C D E C L A R A T I O N S
53;******************************************************************************
54;
55 public EM386ll
56;
57 page
58;******************************************************************************
59; L O C A L C O N S T A N T S
60;******************************************************************************
61;
62 include loadall.inc
63 include VDMseg.inc
64 include desc.inc
65 include VDMsel.inc
66 include instr386.inc
67 include vm386.inc
68 include oemdep.inc
69
70FALSE equ 0
71TRUE equ not FALSE
72
73;
74; Desc3Copy
75; Macro for copying a 386 Loadall descriptor cache entry to a
76; 386 Loadall descriptor cache entry.
77; ENTRY: DS:ESI pts to client's 386 Loadall descriptor entry
78; ES:DI pts to our 386 Loadall descriptor entry
79;
80; EXIT: DS:ESI pts to byte after client's 386 ll descr entry (next entry).
81; ES:DI pts to byte after 386 Loadall descriptor entry (next entry).
82; *** The access rights byte in set to DPL 3 for virtual mode ***
83;
84; USED: EAX
85;
86Desc3Copy MACRO
87 OP32
88 EA32 ; EAX = dword from DS:[ESI]
89 lodsw ; get access rights
90
91 or ah,D_DPL3 ;* set DPL 3 for virtual mode access
92
93 OP32
94 stosw ; store access rights
95
96 OP32
97 EA32 ; EAX = dword from DS:[ESI]
98 lodsw ; 32 bits of Base Addr from 386 entry
99
100 call MapLinear ; map this linear addr by page tables
101
102 OP32
103 stosw ; store Base Addr for 386 entry
104
105 OP32
106 EA32 ; EAX = dword from DS:[ESI]
107 lodsw ; get 32 bits of limit
108
109 OP32
110 stosw ; store 32 bit LIMIT into 386 entry
111 ENDM
112
113;
114; CurCopy
115; Macro for copying a current descriptor cache entry to a
116; 386 Loadall descriptor cache entry.
117; ENTRY: DS:BX pts to current descriptor
118; ES:DI pts to 386 Loadall descriptor entry
119;
120; EXIT: DS:BX unchanged.
121; ES:DI pts to byte after 386 Loadall descriptor entry (next entry).
122; *** The access rights byte in set to DPL 3 for virtual mode ***
123;
124; USED: EAX
125;
126CurCopy MACRO
127 OP32
128 mov ax,[bx+4] ; get AR info
129 or ah,D_DPL3 ;* set DPL 3 for virtual mode access
130 OP32
131 stosw ; store into cache entry
132 mov ah,[bx+7] ; AX = Base[31..16]
133 OP32
134 shl ax,16 ; high word of EAX = Base[31..16]
135 mov ax,[bx+2] ; EAX = Base[31..0]
136 OP32
137 stosw
138 mov al,[bx+6] ; LIMIT[19..16] in low bits of AL
139 and ax,0Fh
140 OP32
141 shl ax,16 ; high word of EAX = LIMIT[31..16]
142 ; NOTE: VDM does not use page
143 ; granularity for limit field !!
144 mov ax,[bx] ; EAX = LIMIT[31..0]
145 OP32
146 stosw ; store into cache for 386 buffer
147 ENDM
148
149;******************************************************************************
150; L O C A L D A T A A R E A
151;******************************************************************************
152
153_DATA segment
154extrn ELOff:word ; offset of 386 loadall buffer
155_DATA ends
156
157
158R_CODE segment
159extrn JumpReal:far ; continue client in real mode (rrtrap.asm)
160R_CODE ends
161
162_TEXT segment
163extrn MapLinear:near ; maps linear addresses (maplin.asm)
164extrn PortTrap:near ; IOBM trap set function (vminit.asm)
165extrn ErrHndlr:near ; error handler (errhndlr.asm)
166_TEXT ends
167
168
169 page
170;******************************************************************************
171; S E G M E N T D E F I N I T I O N
172;******************************************************************************
173;
174_TEXT segment
175 ASSUME CS:_TEXT,DS:DGROUP,ES:DGROUP
176
177;******************************************************************************
178; EM386ll - emulate 386 Loadall
179; The basic approach here is to filter the client's loadall buffer into
180; a temporary buffer, setting our values for the parameters we don't want
181; him to change and then executing the 386 loadall from our buffer.
182;
183; ENTRY: Protected Mode
184; BP points to bottom of client's GPfault stack frame
185; ES(in GP frame):EDI points to the client's loadall buffer info
186; on stack: ESI,EBX,EBP
187;
188; EXIT: via Loadall to virtual mode
189; The 386 Loadall buffer is emulated with the following
190; exceptions:
191; The VM bit is set in EFLAGS.
192; The TR, IDT descriptor cache, & TSS descriptor cache are
193; pointed to the VDM entries.
194;
195; USED: Not applicable... loadall reloads all registers
196;
197;******************************************************************************
198EM386ll proc near
199;
200 PUSH_EAX
201 PUSH_ECX
202 PUSH_EDI
203
204; Build a descriptor to client's 386 loadall buffer
205
206 mov bx,GDTD_GSEL ; get GDT data alias
207 mov ds,bx ; DS -> GDT
208 mov bx, [bp.VTFOE+VMTF_ES] ; Get VM ES from GP stack frame
209 mov ax,bx
210 shl bx,4 ; BX = low 16 bits of base
211 mov ds:[VM1_GSEL+2],bx ; place in descriptor
212 shr ax, 4 ; AH = high 8 bits of base
213 mov ds:[VM1_GSEL+4],ah ; place in descriptor
214
215; Point DS:ESI to start of client's 386 loadall buffer
216 mov bx,VM1_GSEL
217 mov ds,bx
218 OP32
219 mov si,di
220 ASSUME ds:nothing
221
222; Point ES:EDI to start of our 386 loadall buffer
223
224 mov ax,VDMD_GSEL
225 mov es,ax
226 OP32
227 xor di,di ; clear EDI
228 mov di,ES:[ELOff] ; ES:EDI pts to our 386 loadall buffer
229;
230 cld
231
232; Walk through the two buffers in parallel, copying the client's values
233; when appropriate
234
235;
236; CR0 entry
237;
238 EA32
239 OP32
240 lodsw ; get client's CR0
241
242;(0.02) OP32
243;(0.02) test ax,0001h ; TEST EAX,80000001h
244;(0.02) dw 8000h ; Q: PG or PE bit set ?
245;(0.02) jz CR0_OK ; N: continue
246;(0.02) call Em386_Err ; Y: error
247;
248CR0_OK:
249 MOV_ECX_CR0
250 OP32
251 and cx,0011h ; and ECX,80000011h
252 dw 8000h ; save only PG,ET, & PE bits
253 OP32
254 or ax,cx ; or EAX,ECX
255 OP32
256 stosw ; store CR0 for 386 buffer
257 XOR_ECX_ECX ; clear ECX
258;
259; EFLAGS
260;
261 EA32
262 OP32
263 lodsw ; get EFLAGS
264;
265 OP32
266 test ax,0000h
267 dw 0002h ;Q: client's VM bit set ?
268 jz EF_OK ; N: continue
269 jmp Em386_Err ; Y: error handler - won't return here
270EF_OK:
271 and ax,0FFFh ; clear IOPL & NT bits
272 OP32
273 or ax,3000h
274 dw 0002h ; set VM bit and IOPL = 3
275 OP32
276 stosw ; store EFLAGS for 386 buffer
277;
278; Copy the client's EIP, EDI, ESI, EBP, ESP, EBX, EDX, ECX, EAX, DR6 & DR7
279; register images from his 386 loadall buffer to our 386 loadall buffer
280;
281 mov cx,11 ; copy 11 register contents
282 OP32 ; dwords from DS:[ESI] to ES:[EDI]
283 EA32
284 rep movsw ; copy 11 dwords
285
286 EA32
287 nop ; this avoids a B1 errata
288;
289; store TR and LDTR
290;
291 XOR_EAX_EAX ; clear EAX
292 mov ax,TSS_GSEL ; get current TR for VDM's TSS !!!
293 OP32
294 stosw ; store TR for 386 buffer
295;
296 sldt ax ; use current LDT
297 OP32
298 stosw ; store LDTR for 386 buffer
299;
300; Copy the client's GS, FS, DS, SS, CS, ES register images from
301; his 386 loadall buffer to our 386 loadall buffer
302;
303 add si,offset ll3_GS - offset ll3_TSSR
304 mov cx,6
305 OP32 ; dwords from DS:[ESI] to ES:[EDI]
306 EA32
307 rep movsw ; copy 6 dwords
308
309 EA32
310 nop ; this avoids a B1 errata
311;
312; Copy the current TSS, GDT, IDT, LDT descriptors from the GDT table to
313; our 386 loadall buffer
314;
315 push ds ; save client's buffer selector
316 mov ax,GDTD_GSEL
317 mov ds,ax
318
319 mov cx, 4
320 mov bx, TSS_GSEL
321 push word ptr LDTD_GSEL
322 push word ptr GDTD_GSEL
323 push word ptr IDTD_GSEL
324
325CopyCur: ; Copy current descriptors
326 CurCopy ; DS:[BX] points to current descriptor
327 pop bx
328 loop CopyCur
329 mov ds, bx ; restore client's buffer selector
330
331 ; DS:SI pts to 386 GS cache entry
332;
333; Copy the client's GS, FS, DS, SS, CS, ES register cache images from
334; his 386 loadall buffer to our 386 loadall buffer
335;
336 add si,offset ll3_GScache - offset ll3_TSScache
337 mov cx,6
338CopyCac: ; ES:DI pts to our 386 buf cache entry
339 Desc3Copy ; store his cache in our 386 buffer
340 loop CopyCac ; DS:SI pts to client's buf cache entry
341
342;
343; 386 Loadall buffer complete
344;
345
346;(0.03) push es
347;(0.03) mov ax, TSSD_GSEL ; Point ES to TSS for PortTrap
348;(0.03) mov es, ax
349;(0.03) mov bh, 80h ; set every 1k
350;(0.03) mov ax, KbdDataPort
351;(0.03) call PortTrap ; set traps on keyboard ports
352;(0.03) mov ax, KbdCmdPort ; in case client
353;(0.03) call PortTrap ; tries to disable A20
354;(0.03) pop es
355;(0.03) mov es:[A20watch], YesLLdone ; set A20 watch flag
356
357 HwTabLock ; Hardware lock the high ram
358
359 OP32
360 xor di,di ; XOR EDI,EDI - clear EDI
361 mov di,ES:[ELOff] ; ES:EDI pts to loadall buffer
362 dw LODAL386 ; execute 386 LOADALL
363
364 ASSUME DS:DGROUP
365;
366;
367EM386ll endp
368
369 page
370;******************************************************************************
371; Em386_Err - handle 386 ll emulation error
372; This routine is currently called only on attempts to set the
373; VM bit via loadall.
374;******************************************************************************
375Em386_Err proc near
376 push ax
377 push bx
378 mov ax, PrivErr
379 mov bx, Err3LL
380 call ErrHndlr
381 pop bx
382 pop bx
383;
384; continue client in real mode
385;
386 POP_EDI ; restore used regs
387 POP_ECX
388 POP_EAX
389 ; stack back to VmFault exit condition
390
391 jmp JumpReal ; "jump" to real mode and continue interrupted
392 ; code.
393
394Em386_Err endp
395;
396_TEXT ends
397 end