VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TrapSystemCallHandler.asm@ 77922

Last change on this file since 77922 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 28.8 KB
Line 
1; $Id: bs3-mode-TrapSystemCallHandler.asm 76553 2019-01-01 01:45:53Z vboxsync $
2;; @file
3; BS3Kit - System call trap handler.
4;
5
6;
7; Copyright (C) 2007-2019 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;*********************************************************************************************************************************
28;* Header Files *
29;*********************************************************************************************************************************
30%include "bs3kit-template-header.mac"
31
32
33;*********************************************************************************************************************************
34;* External Symbols *
35;*********************************************************************************************************************************
36BS3_EXTERN_DATA16 g_bBs3CurrentMode
37%if TMPL_BITS != 64
38BS3_EXTERN_DATA16 g_uBs3CpuDetected
39%endif
40%if TMPL_BITS == 16
41BS3_EXTERN_DATA16 g_uBs3TrapEipHint
42%endif
43TMPL_BEGIN_TEXT
44
45BS3_EXTERN_CMN Bs3SelProtFar32ToFlat32
46BS3_EXTERN_CMN Bs3RegCtxConvertToRingX
47BS3_EXTERN_CMN Bs3RegCtxRestore
48BS3_EXTERN_CMN Bs3Panic
49
50BS3_BEGIN_TEXT16
51extern Bs3PrintStrN_c16_CX_Bytes_At_DS_SI
52TMPL_BEGIN_TEXT
53
54
55;;
56; System call handler.
57;
58; This is an assembly trap handler that is called in response to a system call
59; request from 'user' code. The only fixed parameter is [ER]AX which contains
60; the system call number. Other registers are assigned on a per system call
61; basis, ditto for which registers are preserved and which are used to return
62; stuff. Generally, though, we preserve all registers not used as return
63; values or otherwise implicitly transformed by the call.
64;
65; Note! The 16-bit versions of this code must be careful with using extended
66; registers as we wish this code to work on real 80286 (maybe even 8086)
67; CPUs too!
68;
69BS3_PROC_BEGIN_MODE Bs3TrapSystemCallHandler, BS3_PBC_NEAR ; Near because we'll probably only ever need this from CGROUP16.
70 ;
71 ; This prologue is kind of complicated because of 80286 and older CPUs
72 ; as well as different requirements for 64-bit and the other modes.
73 ;
74%define VAR_CALLER_BP [xBP]
75%if TMPL_BITS != 64
76 %define VAR_CALLER_DS [xBP - xCB]
77%endif
78%define VAR_CALLER_BX [xBP - sCB*1 - xCB] ; Note! the upper word is not clean on pre-386 (16-bit mode).
79%define VAR_CALLER_AX [xBP - sCB*2 - xCB]
80%define VAR_CALLER_CX [xBP - sCB*3 - xCB]
81%define VAR_CALLER_DX [xBP - sCB*4 - xCB]
82%define VAR_CALLER_SI [xBP - sCB*5 - xCB]
83%define VAR_CALLER_SI_HI [xBP - sCB*5 - xCB + 2]
84%define VAR_CALLER_DI [xBP - sCB*6 - xCB]
85%define VAR_CALLER_DI_HI [xBP - sCB*6 - xCB + 2]
86%if TMPL_BITS == 16
87 %define VAR_CALLER_EBP [xBP - sCB*7 - xCB]
88 %define VAR_CALLER_ESP [xBP - sCB*8 - xCB]
89 %define VAR_CALLER_EFLAGS [xBP - sCB*9 - xCB]
90 %define VAR_CALLER_MODE [xBP - sCB*9 - xCB*2]
91 %define BP_TOP_STACK_EXPR xBP - sCB*9 - xCB*2
92%else
93 %define VAR_CALLER_MODE [xBP - sCB*6 - xCB*2]
94 %define BP_TOP_STACK_EXPR xBP - sCB*6 - xCB*2
95%endif
96 push xBP
97 mov xBP, xSP
98%if TMPL_BITS == 64
99 push 0
100 mov [rsp+2], es
101 mov [rsp], ds
102%else
103 push ds
104 %ifdef TMPL_CMN_R86
105 push BS3_SEL_DATA16
106 %else
107 push RT_CONCAT(BS3_SEL_R0_DS,TMPL_BITS)
108 %endif
109 pop ds ; DS = BS3KIT_GRPNM_DATA16 or FLAT and we can safely access data
110 %if TMPL_BITS == 16 && (TMPL_MODE == BS3_MODE_RM || TMPL_MODE == BS3_MODE_PE16)
111 cmp byte [BS3_DATA16_WRT(g_uBs3CpuDetected)], BS3CPU_80286
112 jbe .prologue_pre_80386
113 %endif
114%endif
115 push sBX
116 push sAX
117 push sCX
118 push sDX
119 push sSI
120 push sDI
121%if TMPL_BITS == 16
122 push ebp
123 push esp
124 pushfd
125 %if TMPL_MODE == BS3_MODE_RM || TMPL_MODE == BS3_MODE_PE16
126 jmp .prologue_end
127
128.prologue_pre_80386:
129 push bx ; dummy
130 push bx
131 xor bx, bx
132 push bx ; dummy
133 push ax
134 push bx ; dummy
135 push cx
136 push bx ; dummy
137 push dx
138 push bx ; dummy
139 push si
140 push bx ; dummy
141 push di
142 sub sp, 0ch ; dummy
143 %endif
144%endif
145.prologue_end:
146
147 ;
148 ; VAR_CALLER_MODE: Save the current mode (important for v8086 with 16-bit kernel).
149 ;
150 xor xBX, xBX
151 mov bl, [BS3_DATA16_WRT(g_bBs3CurrentMode)]
152 push xBX
153
154 ;
155 ; Dispatch the system call.
156 ;
157 cmp ax, BS3_SYSCALL_LAST
158 ja .invalid_syscall
159%if TMPL_BITS == 16
160 mov bx, ax
161 shl bx, 1
162 jmp word [cs:.aoffSyscallHandlers + bx]
163%else
164 movzx ebx, ax
165 mov ebx, [.aoffSyscallHandlers + ebx * 4]
166 jmp xBX
167%endif
168.aoffSyscallHandlers:
169%ifdef TMPL_16BIT
170 dw .invalid_syscall wrt CGROUP16
171 dw .print_chr wrt CGROUP16
172 dw .print_str wrt CGROUP16
173 dw .to_ringX wrt CGROUP16
174 dw .to_ringX wrt CGROUP16
175 dw .to_ringX wrt CGROUP16
176 dw .to_ringX wrt CGROUP16
177 dw .restore_ctx wrt CGROUP16
178%else
179 dd .invalid_syscall wrt FLAT
180 dd .print_chr wrt FLAT
181 dd .print_str wrt FLAT
182 dd .to_ringX wrt FLAT
183 dd .to_ringX wrt FLAT
184 dd .to_ringX wrt FLAT
185 dd .to_ringX wrt FLAT
186 dd .restore_ctx wrt FLAT
187%endif
188
189 ;
190 ; Invalid system call.
191 ;
192.invalid_syscall:
193 int3
194 jmp .return
195
196 ;
197 ; Print char in the CL register.
198 ;
199 ; We use the vga bios teletype interrupt to do the writing, so we must
200 ; be in some kind of real mode for this to work. 16-bit code segment
201 ; requried for the mode switching code.
202 ;
203BS3_BEGIN_TEXT16
204 BS3_SET_BITS TMPL_BITS
205.print_chr:
206%if TMPL_BITS != 64
207 push es
208 mov di, ss ; Must save and restore SS for supporting 16/32 and 32/16 caller/kernel ring-0 combinations.
209%endif
210%ifndef TMPL_CMN_R86
211 ; Switch to real mode (20h param scratch area not required).
212 extern TMPL_NM(Bs3SwitchToRM)
213 call TMPL_NM(Bs3SwitchToRM)
214 BS3_SET_BITS 16
215%endif
216
217 ; Print the character, turning '\n' into '\r\n'.
218 cmp cl, 0ah ; \n
219 je .print_chr_newline
220 mov ah, 0eh
221 mov al, cl
222 mov bx, 0ff00h
223 int 10h
224 jmp .print_chr_done
225
226.print_chr_newline:
227 mov ax, 0e0dh ; cmd + \r
228 mov bx, 0ff00h
229 int 10h
230 mov ax, 0e0ah ; cmd + \n
231 mov bx, 0ff00h
232 int 10h
233
234.print_chr_done:
235%ifndef TMPL_CMN_R86
236 ; Switch back (20h param scratch area not required).
237 extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_rm)
238 call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_rm)
239 BS3_SET_BITS TMPL_BITS
240%endif
241%if TMPL_BITS != 64
242 mov ss, di
243 pop es
244%endif
245 jmp .return
246TMPL_BEGIN_TEXT
247
248
249 ;
250 ; Prints DX chars from the string pointed to by CX:xSI to the screen.
251 ;
252 ; We use the vga bios teletype interrupt to do the writing, so we must
253 ; be in some kind of real mode for this to work. The string must be
254 ; accessible from real mode too.
255 ;
256.print_str:
257%if TMPL_BITS != 64
258 push es
259%endif
260 ; Convert the incoming pointer to real mode (assuming caller checked
261 ; that real mode can access it).
262 call .convert_ptr_arg_to_real_mode_ax_si
263 mov cx, VAR_CALLER_DX
264
265 ; Switch to real mode (no 20h scratch required)
266%ifndef TMPL_CMN_R86
267 %if TMPL_BITS != 16
268 jmp .print_str_to_16bit
269BS3_BEGIN_TEXT16
270.print_str_to_16bit:
271 BS3_SET_BITS TMPL_BITS
272 %endif
273 extern TMPL_NM(Bs3SwitchToRM)
274 call TMPL_NM(Bs3SwitchToRM)
275 BS3_SET_BITS 16
276%endif
277 ; Call code in Bs3PrintStrN to do the work.
278 mov ds, ax
279 call Bs3PrintStrN_c16_CX_Bytes_At_DS_SI
280
281 ; Switch back (20h param scratch area not required).
282%ifndef TMPL_CMN_R86
283 extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_rm)
284 call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_rm)
285 %if TMPL_BITS != 16
286 BS3_SET_BITS TMPL_BITS
287 jmp .print_str_end
288TMPL_BEGIN_TEXT
289 %endif
290.print_str_end:
291%endif
292%if TMPL_BITS != 64
293 pop es
294%endif
295 jmp .return
296
297
298 ;
299 ; Switch the caller to ring-0, ring-1, ring-2 or ring-3.
300 ;
301 ; This implement this by saving the entire register context, calling
302 ; a transformation function (C) and restoring the modified register
303 ; context using a generic worker.
304 ;
305.to_ringX:
306 sub xSP, BS3REGCTX_size
307 mov xBX, xSP ; xBP = BS3REGCTX pointer.
308 call .save_context
309
310%if TMPL_BITS == 32
311 ; Convert xBP to flat pointer in 32-bit
312 push ss
313 push xBX
314 call Bs3SelProtFar32ToFlat32
315 add sSP, 8
316 mov xBX, xAX
317%endif
318 push xBX ; Save pointer for the final restore call.
319
320 ; Convert the register context from whatever it is to ring-0.
321BONLY64 sub rsp, 10h
322 mov ax, VAR_CALLER_AX
323 sub ax, BS3_SYSCALL_TO_RING0
324 push xAX
325BONLY16 push ss
326 push xBX
327 BS3_CALL Bs3RegCtxConvertToRingX, 2
328 add xSP, sCB + xCB BS3_ONLY_64BIT(+ 10h)
329
330 ; Restore the register context (does not return).
331 pop xBX ; restore saved pointer.
332BONLY64 sub rsp, 18h
333BONLY16 push ss
334 push xBX
335 BS3_CALL Bs3RegCtxRestore, 1
336 jmp Bs3Panic
337
338
339 ;
340 ; Restore context pointed to by cx:xSI.
341 ;
342.restore_ctx:
343 call .convert_ptr_arg_to_cx_xSI
344BONLY64 sub rsp, 10h
345 mov xDX, VAR_CALLER_DX
346 push xDX
347BONLY16 push cx
348 push xSI
349 BS3_CALL Bs3RegCtxRestore, 2
350 jmp Bs3Panic
351
352 ;
353 ; Return.
354 ;
355.return:
356 pop xBX ; saved mode
357 mov [BS3_DATA16_WRT(g_bBs3CurrentMode)], bl
358%if TMPL_BITS == 16
359 and bl, BS3_MODE_CODE_MASK
360 cmp bl, BS3_MODE_CODE_V86
361 je .return_to_v8086_from_16bit_krnl
362 cmp bl, BS3_MODE_CODE_32
363 je .return_to_32bit_from_16bit_krnl
364 %if TMPL_MODE == BS3_MODE_RM || TMPL_MODE == BS3_MODE_PE16
365 cmp byte [BS3_DATA16_WRT(g_uBs3CpuDetected)], BS3CPU_80286
366 jbe .return_pre_80386
367 %endif
368
369 popfd
370 pop esp
371 pop ebp
372%endif
373 pop sDI
374 pop sSI
375 pop sDX
376 pop sCX
377 pop sAX
378 pop sBX
379%if TMPL_BITS != 64
380 pop ds
381 leave
382 iret
383%else
384 mov es, [rsp+2]
385 mov ds, [rsp]
386 leave ; skips ds
387 iretq
388%endif
389
390%if TMPL_BITS == 16
391 %if TMPL_MODE == BS3_MODE_RM || TMPL_MODE == BS3_MODE_PE16
392 ; Variant of the above for 80286 and older.
393.return_pre_80386:
394 add sp, 0ch
395 pop di
396 pop bx ; dummy
397 pop si
398 pop bx ; dummy
399 pop dx
400 pop bx ; dummy
401 pop cx
402 pop bx ; dummy
403 pop ax
404 pop bx ; dummy
405 pop bx ; pushed twice
406 pop bx
407 pop ds
408 pop bp
409 iret
410 %endif
411
412.return_to_v8086_from_16bit_krnl:
413 int3
414 jmp .return_to_v8086_from_16bit_krnl
415
416 ;
417 ; Returning to 32-bit code may require us to expand and seed the eip
418 ; and esp addresses in the iret frame since these are truncated when
419 ; using a 16-bit interrupt handler.
420 ;
421 ; Incoming stack: New stack diff cpl:
422 ; bp + 0ah: [ss]
423 ; bp + 08h: [sp] bx + 38h: [ss] New stack same cpl:
424 ; bp + 06h: flags
425 ; bp + 04h: cs bx + 34h: [esp] bx + 30h: eflags
426 ; bp + 02h: ip
427 ; -------------- bx + 30h: eflags bx + 2ch: cs
428 ; bp + 00h: bp
429 ; bp - 02h: ds bx + 2ch: cs bx + 28h: eip
430 ; -------------
431 ; bp - 06h: ebx bx + 28h: eip bx + 26h: bp
432 ; -------------- bx + 24h: ds
433 ; bp - 0ah: eax bx + 26h: bp
434 ; bx + 24h: ds bx + 20h: ebx
435 ; bp - 0eh: ecx
436 ; bx + 20h: ebx bx + 1ch: eax
437 ; bp - 12h: edx
438 ; bx + 1ch: eax bx + 18h: ecx
439 ; bp - 16h: esi
440 ; bx + 18h: ecx bx + 14h: edx
441 ; bp - 1ah: edi
442 ; bx + 14h: edx bx + 10h: esi
443 ; bp - 1eh: esp
444 ; bx + 10h: esi bx + 0ch: edi
445 ; bp - 22h: ebp
446 ; bx + 0ch: edi bx + 08h: esp
447 ; bp - 26h: eflags
448 ; bx + 08h: esp bx + 04h: ebp
449 ;
450 ; bx + 04h: ebp bx + 00h: eflags
451 ;
452 ; bx + 00h: eflags
453 ;
454 ;
455 ; If we're returning to the same CPL, we're still using the stack of
456 ; the 32-bit caller. The high ESP word does not need restoring.
457 ;
458 ; If we're returning to a lower CPL, there on a 16-bit ring-0 stack,
459 ; however, the high ESP word is still that of the caller.
460 ;
461.return_to_32bit_from_16bit_krnl:
462 mov ax, cs
463 and al, 3
464 mov ah, 3
465 and ah, [xBP + xCB*2]
466 ; The iret frame doubles in size, so allocate more stack.
467 cmp al, ah
468 je .return_to_32bit_from_16bit_krnl_same_cpl_sub_sp
469 sub sp, 2*2
470.return_to_32bit_from_16bit_krnl_same_cpl_sub_sp:
471 sub sp, 3*2
472 mov bx, sp
473 ; Copy the saved registers.
474 xor di, di
475.return_to_32bit_from_16bit_krnl_copy_loop:
476 mov ecx, [bp + di - 26h]
477 mov [ss:bx + di], ecx
478 add di, 4
479 cmp di, 28h
480 jb .return_to_32bit_from_16bit_krnl_copy_loop
481 ; Convert the 16-bit iret frame to a 32-bit iret frame.
482 mov ecx, [BS3_DATA16_WRT(g_uBs3TrapEipHint)]
483 mov cx, [bp + 02h] ; ip
484 mov [ss:bx + 28h], ecx
485 mov ecx, 0f00d0000h
486 mov cx, [bp + 04h] ; cs
487 mov [ss:bx + 2ch], ecx
488 mov ecx, [ss:bx] ; caller eflags
489 mov cx, [bp + 06h] ; flags
490 mov [ss:bx + 30h], ecx
491 cmp al, ah
492 jz .return_to_32bit_from_16bit_krnl_do_return
493 mov ecx, [ss:bx + 08h] ; caller esp
494 mov cx, [bp + 08h] ; sp
495 mov [ss:bx + 34h], ecx
496 mov ecx, 0f00d0000h
497 mov cx, [bp + 0ah] ; ss
498 mov [ss:bx + 38h], ecx
499.return_to_32bit_from_16bit_krnl_do_return:
500 popfd
501 pop ecx ; esp - only the high bits!
502 mov cx, sp
503 mov esp, ecx
504 pop ebp
505 lea bp, [bx + 26h]
506 pop edi
507 pop esi
508 pop edx
509 pop ecx
510 pop eax
511 pop ebx
512 pop ds
513 leave
514 iretd
515
516%endif ; 16-bit
517
518
519 ;
520 ; Internal function. ss:xBX = Pointer to register frame (BS3REGCTX).
521 ; @uses xAX
522 ;
523.save_context:
524%if TMPL_BITS == 16
525 cmp byte [BS3_DATA16_WRT(g_uBs3CpuDetected)], BS3CPU_80386
526 jae .save_context_full
527
528 ;
529 ; 80286 or earlier.
530 ;
531
532 ; Clear the state area first.
533 push di
534 xor di, di
535.save_context_16_clear_loop:
536 mov word [ss:bx + di], 0
537 mov word [ss:bx + di + 2], 0
538 mov word [ss:bx + di + 4], 0
539 mov word [ss:bx + di + 6], 0
540 add di, 8
541 cmp di, BS3REGCTX_size
542 jb .save_context_16_clear_loop
543 pop di
544
545 ; Do the 8086/80186/80286 state saving.
546 mov ax, VAR_CALLER_AX
547 mov [ss:bx + BS3REGCTX.rax], ax
548 mov cx, VAR_CALLER_CX
549 mov [ss:bx + BS3REGCTX.rcx], ax
550 mov ax, VAR_CALLER_DX
551 mov [ss:bx + BS3REGCTX.rdx], ax
552 mov ax, VAR_CALLER_BX
553 mov [ss:bx + BS3REGCTX.rbx], ax
554 mov [ss:bx + BS3REGCTX.rsi], si
555 mov [ss:bx + BS3REGCTX.rdi], di
556 mov ax, VAR_CALLER_BP
557 mov [ss:bx + BS3REGCTX.rbp], ax
558 mov ax, VAR_CALLER_DS
559 mov [ss:bx + BS3REGCTX.ds], ax
560 mov [ss:bx + BS3REGCTX.es], es
561 mov ax, [xBP + xCB]
562 mov [ss:bx + BS3REGCTX.rip], ax
563 mov ax, [xBP + xCB*2]
564 mov [ss:bx + BS3REGCTX.cs], ax
565 and al, X86_SEL_RPL
566 mov [ss:bx + BS3REGCTX.bCpl], al
567 cmp al, 0
568 je .save_context_16_same
569 mov ax, [xBP + xCB*4]
570 mov [ss:bx + BS3REGCTX.rsp], ax
571 mov ax, [xBP + xCB*5]
572 mov [ss:bx + BS3REGCTX.ss], ax
573 jmp .save_context_16_done_stack
574.save_context_16_same:
575 mov ax, bp
576 add ax, xCB * (1 + 3)
577 mov [ss:bx + BS3REGCTX.rsp], ax
578 mov ax, ss
579 mov [ss:bx + BS3REGCTX.ss], ax
580.save_context_16_done_stack:
581 mov ax, [xBP + xCB*3]
582 mov [ss:bx + BS3REGCTX.rflags], ax
583 mov al, VAR_CALLER_MODE
584 mov [ss:bx + BS3REGCTX.bMode], al
585 cmp byte [BS3_DATA16_WRT(g_uBs3CpuDetected)], BS3CPU_80286
586 jne .save_context_16_return
587 smsw [ss:bx + BS3REGCTX.cr0]
588 str [ss:bx + BS3REGCTX.tr]
589 sldt [ss:bx + BS3REGCTX.ldtr]
590.save_context_16_return:
591 or byte [ss:bx + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_AMD64 | BS3REG_CTX_F_NO_CR4
592 ret
593%endif ; TMPL_BITS == 16
594
595 ;
596 ; 80386 or later.
597 ;
598.save_context_full:
599
600 ; Clear the state area.
601 push xDI
602 xor xDI, xDI
603 AssertCompileSizeAlignment(BS3REGCTX, 16)
604.save_context_full_clear_loop:
605%if TMPL_BITS != 64
606 mov dword [ss:xBX + xDI], 0
607 mov dword [ss:xBX + xDI + 4], 0
608 add xDI, 8
609%else
610 mov qword [xBX + xDI], 0
611 mov qword [xBX + xDI + 8], 0
612 add xDI, 10h
613%endif
614 cmp xDI, BS3REGCTX_size
615 jb .save_context_full_clear_loop
616 pop xDI
617
618 ; Do the 386+ state saving.
619%if TMPL_BITS == 16 ; save the high word of registered pushed on the stack.
620 mov ecx, VAR_CALLER_AX
621 mov [ss:bx + BS3REGCTX.rax], ecx
622 mov ecx, VAR_CALLER_CX
623 mov [ss:bx + BS3REGCTX.rcx], ecx
624 mov ecx, VAR_CALLER_DX
625 mov [ss:bx + BS3REGCTX.rdx], ecx
626 mov ecx, VAR_CALLER_BX
627 mov [ss:bx + BS3REGCTX.rbx], ecx
628 mov ecx, VAR_CALLER_EBP
629 mov [ss:bx + BS3REGCTX.rbp], ecx
630 mov ecx, VAR_CALLER_ESP
631 mov [ss:bx + BS3REGCTX.rsp], ecx
632 mov ecx, VAR_CALLER_SI
633 mov [ss:bx + BS3REGCTX.rsi], ecx
634 mov ecx, VAR_CALLER_DI
635 mov [ss:bx + BS3REGCTX.rdi], ecx
636 mov ecx, VAR_CALLER_EFLAGS
637 mov [ss:bx + BS3REGCTX.rflags], ecx
638
639 ; Seed high EIP word if 32-bit CS.
640 lar ecx, [bp + 4]
641 jnz .save_context_full_done_16bit_high_word
642 test ecx, X86LAR_F_D
643 jz .save_context_full_done_16bit_high_word
644 mov ecx, [BS3_DATA16_WRT(g_uBs3TrapEipHint)]
645 mov [ss:bx + BS3REGCTX.rip], ecx
646.save_context_full_done_16bit_high_word:
647%endif ; 16-bit
648 mov xAX, VAR_CALLER_AX
649 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rax], xAX
650 mov xCX, VAR_CALLER_CX
651 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rcx], xCX
652 mov xAX, VAR_CALLER_DX
653 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rdx], xAX
654 mov xAX, VAR_CALLER_BX
655 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rbx], xAX
656 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rsi], sSI
657 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rdi], sDI
658 mov xAX, VAR_CALLER_BP
659 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rbp], xAX
660%if TMPL_BITS != 64
661 mov ax, VAR_CALLER_DS
662 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.ds], ax
663%else
664 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.ds], ds
665%endif
666 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.es], es
667 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.fs], fs
668 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.gs], gs
669 mov xAX, [xBP + xCB]
670 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rip], xAX
671 mov ax, [xBP + xCB*2]
672 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.cs], ax
673%if TMPL_MODE != BS3_MODE_RM
674 and al, X86_SEL_RPL
675 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.bCpl], al
676 cmp al, 0
677 je .save_context_full_same
678 mov xAX, [xBP + xCB*4]
679 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rsp], xAX
680 mov ax, [xBP + xCB*5]
681 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.ss], ax
682 jmp .save_context_full_done_stack
683%else
684 mov byte [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.bCpl], 0
685%endif
686.save_context_full_same:
687 mov xAX, xBP
688 add xAX, xCB * (1 + 3)
689 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rsp], xAX
690 mov ax, ss
691 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.ss], ax
692.save_context_full_done_stack:
693 mov xAX, [xBP + xCB*3]
694 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rflags], xAX
695
696 mov al, VAR_CALLER_MODE
697 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.bMode], al
698%if TMPL_BITS == 64
699 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.r8], r8
700 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.r9], r9
701 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.r10], r10
702 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.r11], r11
703 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.r12], r12
704 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.r13], r13
705 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.r14], r14
706 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.r15], r15
707%endif
708 str [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.tr]
709 sldt [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.ldtr]
710 mov sAX, cr0
711 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.cr0], sAX
712 mov sAX, cr2
713 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.cr2], sAX
714 mov sAX, cr3
715 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.cr3], sAX
716%if TMPL_BITS != 64
717 test byte [BS3_DATA16_WRT(g_uBs3CpuDetected)], (BS3CPU_F_CPUID >> 8)
718 jnz .have_cr4
719 or byte [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_CR4
720 jmp .done_cr4
721.have_cr4:
722%endif
723 mov sAX, cr4
724 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.cr4], sAX
725%if TMPL_BITS != 64
726.done_cr4:
727 or byte [ss:xBX + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_AMD64
728
729 ; Deal with extended v8086 frame.
730 %if TMPL_BITS == 32
731 test dword [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rflags], X86_EFL_VM
732 jz .save_context_full_return
733 %else
734 test byte VAR_CALLER_MODE, BS3_MODE_CODE_V86
735 jz .save_context_full_return
736 mov dword [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rflags], X86_EFL_VM
737 %endif
738 mov xAX, [xBP + xCB*4]
739 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rsp], xAX
740 mov ax, [xBP + xCB*5]
741 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.ss], ax
742 mov ax, [xBP + xCB*6]
743 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.es], ax
744 mov ax, [xBP + xCB*7]
745 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.ds], ax
746 mov ax, [xBP + xCB*8]
747 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.fs], ax
748 mov ax, [xBP + xCB*9]
749 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.gs], ax
750 mov byte [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.bCpl], 3
751 jmp .save_context_full_return
752
753%endif ; !64-bit
754
755.save_context_full_return:
756 ret
757
758%if TMPL_BITS == 16
759 CPU 286
760%endif
761
762 ;
763 ; Internal function for converting a syscall pointer parameter (cx:xSI)
764 ; to a pointer we can use here in this context.
765 ;
766 ; Returns the result in cx:xSI.
767 ; @uses xAX, xCX, xDX
768 ;
769.convert_ptr_arg_to_cx_xSI:
770 call .convert_ptr_arg_to_flat
771%if TMPL_BITS == 16
772 ; Convert to tiled address.
773 mov si, ax ; offset.
774 shl dx, X86_SEL_SHIFT
775 add dx, BS3_SEL_TILED
776 mov cx, dx
777%else
778 ; Just supply a flat selector.
779 mov xSI, xAX
780 mov cx, ds
781%endif
782 ret
783
784 ;
785 ; Internal function for converting a syscall pointer parameter (caller CX:xSI)
786 ; to a real mode pointer.
787 ;
788 ; Returns the result in AX:SI.
789 ; @uses xAX, xCX, xDX
790 ;
791.convert_ptr_arg_to_real_mode_ax_si:
792 call .convert_ptr_arg_to_flat
793 mov si, ax
794%if TMPL_BITS == 16
795 mov ax, dx
796%else
797 shr eax, 16
798%endif
799 shl ax, 12
800 ret
801
802 ;
803 ; Internal function for the above that wraps the Bs3SelProtFar32ToFlat32 call.
804 ;
805 ; @returns eax (32-bit, 64-bit), dx+ax (16-bit).
806 ; @uses eax, ecx, edx
807 ;
808.convert_ptr_arg_to_flat:
809%if TMPL_BITS == 16
810 ; Convert to (32-bit) flat address first.
811 test byte VAR_CALLER_MODE, BS3_MODE_CODE_V86
812 jz .convert_ptr_arg_to_flat_prot_16
813
814 mov ax, VAR_CALLER_CX
815 mov dx, ax
816 shl ax, 4
817 shr dx, 12
818 add ax, VAR_CALLER_SI
819 adc dx, 0
820 ret
821
822.convert_ptr_arg_to_flat_prot_16:
823 push es
824 push bx
825 push word VAR_CALLER_CX ; selector
826 xor ax, ax
827 test byte VAR_CALLER_MODE, BS3_MODE_CODE_16
828 jnz .caller_is_16_bit
829 mov ax, VAR_CALLER_SI_HI
830.caller_is_16_bit:
831 push ax ; offset high
832 push word VAR_CALLER_SI ; offset low
833 call Bs3SelProtFar32ToFlat32
834 add sp, 2*3
835 pop bx
836 pop es
837 ret
838
839%else ; 32 or 64 bit
840 test byte VAR_CALLER_MODE, BS3_MODE_CODE_V86
841 jz .convert_ptr_arg_to_cx_xSI_prot
842
843 ; Convert real mode address to flat address and return it.
844 movzx eax, word VAR_CALLER_CX
845 shl eax, 4
846 movzx edx, word VAR_CALLER_SI
847 add eax, edx
848 ret
849
850 ; Convert to (32-bit) flat address.
851.convert_ptr_arg_to_cx_xSI_prot:
852 %if TMPL_BITS == 64
853 push r11
854 push r10
855 push r9
856 push r8
857 sub rsp, 10h
858 %endif
859 movzx ecx, word VAR_CALLER_CX
860 push xCX
861 mov eax, VAR_CALLER_SI
862 test byte VAR_CALLER_MODE, BS3_MODE_CODE_16
863 jz .no_masking_offset
864 and eax, 0ffffh
865.no_masking_offset:
866 push xAX
867 BS3_CALL Bs3SelProtFar32ToFlat32,2
868 add xSP, xCB*2 BS3_ONLY_64BIT(+ 10h)
869 %if TMPL_BITS == 64
870 pop r8
871 pop r9
872 pop r10
873 pop r11
874 %endif
875%endif
876 ret
877
878BS3_PROC_END_MODE Bs3TrapSystemCallHandler
879
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