VirtualBox

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

Last change on this file since 106215 was 106061, checked in by vboxsync, 3 months ago

Copyright year updates by scm.

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