VirtualBox

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

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

bs3kit: A bunch of changes to be able to test the effects of a GDT page being read-only or not-present.

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