VirtualBox

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

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