VirtualBox

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

Last change on this file since 60749 was 60749, checked in by vboxsync, 9 years ago

bs3kit: updates

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.2 KB
Line 
1; $Id: bs3-cmn-RegCtxRestore.asm 60749 2016-04-28 19:41:14Z vboxsync $
2;; @file
3; BS3Kit - Bs3RegCtxRestore.
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
29
30BS3_EXTERN_SYSTEM16 Bs3Gdt
31BS3_EXTERN_DATA16 g_bBs3CurrentMode
32%if TMPL_BITS != 64
33BS3_EXTERN_DATA16 g_uBs3CpuDetected
34%endif
35TMPL_BEGIN_TEXT
36BS3_EXTERN_CMN Bs3Syscall
37BS3_EXTERN_CMN Bs3Panic
38TMPL_BEGIN_TEXT
39
40
41;;
42; Restores the given register context.
43;
44; @param pRegCtx
45; @param fFlags
46; @uses All registers and may trash stack immediately before the resume point.
47;
48; @note Only respects the BS3_MODE_CODE_MASK part of pRegCtx->bMode.
49;
50%if TMPL_BITS == 16
51BS3_PROC_BEGIN_CMN Bs3RegCtxRestore_aborts, BS3_PBC_FAR ; special entry point for when watcom applies __aborts
52BS3_PROC_BEGIN_CMN Bs3RegCtxRestore_aborts, BS3_PBC_NEAR ; special entry point for when watcom applies __aborts
53 CPU 8086
54 xor xAX, xAX
55 push xAX ; fake return address.
56 push xAX
57 jmp _Bs3RegCtxRestore_f16
58%elif TMPL_BITS == 32
59BS3_PROC_BEGIN_CMN Bs3RegCtxRestore_aborts, BS3_PBC_NEAR ; special entry point for when watcom applies __aborts
60 push 0feedfaceh ; fake return address.
61%endif
62BS3_PROC_BEGIN_CMN Bs3RegCtxRestore, BS3_PBC_HYBRID
63 BS3_CALL_CONV_PROLOG 2
64 push xBP
65 mov xBP, xSP
66
67 ;
68 ; If we're not in ring-0, ask the kernel to restore it for us (quicker
69 ; and less problematic if we're in a funny context right now with weird
70 ; CS or SS values).
71 ;
72%if TMPL_BITS == 16
73 cmp byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM
74 je .in_ring0
75 test byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86
76 jnz .do_syscall_restore_ctx
77%endif
78 mov ax, ss
79 test al, 3
80 jz .in_ring0
81
82.do_syscall_restore_ctx:
83%if TMPL_BITS != 16
84.do_syscall_restore_ctx_restore_ds:
85 mov cx, ds
86 mov xSI, [xBP + xCB*2]
87 movzx edx, word [xBP + xCB*3]
88 mov eax, BS3_SYSCALL_RESTORE_CTX
89%else
90 mov si, [bp + xCB + cbCurRetAddr]
91 mov cx, [bp + xCB + cbCurRetAddr + 2]
92 mov dx, [bp + xCB + cbCurRetAddr + sCB]
93 mov ax, BS3_SYSCALL_RESTORE_CTX
94%endif
95 call Bs3Syscall
96 call Bs3Panic
97
98%if TMPL_BITS == 16
99.do_syscall_restore_ctx_restore_ds:
100 push es
101 pop ds
102 jmp .do_syscall_restore_ctx
103%endif
104
105 ;
106 ; Prologue. Loads ES with BS3KIT_GRPNM_DATA16/FLAT (for g_bBs3CurrentMode
107 ; and g_uBs3CpuDetected), DS:xBX with pRegCtx and fFlags into xCX.
108 ;
109.in_ring0:
110%if TMPL_BITS == 16
111 mov ax, BS3_SEL_DATA16
112 mov es, ax
113 lds bx, [bp + xCB + cbCurRetAddr]
114 mov cx, [bp + xCB + cbCurRetAddr + sCB]
115%elif TMPL_BITS == 32
116 mov ax, BS3_SEL_R0_DS32
117 mov ds, ax
118 mov xBX, [xBP + xCB*2]
119 movzx xCX, word [xBP + xCB*3]
120%else
121 mov ax, BS3_SEL_R0_DS64
122 mov ds, ax
123 mov xBX, [xBP + xCB*2]
124 movzx xCX, word [xBP + xCB*3]
125%endif
126
127
128%if TMPL_BITS != 64
129 ; Restoring a 64-bit context is best done from 64-bit code.
130 mov al, [xBX + BS3REGCTX.bMode]
131 test al, BS3_MODE_CODE_64
132 jnz .do_syscall_restore_ctx_restore_ds
133%endif
134
135 ; The remainder must be done with interrupts disabled.
136 cli
137
138 ;
139 ; Update g_bs3CurrentMode.
140 ;
141%if TMPL_BITS == 64
142 mov al, [xBX + BS3REGCTX.bMode]
143%endif
144 and al, BS3_MODE_CODE_MASK
145 mov ah, [BS3_ONLY_16BIT(es:) BS3_DATA16_WRT(g_bBs3CurrentMode)]
146 and ah, ~BS3_MODE_CODE_MASK
147 or al, ah
148 mov [BS3_ONLY_16BIT(es:) BS3_DATA16_WRT(g_bBs3CurrentMode)], al
149
150%if TMPL_BITS == 16
151 ;
152 ; Check what the CPU can do.
153 ;
154 cmp byte [es:BS3_DATA16_WRT(g_uBs3CpuDetected)], BS3CPU_80386
155 jae .restore_full
156
157 ; Do the 80286 specifics first.
158 cmp byte [es:BS3_DATA16_WRT(g_uBs3CpuDetected)], BS3CPU_80286
159 jb .restore_16_bit_ancient
160 CPU 286
161
162 lmsw [bx + BS3REGCTX.cr0]
163 cmp byte [es:BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM
164 je .restore_16_bit_ancient
165 lldt [bx + BS3REGCTX.ldtr]
166
167 ; TR - complicated because we need to clear the busy bit. ASSUMES GDT.
168 str ax
169 cmp ax, [bx + BS3REGCTX.tr]
170 je .skip_tr_286
171
172 mov di, word [xBX + BS3REGCTX.tr]
173 or di, di ; check for null.
174 jz .load_tr_286
175
176 push ds
177 push BS3_SEL_SYSTEM16
178 pop ds
179 add di, Bs3Gdt wrt BS3SYSTEM16
180 add di, X86DESCGENERIC_BIT_OFF_TYPE / 8
181 and byte [di], ~(X86_SEL_TYPE_SYS_TSS_BUSY_MASK << (X86DESCGENERIC_BIT_OFF_TYPE % 8))
182 pop ds
183
184.load_tr_286:
185 ltr [bx + BS3REGCTX.tr]
186.skip_tr_286:
187
188.restore_16_bit_ancient:
189 CPU 8086
190 ; Some general registers.
191 mov cx, [bx + BS3REGCTX.rcx]
192 mov dx, [bx + BS3REGCTX.rdx]
193
194 ; Do the return frame and final registers (keep short as we're not quite
195 ; NMI safe here if pRegCtx is on the stack).
196 cmp byte [es:BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM
197 mov di, [bx + BS3REGCTX.rsp]
198 je .restore_16_bit_same_privilege
199 cmp byte [bx + BS3REGCTX.bCpl], 0
200 je .restore_16_bit_same_privilege
201
202 mov ax, [bx + BS3REGCTX.ss]
203 push ax
204 mov ax, [bx + BS3REGCTX.rsp]
205 push ax
206 mov ax, [bx + BS3REGCTX.rflags]
207 push ax
208 mov ax, [bx + BS3REGCTX.cs]
209 push ax
210 mov ax, [bx + BS3REGCTX.rip]
211 push ax
212 mov ax, [bx + BS3REGCTX.ds]
213 push ax
214
215 mov si, [bx + BS3REGCTX.rsi]
216 mov di, [bx + BS3REGCTX.rdi]
217 mov es, [bx + BS3REGCTX.es]
218 mov ax, [bx + BS3REGCTX.rax]
219 mov bp, [bx + BS3REGCTX.rbp] ; restore late for better stacks.
220 mov bx, [bx + BS3REGCTX.rbx]
221
222 pop ds
223 iret
224
225.restore_16_bit_same_privilege:
226 sub di, 2*5 ; iret frame + pop ds
227 mov si, di
228 mov es, [bx + BS3REGCTX.ss] ; ES is target stack segment.
229 cld
230
231 mov ax, [bx + BS3REGCTX.ds]
232 stosw
233 mov ax, [bx + BS3REGCTX.rbp] ; Restore esp as late as possible for better stacks.
234 stosw
235 mov ax, [bx + BS3REGCTX.rip]
236 stosw
237 mov ax, [bx + BS3REGCTX.cs]
238 stosw
239 mov ax, [bx + BS3REGCTX.rflags]
240 stosw
241
242 mov di, [bx + BS3REGCTX.rdi]
243 mov es, [bx + BS3REGCTX.es]
244 mov ax, [bx + BS3REGCTX.rax]
245 mov ss, [bx + BS3REGCTX.ss]
246 mov sp, si
247 mov si, [bx + BS3REGCTX.rsi]
248 mov bx, [bx + BS3REGCTX.rbx]
249
250 pop ds
251 pop bp
252 iret
253
254 CPU 386
255%endif
256
257.restore_full:
258 ;
259 ; 80386 or later.
260 ; For 32-bit and 16-bit versions, we always use 32-bit iret.
261 ;
262
263 ; Restore control registers if they've changed.
264 test cl, BS3TRAPRESUME_F_SKIP_CRX
265 jnz .skip_control_regs
266 test byte [xBX + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_CR0_IS_MSW | BS3REG_CTX_F_NO_CR2_CR3
267 jnz .skip_control_regs
268
269 test byte [xBX + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_CR4 ; (old 486s and 386s didn't have CR4)
270 jnz .skip_cr4
271%if TMPL_BITS != 64
272 test word [BS3_ONLY_16BIT(es:) BS3_DATA16_WRT(g_uBs3CpuDetected)], BS3CPU_F_CPUID
273 jz .skip_cr4
274%endif
275 mov sAX, [xBX + BS3REGCTX.cr4]
276 mov sDX, cr4
277 cmp sAX, sDX
278 je .skip_cr4
279 mov cr4, sAX
280.skip_cr4:
281
282 mov sAX, [xBX + BS3REGCTX.cr0]
283 mov sDX, cr0
284 cmp sAX, sDX
285 je .skip_cr0
286 mov cr0, sAX
287.skip_cr0:
288
289 mov sAX, [xBX + BS3REGCTX.cr3]
290 mov sDX, cr3
291 cmp sAX, sDX
292 je .skip_cr3
293 mov cr3, sAX
294.skip_cr3:
295
296 mov sAX, [xBX + BS3REGCTX.cr2]
297 mov sDX, cr2
298 cmp sAX, sDX
299 je .skip_cr2
300 mov cr2, sAX
301.skip_cr2:
302
303 ;
304 ; Restore
305 ;
306%if TMPL_BITS != 64
307 ; We cannot restore ldtr and tr if we're in real-mode.
308 cmp byte [BS3_ONLY_16BIT(es:) BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM
309 je .skip_control_regs
310%endif
311
312 ; LDTR
313 sldt ax
314 cmp ax, [xBX + BS3REGCTX.ldtr]
315 je .skip_ldtr
316 lldt [xBX + BS3REGCTX.ldtr]
317.skip_ldtr:
318
319 ; TR - complicated because we need to clear the busy bit. ASSUMES GDT.
320 str ax
321 cmp ax, [xBX + BS3REGCTX.tr]
322 je .skip_tr
323
324 movzx edi, word [xBX + BS3REGCTX.tr]
325 or edi, edi ; check for null.
326 jz .load_tr
327
328%if TMPL_BITS == 16
329 push ds
330 push BS3_SEL_SYSTEM16
331 pop ds
332 add xDI, Bs3Gdt wrt BS3SYSTEM16
333%else
334 add xDI, Bs3Gdt wrt FLAT
335%endif
336 add xDI, X86DESCGENERIC_BIT_OFF_TYPE / 8
337 and byte [xDI], ~(X86_SEL_TYPE_SYS_TSS_BUSY_MASK << (X86DESCGENERIC_BIT_OFF_TYPE % 8))
338%if TMPL_BITS == 16
339 pop ds
340%endif
341.load_tr:
342 ltr [xBX + BS3REGCTX.tr]
343.skip_tr:
344
345.skip_control_regs:
346
347
348%if TMPL_BITS == 64
349 ;
350 ; 64-bit returns are simple because ss:rsp are always restored.
351 ;
352 movzx eax, word [xBX + BS3REGCTX.ss]
353 push rax
354 push qword [xBX + BS3REGCTX.rsp]
355 push qword [xBX + BS3REGCTX.rflags]
356 movzx eax, word [xBX + BS3REGCTX.cs]
357 push rax
358 push qword [xBX + BS3REGCTX.rip]
359
360 mov es, [xBX + BS3REGCTX.es]
361 mov fs, [xBX + BS3REGCTX.fs]
362 mov gs, [xBX + BS3REGCTX.gs]
363 mov rax, [xBX + BS3REGCTX.rax]
364 mov rdx, [xBX + BS3REGCTX.rdx]
365 mov rcx, [xBX + BS3REGCTX.rcx]
366 mov rsi, [xBX + BS3REGCTX.rsi]
367 mov rdi, [xBX + BS3REGCTX.rdi]
368 mov r8, [xBX + BS3REGCTX.r8]
369 mov r9, [xBX + BS3REGCTX.r9]
370 mov r10, [xBX + BS3REGCTX.r10]
371 mov r11, [xBX + BS3REGCTX.r11]
372 mov r12, [xBX + BS3REGCTX.r12]
373 mov r13, [xBX + BS3REGCTX.r13]
374 mov r14, [xBX + BS3REGCTX.r14]
375 mov r15, [xBX + BS3REGCTX.r15]
376 mov rbp, [xBX + BS3REGCTX.rbp] ; restore late for better stacks.
377 mov ds, [xBX + BS3REGCTX.ds]
378 mov rbx, [xBX + BS3REGCTX.rbx]
379 iretq
380
381%else
382 ;
383 ; 32-bit/16-bit is more complicated as we have three different iret frames.
384 ;
385 mov al, [BS3_ONLY_16BIT(es:) BS3_DATA16_WRT(g_bBs3CurrentMode)]
386 cmp al, BS3_MODE_RM
387 je .iretd_same_cpl_rm
388
389 test dword [xBX + BS3REGCTX.rflags], X86_EFL_VM
390 jnz .restore_v8086
391
392 cmp byte [xBX + BS3REGCTX.bCpl], 0
393 je .iretd_same_cpl
394
395 ;
396 ; IRETD to different CPL. Frame includes ss:esp.
397 ;
398.iretd_different_cpl:
399 or eax, 0ffffffffh ; poison unused parts of segment pushes
400 mov ax, [xBX + BS3REGCTX.ss]
401 push eax
402 push dword [xBX + BS3REGCTX.rsp]
403 push dword [xBX + BS3REGCTX.rflags]
404 mov ax, [xBX + BS3REGCTX.cs]
405 push eax
406 push dword [xBX + BS3REGCTX.rip]
407 push dword [xBX + BS3REGCTX.rbp] ; Restore esp as late as possible for better stacks.
408 mov ax, [xBX + BS3REGCTX.ds]
409 push xAX
410
411 mov es, [xBX + BS3REGCTX.es]
412 mov fs, [xBX + BS3REGCTX.fs]
413 mov gs, [xBX + BS3REGCTX.gs]
414 mov eax, [xBX + BS3REGCTX.rax]
415 mov edx, [xBX + BS3REGCTX.rdx]
416 mov ecx, [xBX + BS3REGCTX.rcx]
417 mov esi, [xBX + BS3REGCTX.rsi]
418 %if TMPL_BITS == 16 ; if SS is 16-bit, we will not be able to restore the high word.
419 mov edi, [xBX + BS3REGCTX.rsp]
420 mov di, sp
421 mov esp, edi
422 %endif
423 mov edi, [xBX + BS3REGCTX.rdi]
424 mov ebx, [xBX + BS3REGCTX.rbx]
425
426 pop ds
427 pop ebp
428 iretd
429
430 ;
431 ; IRETD to same CPL (includes real mode).
432 ;
433.iretd_same_cpl_rm:
434 ; Use STOSD/ES:EDI to create the frame.
435 mov es, [xBX + BS3REGCTX.ss]
436 mov esi, [xBX + BS3REGCTX.rsp]
437 sub esi, 5*4
438 movzx edi, si
439 jmp .es_edi_is_pointing_to_return_frame_location
440
441.iretd_same_cpl:
442 ; Use STOSD/ES:EDI to create the frame.
443 mov es, [xBX + BS3REGCTX.ss]
444 mov edi, [xBX + BS3REGCTX.rsp]
445 sub edi, 5*4
446
447 ; Which part of the stack pointer is actually used depends on the SS.D/B bit.
448 lar eax, [xBX + BS3REGCTX.ss]
449 jnz .using_32_bit_stack_pointer
450 test eax, X86LAR_F_D
451 jnz .using_32_bit_stack_pointer
452.using_16_bit_stack_pointer:
453 mov esi, edi ; save rsp for later.
454 movzx edi, di
455 jmp .es_edi_is_pointing_to_return_frame_location
456.using_32_bit_stack_pointer:
457 mov esi, edi
458.es_edi_is_pointing_to_return_frame_location:
459 cld
460 mov ax, [xBX + BS3REGCTX.ds]
461 o32 stosd
462 mov eax, [xBX + BS3REGCTX.rbp] ; Restore esp as late as possible for better stacks.
463 o32 stosd
464 mov eax, [xBX + BS3REGCTX.rip]
465 o32 stosd
466 mov ax, [xBX + BS3REGCTX.cs]
467 o32 stosd
468 mov eax, [xBX + BS3REGCTX.rflags]
469 o32 stosd
470
471 mov es, [xBX + BS3REGCTX.es]
472 mov fs, [xBX + BS3REGCTX.fs]
473 mov gs, [xBX + BS3REGCTX.gs]
474 mov eax, [xBX + BS3REGCTX.rax]
475 mov edx, [xBX + BS3REGCTX.rdx]
476 mov ecx, [xBX + BS3REGCTX.rcx]
477 mov edi, [xBX + BS3REGCTX.rdi]
478 mov ebp, [xBX + BS3REGCTX.rbp] ; restore late for better stacks.
479
480 mov ss, [xBX + BS3REGCTX.ss]
481 mov esp, esi
482 mov esi, [xBX + BS3REGCTX.rsi]
483 mov ebx, [xBX + BS3REGCTX.rbx]
484
485 o32 pop ds
486 pop ebp
487 iretd
488
489 ;
490 ; IRETD to v8086 mode. Frame includes ss:esp and the 4 data segment registers.
491 ;
492.restore_v8086:
493 or eax, 0ffffffffh ; poison unused parts of segment pushes
494 mov eax, [xBX + BS3REGCTX.gs]
495 push eax
496 mov eax, [xBX + BS3REGCTX.fs]
497 push eax
498 mov eax, [xBX + BS3REGCTX.ds]
499 push eax
500 mov eax, [xBX + BS3REGCTX.es]
501 push eax
502 mov eax, [xBX + BS3REGCTX.ss]
503 push eax
504 push dword [xBX + BS3REGCTX.rsp]
505 push dword [xBX + BS3REGCTX.rflags]
506 mov ax, [xBX + BS3REGCTX.cs]
507 push eax
508 push dword [xBX + BS3REGCTX.rip]
509
510 mov eax, [xBX + BS3REGCTX.rax]
511 mov edx, [xBX + BS3REGCTX.rdx]
512 mov ecx, [xBX + BS3REGCTX.rcx]
513 mov esi, [xBX + BS3REGCTX.rsi]
514 mov edi, [xBX + BS3REGCTX.rdi]
515 mov ebp, [xBX + BS3REGCTX.rbp] ; restore late for better stacks.
516 mov ebx, [xBX + BS3REGCTX.rbx]
517
518 iretd
519%endif
520BS3_PROC_END_CMN Bs3RegCtxRestore
521
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