VirtualBox

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

Last change on this file since 98103 was 98103, checked in by vboxsync, 20 months ago

Copyright year updates by scm.

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