VirtualBox

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

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

bs3kit: oops.

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