]>
wirehaze git hosting - MS-DOS.git/blob - v4.0/src/MEMM/MEMM/EM386LL.ASM
4 ;******************************************************************************
5 title EM386LL
- 386 routine to emulate
386 LOADALL
6 ;******************************************************************************
8 ; (C) Copyright MICROSOFT Corp. 1986
10 ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
12 ; Module: EM386LL - 386 routine to emulate 386 LOADALL
20 ;******************************************************************************
24 ; DATE REVISION DESCRIPTION
25 ; -------- -------- -------------------------------------------------------
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
37 ;******************************************************************************
39 ; Functional Description:
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
45 ; check DR6/DR7 for addresses > 1meg ?
47 ;******************************************************************************
48 .lfcond
; list false conditionals
51 ;******************************************************************************
52 ; P U B L I C D E C L A R A T I O N S
53 ;******************************************************************************
58 ;******************************************************************************
59 ; L O C A L C O N S T A N T S
60 ;******************************************************************************
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
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 ***
88 EA32
; EAX = dword from DS:[ESI]
89 lodsw ; get access rights
91 or ah,D_DPL3
;* set DPL 3 for virtual mode access
94 stosw ; store access rights
97 EA32
; EAX = dword from DS:[ESI]
98 lodsw ; 32 bits of Base Addr from 386 entry
100 call MapLinear
; map this linear addr by page tables
103 stosw ; store Base Addr for 386 entry
106 EA32
; EAX = dword from DS:[ESI]
107 lodsw ; get 32 bits of limit
110 stosw ; store 32 bit LIMIT into 386 entry
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
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 ***
128 mov ax,[bx+4] ; get AR info
129 or ah,D_DPL3
;* set DPL 3 for virtual mode access
131 stosw ; store into cache entry
132 mov ah,[bx+7] ; AX = Base[31..16]
134 shl ax,16 ; high word of EAX = Base[31..16]
135 mov ax,[bx+2] ; EAX = Base[31..0]
138 mov al,[bx+6] ; LIMIT[19..16] in low bits of AL
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]
146 stosw ; store into cache for 386 buffer
149 ;******************************************************************************
150 ; L O C A L D A T A A R E A
151 ;******************************************************************************
154 extrn ELOff
:word ; offset of 386 loadall buffer
159 extrn JumpReal
:far ; continue client in real mode (rrtrap.asm)
163 extrn MapLinear
:near ; maps linear addresses (maplin.asm)
164 extrn PortTrap
:near ; IOBM trap set function (vminit.asm)
165 extrn ErrHndlr
:near ; error handler (errhndlr.asm)
170 ;******************************************************************************
171 ; S E G M E N T D E F I N I T I O N
172 ;******************************************************************************
175 ASSUME
CS:_TEXT
,DS:DGROUP
,ES:DGROUP
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.
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
188 ; EXIT: via Loadall to virtual mode
189 ; The 386 Loadall buffer is emulated with the following
191 ; The VM bit is set in EFLAGS.
192 ; The TR, IDT descriptor cache, & TSS descriptor cache are
193 ; pointed to the VDM entries.
195 ; USED: Not applicable... loadall reloads all registers
197 ;******************************************************************************
204 ; Build a descriptor to client's 386 loadall buffer
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
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
215 ; Point DS:ESI to start of client's 386 loadall buffer
222 ; Point ES:EDI to start of our 386 loadall buffer
227 xor di,di ; clear EDI
228 mov di,ES:[ELOff
] ; ES:EDI pts to our 386 loadall buffer
232 ; Walk through the two buffers in parallel, copying the client's values
240 lodsw ; get client's CR0
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
251 and cx,0011h ; and ECX,80000011h
252 dw 8000h
; save only PG,ET, & PE bits
254 or ax,cx ; or EAX,ECX
256 stosw ; store CR0 for 386 buffer
257 XOR_ECX_ECX
; clear ECX
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
271 and ax,0FFFh ; clear IOPL & NT bits
274 dw 0002h ; set VM bit and IOPL = 3
276 stosw ; store EFLAGS for 386 buffer
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
281 mov cx,11 ; copy 11 register contents
282 OP32
; dwords from DS:[ESI] to ES:[EDI]
284 rep movsw ; copy 11 dwords
287 nop ; this avoids a B1 errata
291 XOR_EAX_EAX
; clear EAX
292 mov ax,TSS_GSEL
; get current TR for VDM's TSS !!!
294 stosw ; store TR for 386 buffer
296 sldt ax ; use current LDT
298 stosw ; store LDTR for 386 buffer
300 ; Copy the client's GS, FS, DS, SS, CS, ES register images from
301 ; his 386 loadall buffer to our 386 loadall buffer
303 add si,offset ll3_GS
- offset ll3_TSSR
305 OP32
; dwords from DS:[ESI] to ES:[EDI]
307 rep movsw ; copy 6 dwords
310 nop ; this avoids a B1 errata
312 ; Copy the current TSS, GDT, IDT, LDT descriptors from the GDT table to
313 ; our 386 loadall buffer
315 push ds ; save client's buffer selector
321 push word ptr LDTD_GSEL
322 push word ptr GDTD_GSEL
323 push word ptr IDTD_GSEL
325 CopyCur: ; Copy current descriptors
326 CurCopy
; DS:[BX] points to current descriptor
329 mov ds, bx ; restore client's buffer selector
331 ; DS:SI pts to 386 GS cache entry
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
336 add si,offset ll3_GScache
- offset ll3_TSScache
338 CopyCac: ; 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
343 ; 386 Loadall buffer complete
347 ;(0.03) mov ax, TSSD_GSEL ; Point ES to TSS for PortTrap
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
355 ;(0.03) mov es:[A20watch], YesLLdone ; set A20 watch flag
357 HwTabLock
; Hardware lock the high ram
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
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 ;******************************************************************************
384 ; continue client in real mode
386 POP_EDI
; restore used regs
389 ; stack back to VmFault exit condition
391 jmp JumpReal
; "jump" to real mode and continue interrupted