VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToRM.asm@ 66316

Last change on this file since 66316 was 64694, checked in by vboxsync, 8 years ago

bs3kit: Added Bs3SwitchTo32BitAndCallC and fixed a few problems switching from PE32 to other mode and back again.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.6 KB
Line 
1; $Id: bs3-mode-SwitchToRM.asm 64694 2016-11-17 17:10:47Z vboxsync $
2;; @file
3; BS3Kit - Bs3SwitchToRM
4;
5
6;
7; Copyright (C) 2007-2016 Oracle Corporation
8;
9; This file is part of VirtualBox Open Source Edition (OSE), as
10; available from http://www.virtualbox.org. This file is free software;
11; you can redistribute it and/or modify it under the terms of the GNU
12; General Public License (GPL) as published by the Free Software
13; Foundation, in version 2 as it comes in the "COPYING" file of the
14; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16;
17; The contents of this file may alternatively be used under the terms
18; of the Common Development and Distribution License Version 1.0
19; (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20; VirtualBox OSE distribution, in which case the provisions of the
21; CDDL are applicable instead of those of the GPL.
22;
23; You may elect to license modified versions of this file under the
24; terms and conditions of either the GPL or the CDDL or both.
25;
26
27%include "bs3kit-template-header.mac"
28
29BS3_EXTERN_SYSTEM16 Bs3Gdt
30%if TMPL_MODE == BS3_MODE_PE16
31BS3_EXTERN_DATA16 g_uBs3CpuDetected
32BS3_EXTERN_CMN Bs3KbdWrite
33BS3_EXTERN_CMN Bs3KbdWait
34%endif
35
36
37;*********************************************************************************************************************************
38;* Global Variables *
39;*********************************************************************************************************************************
40%if TMPL_MODE == BS3_MODE_PE16
41BS3_BEGIN_DATA16
42;; Where to start restoring stack.
43g_ResumeSp: dw 0xfeed
44;; Where to start restoring stack.
45g_ResumeSs: dw 0xface
46%endif
47
48TMPL_BEGIN_TEXT
49
50
51;;
52; Switch to real mode from any other mode.
53;
54; @cproto BS3_DECL(void) Bs3SwitchToRM(void);
55;
56; @uses GPRs and EFLAGS are unchanged (except high 32-bit register (AMD64) parts).
57; CS is loaded with CGROUP16.
58; SS:[RE]SP is converted to real mode address.
59; DS and ES are loaded with BS3DATA16_GROUP.
60; FS and GS are loaded with zero if present.
61;
62; @remarks Obviously returns to 16-bit mode, even if the caller was
63; in 32-bit or 64-bit mode.
64;
65; @remarks Does not require 20h of parameter scratch space in 64-bit mode.
66;
67%if TMPL_BITS == 16
68BS3_GLOBAL_NAME_EX TMPL_NM(Bs3SwitchToRM_Safe), function , 0
69%endif
70BS3_PROC_BEGIN_MODE Bs3SwitchToRM, BS3_PBC_NEAR
71%ifdef TMPL_RM
72 push ax
73 mov ax, BS3_SEL_DATA16
74 mov ds, ax
75 mov es, ax
76 pop ax
77 ret
78
79%elif BS3_MODE_IS_V86(TMPL_MODE)
80 ;
81 ; V8086 - Switch to 16-bit ring-0 and call worker for that mode.
82 ;
83 extern BS3_CMN_NM(Bs3SwitchToRing0)
84 call BS3_CMN_NM(Bs3SwitchToRing0)
85 extern %[BS3_MODE_R0_NM_ %+ TMPL_MODE](Bs3SwitchToRM)
86 jmp %[BS3_MODE_R0_NM_ %+ TMPL_MODE](Bs3SwitchToRM)
87
88%else
89 ;
90 ; Protected mode.
91 ; 80286 requirements for PE16 clutters the code a little.
92 ;
93 %if TMPL_MODE == BS3_MODE_PE16
94 cmp byte [BS3_DATA16_WRT(g_uBs3CpuDetected)], BS3CPU_80286
95 ja .do_386_prologue
96 push ax
97 push bx
98 pushf
99 push word 1
100 jmp .done_prologue
101 %endif
102.do_386_prologue:
103 push sAX
104 push sBX
105 sPUSHF
106 %if TMPL_MODE == BS3_MODE_PE16
107 push word 0
108 %elif BS3_MODE_IS_64BIT_SYS(TMPL_MODE)
109 push sDX
110 push sCX
111 %endif
112.done_prologue:
113
114 ;
115 ; Get to 16-bit ring-0 and disable interrupts.
116 ;
117 extern BS3_CMN_NM(Bs3SwitchToRing0)
118 call BS3_CMN_NM(Bs3SwitchToRing0)
119
120 cli
121
122 %if TMPL_MODE == BS3_MODE_PE16
123 ;
124 ; On 80286 we must reset the CPU to get back to real mode.
125 ;
126 CPU 286
127 pop ax
128 push ax
129 test ax, ax
130 jz .is_386_or_better
131
132 ; Save registers and flags, storing SS:SP in at a known global address.
133%ifdef BS3_STRICT
134 mov ax, 0feedh
135 mov bx, 0faceh
136%endif
137 push di
138 push si
139 push bp
140 push bx
141 push dx
142 push cx
143 push ax
144 pushf
145
146 ; Convert ss:sp to real mode address.
147 BS3_EXTERN_CMN Bs3SelProtFar32ToFlat32
148 mov ax, sp
149 push ss
150 push 0
151 push ax
152 call Bs3SelProtFar32ToFlat32
153 add sp, 6
154
155 mov [g_ResumeSp], ax
156 shl dx, 12
157 mov [g_ResumeSs], dx
158
159 ; Setup resume vector.
160 mov bx, BS3_SEL_R0_SS16
161 mov es, bx
162 mov word [es:467h], .resume
163 mov word [es:467h+2], BS3_SEL_TEXT16
164
165 mov al, 0fh | 80h
166 out 70h, al ; set register index
167 in al, 80h
168 mov al, 0ah ; shutdown action command - no EOI, no 287 reset.
169 out 71h, al ; set cmos[f] = al - invoke testResume as early as possible.
170 in al, 71h ; flush
171
172 %if 0 ; for testing in VM
173 CPU 386
174 mov ax, BS3_SEL_R0_DS16
175 mov ds, ax
176 mov es, ax
177 mov fs, ax
178 mov gs, ax
179
180 mov eax, cr0
181 and ax, ~X86_CR0_PE
182 mov cr0, eax
183 jmp BS3_SEL_TEXT16:.resume
184 %endif
185
186 ; Port A reset. (FYI: tripple fault does not do the trick)
187 in al, 92h
188 or al, 1
189 out 92h, al
190 in al, 80h ; flush
191 mov cx, 0ffffh
192.reset_delay:
193 loop .reset_delay
194
195 ; Keyboard controller reset.
196 call Bs3KbdWait
197 push 0 ; zero data (whatever.
198 push 0fh ; KBD_CCMD_RESET
199 call Bs3KbdWrite
200.forever:
201 jmp .forever
202
203 ; This is the resume point. We should be in real mode now, at least in theory.
204.resume:
205 mov ax, BS3_SEL_DATA16
206 mov ds, ax
207 mov es, ax
208 mov ax, [g_ResumeSp]
209 mov ss, [g_ResumeSs]
210 mov sp, ax
211
212 popf
213 pop ax
214 pop cx
215 pop dx
216 pop bx
217 pop bp
218 pop si
219 pop di
220 %ifdef BS3_STRICT
221 cmp ax, 0feedh
222 jne .bad_286_rm_switch
223 cmp bx, 0faceh
224 jne .bad_286_rm_switch
225 %endif
226 jmp .enter_mode
227
228 %ifdef BS3_STRICT
229.bad_286_rm_switch:
230 mov ax, 0e00h + 'Q'
231 mov bx, 0ff00h
232 int 10h
233 jmp .bad_286_rm_switch
234 %endif
235
236 CPU 386
237 %elif TMPL_BITS != 16
238 ;
239 ; Must be in 16-bit segment when calling Bs3SwitchTo16Bit.
240 ;
241 jmp .sixteen_bit_segment wrt FLAT
242BS3_BEGIN_TEXT16
243 BS3_SET_BITS TMPL_BITS
244BS3_GLOBAL_LOCAL_LABEL .sixteen_bit_segment
245
246 extern BS3_CMN_NM(Bs3SwitchTo16Bit)
247 call BS3_CMN_NM(Bs3SwitchTo16Bit)
248 BS3_SET_BITS 16
249 %endif
250 ;
251 ; Before exiting to real mode we must load sensible selectors into the
252 ; segment registers so the hidden parts (which doesn't get reloaded in
253 ; real mode) are real mode compatible.
254 ;
255.is_386_or_better:
256;; @todo Testcase: Experiment leaving weird stuff in the hidden segment registers.
257 mov ax, BS3_SEL_R0_DS16
258 mov ds, ax
259 mov es, ax
260 mov fs, ax
261 mov gs, ax
262
263 ;
264 ; Exit to real mode.
265 ;
266 mov eax, cr0
267 and eax, X86_CR0_NO_PE_NO_PG
268 mov cr0, eax
269 jmp CGROUP16:.reload_cs
270.reload_cs:
271
272 ;
273 ; Convert the stack (now 16-bit prot) to real mode.
274 ;
275 mov ax, BS3_SEL_SYSTEM16
276 mov ds, ax
277 mov bx, ss
278 and bx, X86_SEL_MASK ; ASSUMES GDT stack selector
279 mov al, [bx + 4 + Bs3Gdt]
280 mov ah, [bx + 7 + Bs3Gdt]
281 add sp, [bx + 2 + Bs3Gdt] ; ASSUMES not expand down segment.
282 adc ax, 0
283 %ifdef BS3_STRICT
284 test ax, 0fff0h
285 jz .stack_conv_ok
286 int3
287.stack_conv_ok:
288 %endif
289 shl ax, 12
290 mov ss, ax
291 %if TMPL_BITS != 16
292 and esp, 0ffffh
293 %endif
294
295 %if BS3_MODE_IS_64BIT_SYS(TMPL_MODE)
296 ;
297 ; Clear the long mode enable bit.
298 ;
299 mov ecx, MSR_K6_EFER
300 rdmsr
301 and eax, ~MSR_K6_EFER_LME
302 wrmsr
303 %endif
304
305 ;
306 ; Call routine for doing mode specific setups.
307 ;
308.enter_mode:
309 extern NAME(Bs3EnteredMode_rm)
310 call NAME(Bs3EnteredMode_rm)
311
312 %if TMPL_MODE == BS3_MODE_PE16
313 pop ax
314 test ax, ax
315 jz .do_386_epilogue
316 popf
317 pop bx
318 pop ax
319 ret
320 %endif
321.do_386_epilogue:
322 %if BS3_MODE_IS_64BIT_SYS(TMPL_MODE)
323 pop ecx
324TONLY64 pop eax
325 pop edx
326TONLY64 pop eax
327 %endif
328 popfd
329TONLY64 pop eax
330 pop ebx
331TONLY64 pop eax
332 pop eax
333TONLY64 add sp, 4
334 retn (TMPL_BITS - 16) / 8
335
336 %if TMPL_BITS != 16
337TMPL_BEGIN_TEXT
338 %endif
339%endif
340BS3_PROC_END_MODE Bs3SwitchToRM
341
342
343%if TMPL_BITS == 16
344;;
345; Custom far stub.
346BS3_BEGIN_TEXT16_FARSTUBS
347BS3_PROC_BEGIN_MODE Bs3SwitchToRM, BS3_PBC_FAR
348 inc bp
349 push bp
350 mov bp, sp
351
352 ; Call the real thing.
353 call TMPL_NM(Bs3SwitchToRM)
354
355 %if !BS3_MODE_IS_RM_OR_V86(TMPL_MODE)
356 ; Jmp to common code for the tedious conversion.
357 BS3_EXTERN_CMN Bs3SwitchHlpConvProtModeRetfPopBpDecBpAndReturn
358 jmp Bs3SwitchHlpConvProtModeRetfPopBpDecBpAndReturn
359 %else
360 pop bp
361 dec bp
362 retf
363 %endif
364BS3_PROC_END_MODE Bs3SwitchToRM
365
366%else
367;;
368; Safe far return to non-BS3TEXT16 code.
369BS3_EXTERN_CMN Bs3SelFlatCodeToRealMode
370BS3_BEGIN_TEXT16
371BS3_SET_BITS TMPL_BITS
372BS3_PROC_BEGIN_MODE Bs3SwitchToRM_Safe, BS3_PBC_NEAR
373 %if TMPL_BITS == 64
374 push xAX
375 push xCX
376 sub xSP, 20h
377
378 mov xCX, [xSP + xCB*2 + 20h]
379 call Bs3SelFlatCodeToRealMode ; well behaved assembly function, only clobbers ecx
380 mov [xSP + xCB*2 + 20h + 4], eax
381
382 add xSP, 20h
383 pop xCX
384 pop xAX
385 add xSP, 4
386 %else
387 xchg eax, [xSP]
388 push xAX
389 call Bs3SelFlatCodeToRealMode ; well behaved assembly function, only clobbers eax
390 add xSP, 4
391 xchg [xSP], eax
392 %endif
393 call TMPL_NM(Bs3SwitchToRM)
394 BS3_SET_BITS 16
395 retf
396BS3_PROC_END_MODE Bs3SwitchToRM_Safe
397%endif
398
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette