VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSaveEx.asm@ 78210

Last change on this file since 78210 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.3 KB
Line 
1; $Id: bs3-cmn-RegCtxSaveEx.asm 76553 2019-01-01 01:45:53Z vboxsync $
2;; @file
3; BS3Kit - Bs3RegCtxSaveEx.
4;
5
6;
7; Copyright (C) 2007-2019 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
29
30
31;*********************************************************************************************************************************
32;* External Symbols *
33;*********************************************************************************************************************************
34BS3_EXTERN_DATA16 g_bBs3CurrentMode
35%if ARCH_BITS != 64
36BS3_EXTERN_DATA16 g_uBs3CpuDetected
37%endif
38
39TMPL_BEGIN_TEXT
40BS3_EXTERN_CMN Bs3Panic
41BS3_EXTERN_CMN Bs3RegCtxSave
42BS3_EXTERN_CMN Bs3SwitchTo16Bit
43%if TMPL_BITS != 64
44BS3_EXTERN_CMN Bs3SwitchTo16BitV86
45%endif
46%if TMPL_BITS != 32
47BS3_EXTERN_CMN Bs3SwitchTo32Bit
48%endif
49%if TMPL_BITS != 64
50BS3_EXTERN_CMN Bs3SwitchTo64Bit
51%endif
52%if TMPL_BITS == 16
53BS3_EXTERN_CMN Bs3SelRealModeDataToProtFar16
54BS3_EXTERN_CMN Bs3SelProtFar16DataToRealMode
55BS3_EXTERN_CMN Bs3SelRealModeDataToFlat
56BS3_EXTERN_CMN Bs3SelProtFar16DataToFlat
57%else
58BS3_EXTERN_CMN Bs3SelFlatDataToProtFar16
59%endif
60%if TMPL_BITS == 32
61BS3_EXTERN_CMN Bs3SelFlatDataToRealMode
62%endif
63
64BS3_BEGIN_TEXT16
65%if TMPL_BITS != 16
66extern _Bs3RegCtxSave_c16
67extern _Bs3SwitchTo%[TMPL_BITS]Bit_c16
68%endif
69
70BS3_BEGIN_TEXT32
71%if TMPL_BITS != 32
72extern _Bs3RegCtxSave_c32
73extern _Bs3SwitchTo%[TMPL_BITS]Bit_c32
74%endif
75%if TMPL_BITS == 16
76extern _Bs3SwitchTo16BitV86_c32
77%endif
78
79BS3_BEGIN_TEXT64
80%if TMPL_BITS != 64
81extern _Bs3RegCtxSave_c64
82extern _Bs3SwitchTo%[TMPL_BITS]Bit_c64
83%endif
84
85TMPL_BEGIN_TEXT
86
87
88
89;;
90; Saves the current register context.
91;
92; @param pRegCtx
93; @param bBitMode (8)
94; @param cbExtraStack (16)
95; @uses xAX, xDX, xCX
96;
97BS3_PROC_BEGIN_CMN Bs3RegCtxSaveEx, BS3_PBC_NEAR ; Far stub generated by the makefile/bs3kit.h.
98TONLY16 CPU 8086
99 BS3_CALL_CONV_PROLOG 3
100 push xBP
101 mov xBP, xSP
102%if ARCH_BITS == 64
103 push rcx ; Save pRegCtx
104%endif
105
106 ;
107 ; Get the CPU bitcount part of the current mode.
108 ;
109 mov dl, [BS3_DATA16_WRT(g_bBs3CurrentMode)]
110 and dl, BS3_MODE_CODE_MASK
111%if TMPL_BITS == 16
112 push dx ; bp - 2: previous CPU mode (16-bit)
113%endif
114
115 ;
116 ; Reserve extra stack space. Make sure we've got 20h here in case we
117 ; are saving a 64-bit context.
118 ;
119TONLY16 mov ax, [xBP + xCB + cbCurRetAddr + sCB + xCB]
120TNOT16 movzx eax, word [xBP + xCB + cbCurRetAddr + sCB + xCB]
121%ifdef BS3_STRICT
122 cmp xAX, 4096
123 jb .extra_stack_ok
124 call Bs3Panic
125.extra_stack_ok:
126%endif
127 cmp xAX, 20h
128 jae .at_least_20h_extra_stack
129 add xAX, 20h
130.at_least_20h_extra_stack:
131 sub xSP, xAX
132
133 ;
134 ; Are we just saving the mode we're already in?
135 ;
136 mov al, [xBP + xCB + cbCurRetAddr + sCB]
137 and al, BS3_MODE_CODE_MASK
138 cmp dl, al
139 jne .not_the_same_mode
140
141%if TMPL_BITS == 16
142 push word [xBP + xCB + cbCurRetAddr + 2]
143 push word [xBP + xCB + cbCurRetAddr]
144%elif TMPL_BITS == 32
145 push dword [xBP + xCB + cbCurRetAddr]
146%endif
147 call Bs3RegCtxSave ; 64-bit: rcx is untouched thus far.
148
149
150 ;
151 ; Return - no need to pop xAX and xDX as the last two
152 ; operations preserves all registers.
153 ;
154.return:
155 mov xSP, xBP
156 pop xBP
157 BS3_CALL_CONV_EPILOG 3
158 BS3_HYBRID_RET
159
160 ;
161 ; Turns out we have to do switch to a different bitcount before saving.
162 ;
163.not_the_same_mode:
164 cmp al, BS3_MODE_CODE_16
165 je .code_16
166
167TONLY16 CPU 386
168%if TMPL_BITS != 32
169 cmp al, BS3_MODE_CODE_32
170 je .code_32
171%endif
172%if TMPL_BITS != 64
173 cmp al, BS3_MODE_CODE_V86
174 je .code_v86
175 cmp al, BS3_MODE_CODE_64
176 jne .bad_input_mode
177 jmp .code_64
178%endif
179
180 ; Bad input (al=input, dl=current).
181.bad_input_mode:
182 call Bs3Panic
183
184
185 ;
186 ; Save a 16-bit context.
187 ;
188 ; Convert pRegCtx to 16:16 protected mode and make sure we're in the
189 ; 16-bit code segment.
190 ;
191.code_16:
192%if TMPL_BITS == 16
193 %ifdef BS3_STRICT
194 cmp dl, BS3_MODE_CODE_V86
195 jne .bad_input_mode
196 %endif
197 push word [xBP + xCB + cbCurRetAddr + 2]
198 push word [xBP + xCB + cbCurRetAddr]
199 call Bs3SelRealModeDataToProtFar16
200 add sp, 4h
201 push dx ; Parameter #0 for _Bs3RegCtxSave_c16
202 push ax
203%else
204 %if TMPL_BITS == 32
205 push dword [xBP + xCB + cbCurRetAddr]
206 %endif
207 call Bs3SelFlatDataToProtFar16 ; 64-bit: BS3_CALL not needed, ecx not touched thus far.
208 mov [xSP], eax ; Parameter #0 for _Bs3RegCtxSave_c16
209 jmp .code_16_safe_segment
210 BS3_BEGIN_TEXT16
211 BS3_SET_BITS TMPL_BITS
212.code_16_safe_segment:
213%endif
214 call Bs3SwitchTo16Bit
215 BS3_SET_BITS 16
216
217 call _Bs3RegCtxSave_c16
218
219%if TMPL_BITS == 16
220 call _Bs3SwitchTo16BitV86_c16
221%else
222 call _Bs3SwitchTo%[TMPL_BITS]Bit_c16
223%endif
224 BS3_SET_BITS TMPL_BITS
225 jmp .supplement_and_return
226 TMPL_BEGIN_TEXT
227
228TONLY16 CPU 386
229
230
231%if TMPL_BITS != 64
232 ;
233 ; Save a v8086 context.
234 ;
235.code_v86:
236 %if TMPL_BITS == 16
237 %ifdef BS3_STRICT
238 cmp dl, BS3_MODE_CODE_16
239 jne .bad_input_mode
240 %endif
241 push word [xBP + xCB + cbCurRetAddr + 2]
242 push word [xBP + xCB + cbCurRetAddr]
243 call Bs3SelProtFar16DataToRealMode
244 add sp, 4h
245 push dx ; Parameter #0 for _Bs3RegCtxSave_c16
246 push ax
247 %else
248 push dword [xBP + xCB + cbCurRetAddr]
249 call Bs3SelFlatDataToRealMode
250 mov [xSP], eax ; Parameter #0 for _Bs3RegCtxSave_c16
251 jmp .code_v86_safe_segment
252 BS3_BEGIN_TEXT16
253 BS3_SET_BITS TMPL_BITS
254.code_v86_safe_segment:
255 %endif
256 call Bs3SwitchTo16BitV86
257 BS3_SET_BITS 16
258
259 call _Bs3RegCtxSave_c16
260
261 call _Bs3SwitchTo%[TMPL_BITS]Bit_c16
262 BS3_SET_BITS TMPL_BITS
263 jmp .supplement_and_return
264TMPL_BEGIN_TEXT
265%endif
266
267
268%if TMPL_BITS != 32
269 ;
270 ; Save a 32-bit context.
271 ;
272.code_32:
273 %if TMPL_BITS == 16
274 push word [xBP + xCB + cbCurRetAddr + 2]
275 push word [xBP + xCB + cbCurRetAddr]
276 test dl, BS3_MODE_CODE_V86
277 jnz .code_32_from_v86
278 call Bs3SelProtFar16DataToFlat
279 jmp .code_32_flat_ptr
280.code_32_from_v86:
281 call Bs3SelRealModeDataToFlat
282.code_32_flat_ptr:
283 add sp, 4h
284 push dx ; Parameter #0 for _Bs3RegCtxSave_c32
285 push ax
286 %else
287 mov [rsp], ecx ; Parameter #0 for _Bs3RegCtxSave_c16
288 %endif
289 call Bs3SwitchTo32Bit
290 BS3_SET_BITS 32
291
292 call _Bs3RegCtxSave_c32
293
294 %if TMPL_BITS == 16
295 cmp byte [bp - 2], BS3_MODE_CODE_V86
296 je .code_32_back_to_v86
297 call _Bs3SwitchTo16Bit_c32
298 BS3_SET_BITS TMPL_BITS
299 jmp .supplement_and_return
300.code_32_back_to_v86:
301 BS3_SET_BITS 32
302 call _Bs3SwitchTo16BitV86_c32
303 BS3_SET_BITS TMPL_BITS
304 jmp .return
305 %else
306 call _Bs3SwitchTo64Bit_c32
307 BS3_SET_BITS TMPL_BITS
308 jmp .supplement_and_return
309 %endif
310%endif
311
312
313%if TMPL_BITS != 64
314 ;
315 ; Save a 64-bit context.
316 ;
317 CPU x86-64
318.code_64:
319 %if TMPL_BITS == 16
320 %ifdef BS3_STRICT
321 cmp dl, BS3_MODE_CODE_16
322 jne .bad_input_mode
323 %endif
324 push word [xBP + xCB + cbCurRetAddr + 2]
325 push word [xBP + xCB + cbCurRetAddr]
326 call Bs3SelProtFar16DataToFlat
327 add sp, 4h
328 mov cx, dx ; Parameter #0 for _Bs3RegCtxSave_c64
329 shl ecx, 16
330 mov cx, ax
331 %else
332 mov ecx, [xBP + xCB + cbCurRetAddr] ; Parameter #0 for _Bs3RegCtxSave_c64
333 %endif
334 call Bs3SwitchTo64Bit ; (preserves all 32-bit GPRs)
335 BS3_SET_BITS 64
336
337 call _Bs3RegCtxSave_c64 ; No BS3_CALL as rcx is already ready.
338
339 call _Bs3SwitchTo%[TMPL_BITS]Bit_c64
340 BS3_SET_BITS TMPL_BITS
341 jmp .return
342%endif
343
344
345 ;
346 ; Supplement the state out of the current context and then return.
347 ;
348.supplement_and_return:
349%if ARCH_BITS == 16
350 CPU 8086
351 ; Skip 286 and older. Also make 101% sure we not in real mode or v8086 mode.
352 cmp byte [BS3_DATA16_WRT(g_uBs3CpuDetected)], BS3CPU_80386
353 jb .return ; Just skip if 286 or older.
354 test byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86
355 jnz .return
356 cmp byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM
357 jne .return ; paranoia
358 CPU 386
359%endif
360
361 ; Load the context pointer into a suitable register.
362%if ARCH_BITS == 64
363 %define pRegCtx rcx
364 mov rcx, [xBP - xCB]
365%elif ARCH_BITS == 32
366 %define pRegCtx ecx
367 mov ecx, [xBP + xCB + cbCurRetAddr]
368%else
369 %define pRegCtx es:bx
370 push es
371 push bx
372 les bx, [xBP + xCB + cbCurRetAddr]
373%endif
374%if ARCH_BITS == 64
375 ; If we're in 64-bit mode we can capture and restore the high bits.
376 test byte [pRegCtx + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_AMD64
377 jz .supplemented_64bit_registers
378 mov [pRegCtx + BS3REGCTX.r8], r8
379 mov [pRegCtx + BS3REGCTX.r9], r9
380 mov [pRegCtx + BS3REGCTX.r10], r10
381 mov [pRegCtx + BS3REGCTX.r11], r11
382 mov [pRegCtx + BS3REGCTX.r12], r12
383 mov [pRegCtx + BS3REGCTX.r13], r13
384 mov [pRegCtx + BS3REGCTX.r14], r14
385 mov [pRegCtx + BS3REGCTX.r15], r15
386 shr rax, 32
387 mov [pRegCtx + BS3REGCTX.rax + 4], eax
388 mov rax, rbx
389 shr rax, 32
390 mov [pRegCtx + BS3REGCTX.rbx + 4], eax
391 mov rax, rcx
392 shr rax, 32
393 mov [pRegCtx + BS3REGCTX.rcx + 4], eax
394 mov rax, rdx
395 shr rax, 32
396 mov [pRegCtx + BS3REGCTX.rdx + 4], eax
397 mov rax, rsp
398 shr rax, 32
399 mov [pRegCtx + BS3REGCTX.rsp + 4], eax
400 mov rax, rbp
401 shr rax, 32
402 mov [pRegCtx + BS3REGCTX.rbp + 4], eax
403 mov rax, rsi
404 shr rax, 32
405 mov [pRegCtx + BS3REGCTX.rsi + 4], eax
406 mov rax, rdi
407 shr rax, 32
408 mov [pRegCtx + BS3REGCTX.rdi + 4], eax
409 and byte [pRegCtx + BS3REGCTX.fbFlags], ~BS3REG_CTX_F_NO_AMD64
410.supplemented_64bit_registers:
411%endif
412 ; The rest requires ring-0 (at least during restore).
413 mov ax, ss
414 test ax, 3
415 jnz .done_supplementing
416
417 ; Do control registers.
418 test byte [pRegCtx + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_CR2_CR3 | BS3REG_CTX_F_NO_CR0_IS_MSW | BS3REG_CTX_F_NO_CR4
419 jz .supplemented_control_registers
420 mov sAX, cr0
421 mov [pRegCtx + BS3REGCTX.cr0], sAX
422 mov sAX, cr2
423 mov [pRegCtx + BS3REGCTX.cr2], sAX
424 mov sAX, cr3
425 mov [pRegCtx + BS3REGCTX.cr3], sAX
426 and byte [pRegCtx + BS3REGCTX.fbFlags], ~(BS3REG_CTX_F_NO_CR2_CR3 | BS3REG_CTX_F_NO_CR0_IS_MSW)
427
428%if ARCH_BITS != 64
429 test byte [1 + BS3_DATA16_WRT(g_uBs3CpuDetected)], (BS3CPU_F_CPUID >> 8)
430 jz .supplemented_control_registers
431%endif
432 mov sAX, cr4
433 mov [pRegCtx + BS3REGCTX.cr4], sAX
434 and byte [pRegCtx + BS3REGCTX.fbFlags], ~BS3REG_CTX_F_NO_CR4
435.supplemented_control_registers:
436
437 ; Supply tr and ldtr if necessary
438 test byte [pRegCtx + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_TR_LDTR
439 jz .done_supplementing
440 str [pRegCtx + BS3REGCTX.tr]
441 sldt [pRegCtx + BS3REGCTX.ldtr]
442 and byte [pRegCtx + BS3REGCTX.fbFlags], ~BS3REG_CTX_F_NO_TR_LDTR
443
444.done_supplementing:
445TONLY16 pop bx
446TONLY16 pop es
447 jmp .return
448%undef pRegCtx
449BS3_PROC_END_CMN Bs3RegCtxSaveEx
450
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