VirtualBox

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

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

bs3kit: got the weird v8086 w/ 16-bit tss and trap handlers working.

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