VirtualBox

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

最後變更 在這個檔案從97575是 96407,由 vboxsync 提交於 3 年 前

scm copyright and license note update

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 29.1 KB
 
1; $Id: bs3-mode-TrapSystemCallHandler.asm 96407 2022-08-22 17:43:14Z vboxsync $
2;; @file
3; BS3Kit - System call trap handler.
4;
5
6;
7; Copyright (C) 2007-2022 Oracle and/or its affiliates.
8;
9; This file is part of VirtualBox base platform packages, as
10; available from https://www.alldomusa.eu.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%endif
270 ; Convert the incoming pointer to real mode (assuming caller checked
271 ; that real mode can access it).
272 call .convert_ptr_arg_to_real_mode_ax_si
273 mov cx, VAR_CALLER_DX
274
275 ; Switch to real mode (no 20h scratch required)
276%ifndef TMPL_CMN_R86
277 %if TMPL_BITS != 16
278 jmp .print_str_to_16bit
279BS3_BEGIN_TEXT16
280.print_str_to_16bit:
281 BS3_SET_BITS TMPL_BITS
282 %endif
283 extern TMPL_NM(Bs3SwitchToRM)
284 call TMPL_NM(Bs3SwitchToRM)
285 BS3_SET_BITS 16
286%endif
287 ; Call code in Bs3PrintStrN to do the work.
288 mov ds, ax
289 call Bs3PrintStrN_c16_CX_Bytes_At_DS_SI
290
291 ; Switch back (20h param scratch area not required).
292%ifndef TMPL_CMN_R86
293 extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_rm)
294 call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_rm)
295 %if TMPL_BITS != 16
296 BS3_SET_BITS TMPL_BITS
297 jmp .print_str_end
298TMPL_BEGIN_TEXT
299 %endif
300.print_str_end:
301%endif
302%if TMPL_BITS != 64
303 pop es
304%endif
305 jmp .return
306
307
308 ;
309 ; Switch the caller to ring-0, ring-1, ring-2 or ring-3.
310 ;
311 ; This implement this by saving the entire register context, calling
312 ; a transformation function (C) and restoring the modified register
313 ; context using a generic worker.
314 ;
315.to_ringX:
316 sub xSP, BS3REGCTX_size
317 mov xBX, xSP ; xBP = BS3REGCTX pointer.
318 call .save_context
319
320%if TMPL_BITS == 32
321 ; Convert xBP to flat pointer in 32-bit
322 push ss
323 push xBX
324 call Bs3SelProtFar32ToFlat32
325 add sSP, 8
326 mov xBX, xAX
327%endif
328 push xBX ; Save pointer for the final restore call.
329
330 ; Convert the register context from whatever it is to ring-0.
331BONLY64 sub rsp, 10h
332 mov ax, VAR_CALLER_AX
333 sub ax, BS3_SYSCALL_TO_RING0
334 push xAX
335BONLY16 push ss
336 push xBX
337 BS3_CALL Bs3RegCtxConvertToRingX, 2
338 add xSP, sCB + xCB BS3_ONLY_64BIT(+ 10h)
339
340 ; Restore the register context (does not return).
341 pop xBX ; restore saved pointer.
342BONLY64 sub rsp, 18h
343BONLY16 push ss
344 push xBX
345 BS3_CALL Bs3RegCtxRestore, 1
346 jmp Bs3Panic
347
348
349 ;
350 ; Restore context pointed to by cx:xSI.
351 ;
352.restore_ctx:
353 call .convert_ptr_arg_to_cx_xSI
354BONLY64 sub rsp, 10h
355 mov xDX, VAR_CALLER_DX
356 push xDX
357BONLY16 push cx
358 push xSI
359 BS3_CALL Bs3RegCtxRestore, 2
360 jmp Bs3Panic
361
362 ;
363 ; Return.
364 ;
365.return:
366 pop xBX ; saved mode
367 mov [BS3_DATA16_WRT(g_bBs3CurrentMode)], bl
368%if TMPL_BITS == 16
369 and bl, BS3_MODE_CODE_MASK
370 cmp bl, BS3_MODE_CODE_V86
371 je .return_to_v8086_from_16bit_krnl
372 cmp bl, BS3_MODE_CODE_32
373 je .return_to_32bit_from_16bit_krnl
374 %if TMPL_MODE == BS3_MODE_RM || TMPL_MODE == BS3_MODE_PE16
375 cmp byte [BS3_DATA16_WRT(g_uBs3CpuDetected)], BS3CPU_80286
376 jbe .return_pre_80386
377 %endif
378
379 popfd
380 pop esp
381 pop ebp
382%endif
383 pop sDI
384 pop sSI
385 pop sDX
386 pop sCX
387 pop sAX
388 pop sBX
389%if TMPL_BITS != 64
390 pop ds
391 leave
392 iret
393%else
394 mov es, [rsp+2]
395 mov ds, [rsp]
396 leave ; skips ds
397 iretq
398%endif
399
400%if TMPL_BITS == 16
401 %if TMPL_MODE == BS3_MODE_RM || TMPL_MODE == BS3_MODE_PE16
402 ; Variant of the above for 80286 and older.
403.return_pre_80386:
404 add sp, 0ch
405 pop di
406 pop bx ; dummy
407 pop si
408 pop bx ; dummy
409 pop dx
410 pop bx ; dummy
411 pop cx
412 pop bx ; dummy
413 pop ax
414 pop bx ; dummy
415 pop bx ; pushed twice
416 pop bx
417 pop ds
418 pop bp
419 iret
420 %endif
421
422.return_to_v8086_from_16bit_krnl:
423 int3
424 jmp .return_to_v8086_from_16bit_krnl
425
426 ;
427 ; Returning to 32-bit code may require us to expand and seed the eip
428 ; and esp addresses in the iret frame since these are truncated when
429 ; using a 16-bit interrupt handler.
430 ;
431 ; Incoming stack: New stack diff cpl:
432 ; bp + 0ah: [ss]
433 ; bp + 08h: [sp] bx + 38h: [ss] New stack same cpl:
434 ; bp + 06h: flags
435 ; bp + 04h: cs bx + 34h: [esp] bx + 30h: eflags
436 ; bp + 02h: ip
437 ; -------------- bx + 30h: eflags bx + 2ch: cs
438 ; bp + 00h: bp
439 ; bp - 02h: ds bx + 2ch: cs bx + 28h: eip
440 ; -------------
441 ; bp - 06h: ebx bx + 28h: eip bx + 26h: bp
442 ; -------------- bx + 24h: ds
443 ; bp - 0ah: eax bx + 26h: bp
444 ; bx + 24h: ds bx + 20h: ebx
445 ; bp - 0eh: ecx
446 ; bx + 20h: ebx bx + 1ch: eax
447 ; bp - 12h: edx
448 ; bx + 1ch: eax bx + 18h: ecx
449 ; bp - 16h: esi
450 ; bx + 18h: ecx bx + 14h: edx
451 ; bp - 1ah: edi
452 ; bx + 14h: edx bx + 10h: esi
453 ; bp - 1eh: esp
454 ; bx + 10h: esi bx + 0ch: edi
455 ; bp - 22h: ebp
456 ; bx + 0ch: edi bx + 08h: esp
457 ; bp - 26h: eflags
458 ; bx + 08h: esp bx + 04h: ebp
459 ;
460 ; bx + 04h: ebp bx + 00h: eflags
461 ;
462 ; bx + 00h: eflags
463 ;
464 ;
465 ; If we're returning to the same CPL, we're still using the stack of
466 ; the 32-bit caller. The high ESP word does not need restoring.
467 ;
468 ; If we're returning to a lower CPL, there on a 16-bit ring-0 stack,
469 ; however, the high ESP word is still that of the caller.
470 ;
471.return_to_32bit_from_16bit_krnl:
472 mov ax, cs
473 and al, 3
474 mov ah, 3
475 and ah, [xBP + xCB*2]
476 ; The iret frame doubles in size, so allocate more stack.
477 cmp al, ah
478 je .return_to_32bit_from_16bit_krnl_same_cpl_sub_sp
479 sub sp, 2*2
480.return_to_32bit_from_16bit_krnl_same_cpl_sub_sp:
481 sub sp, 3*2
482 mov bx, sp
483 ; Copy the saved registers.
484 xor di, di
485.return_to_32bit_from_16bit_krnl_copy_loop:
486 mov ecx, [bp + di - 26h]
487 mov [ss:bx + di], ecx
488 add di, 4
489 cmp di, 28h
490 jb .return_to_32bit_from_16bit_krnl_copy_loop
491 ; Convert the 16-bit iret frame to a 32-bit iret frame.
492 mov ecx, [BS3_DATA16_WRT(g_uBs3TrapEipHint)]
493 mov cx, [bp + 02h] ; ip
494 mov [ss:bx + 28h], ecx
495 mov ecx, 0f00d0000h
496 mov cx, [bp + 04h] ; cs
497 mov [ss:bx + 2ch], ecx
498 mov ecx, [ss:bx] ; caller eflags
499 mov cx, [bp + 06h] ; flags
500 mov [ss:bx + 30h], ecx
501 cmp al, ah
502 jz .return_to_32bit_from_16bit_krnl_do_return
503 mov ecx, [ss:bx + 08h] ; caller esp
504 mov cx, [bp + 08h] ; sp
505 mov [ss:bx + 34h], ecx
506 mov ecx, 0f00d0000h
507 mov cx, [bp + 0ah] ; ss
508 mov [ss:bx + 38h], ecx
509.return_to_32bit_from_16bit_krnl_do_return:
510 popfd
511 pop ecx ; esp - only the high bits!
512 mov cx, sp
513 mov esp, ecx
514 pop ebp
515 lea bp, [bx + 26h]
516 pop edi
517 pop esi
518 pop edx
519 pop ecx
520 pop eax
521 pop ebx
522 pop ds
523 leave
524 iretd
525
526%endif ; 16-bit
527
528
529 ;
530 ; Internal function. ss:xBX = Pointer to register frame (BS3REGCTX).
531 ; @uses xAX
532 ;
533.save_context:
534%if TMPL_BITS == 16
535 cmp byte [BS3_DATA16_WRT(g_uBs3CpuDetected)], BS3CPU_80386
536 jae .save_context_full
537
538 ;
539 ; 80286 or earlier.
540 ;
541
542 ; Clear the state area first.
543 push di
544 xor di, di
545.save_context_16_clear_loop:
546 mov word [ss:bx + di], 0
547 mov word [ss:bx + di + 2], 0
548 mov word [ss:bx + di + 4], 0
549 mov word [ss:bx + di + 6], 0
550 add di, 8
551 cmp di, BS3REGCTX_size
552 jb .save_context_16_clear_loop
553 pop di
554
555 ; Do the 8086/80186/80286 state saving.
556 mov ax, VAR_CALLER_AX
557 mov [ss:bx + BS3REGCTX.rax], ax
558 mov cx, VAR_CALLER_CX
559 mov [ss:bx + BS3REGCTX.rcx], ax
560 mov ax, VAR_CALLER_DX
561 mov [ss:bx + BS3REGCTX.rdx], ax
562 mov ax, VAR_CALLER_BX
563 mov [ss:bx + BS3REGCTX.rbx], ax
564 mov [ss:bx + BS3REGCTX.rsi], si
565 mov [ss:bx + BS3REGCTX.rdi], di
566 mov ax, VAR_CALLER_BP
567 mov [ss:bx + BS3REGCTX.rbp], ax
568 mov ax, VAR_CALLER_DS
569 mov [ss:bx + BS3REGCTX.ds], ax
570 mov [ss:bx + BS3REGCTX.es], es
571 mov ax, [xBP + xCB]
572 mov [ss:bx + BS3REGCTX.rip], ax
573 mov ax, [xBP + xCB*2]
574 mov [ss:bx + BS3REGCTX.cs], ax
575 and al, X86_SEL_RPL
576 mov [ss:bx + BS3REGCTX.bCpl], al
577 cmp al, 0
578 je .save_context_16_same
579 mov ax, [xBP + xCB*4]
580 mov [ss:bx + BS3REGCTX.rsp], ax
581 mov ax, [xBP + xCB*5]
582 mov [ss:bx + BS3REGCTX.ss], ax
583 jmp .save_context_16_done_stack
584.save_context_16_same:
585 mov ax, bp
586 add ax, xCB * (1 + 3)
587 mov [ss:bx + BS3REGCTX.rsp], ax
588 mov ax, ss
589 mov [ss:bx + BS3REGCTX.ss], ax
590.save_context_16_done_stack:
591 mov ax, [xBP + xCB*3]
592 mov [ss:bx + BS3REGCTX.rflags], ax
593 mov al, VAR_CALLER_MODE
594 mov [ss:bx + BS3REGCTX.bMode], al
595 cmp byte [BS3_DATA16_WRT(g_uBs3CpuDetected)], BS3CPU_80286
596 jne .save_context_16_return
597 smsw [ss:bx + BS3REGCTX.cr0]
598 str [ss:bx + BS3REGCTX.tr]
599 sldt [ss:bx + BS3REGCTX.ldtr]
600.save_context_16_return:
601 or byte [ss:bx + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_AMD64 | BS3REG_CTX_F_NO_CR4
602 ret
603%endif ; TMPL_BITS == 16
604
605 ;
606 ; 80386 or later.
607 ;
608.save_context_full:
609
610 ; Clear the state area.
611 push xDI
612 xor xDI, xDI
613 AssertCompileSizeAlignment(BS3REGCTX, 16)
614.save_context_full_clear_loop:
615%if TMPL_BITS != 64
616 mov dword [ss:xBX + xDI], 0
617 mov dword [ss:xBX + xDI + 4], 0
618 add xDI, 8
619%else
620 mov qword [xBX + xDI], 0
621 mov qword [xBX + xDI + 8], 0
622 add xDI, 10h
623%endif
624 cmp xDI, BS3REGCTX_size
625 jb .save_context_full_clear_loop
626 pop xDI
627
628 ; Do the 386+ state saving.
629%if TMPL_BITS == 16 ; save the high word of registered pushed on the stack.
630 mov ecx, VAR_CALLER_AX
631 mov [ss:bx + BS3REGCTX.rax], ecx
632 mov ecx, VAR_CALLER_CX
633 mov [ss:bx + BS3REGCTX.rcx], ecx
634 mov ecx, VAR_CALLER_DX
635 mov [ss:bx + BS3REGCTX.rdx], ecx
636 mov ecx, VAR_CALLER_BX
637 mov [ss:bx + BS3REGCTX.rbx], ecx
638 mov ecx, VAR_CALLER_EBP
639 mov [ss:bx + BS3REGCTX.rbp], ecx
640 mov ecx, VAR_CALLER_ESP
641 mov [ss:bx + BS3REGCTX.rsp], ecx
642 mov ecx, VAR_CALLER_SI
643 mov [ss:bx + BS3REGCTX.rsi], ecx
644 mov ecx, VAR_CALLER_DI
645 mov [ss:bx + BS3REGCTX.rdi], ecx
646 mov ecx, VAR_CALLER_EFLAGS
647 mov [ss:bx + BS3REGCTX.rflags], ecx
648
649 ; Seed high EIP word if 32-bit CS.
650 lar ecx, [bp + 4]
651 jnz .save_context_full_done_16bit_high_word
652 test ecx, X86LAR_F_D
653 jz .save_context_full_done_16bit_high_word
654 mov ecx, [BS3_DATA16_WRT(g_uBs3TrapEipHint)]
655 mov [ss:bx + BS3REGCTX.rip], ecx
656.save_context_full_done_16bit_high_word:
657%endif ; 16-bit
658 mov xAX, VAR_CALLER_AX
659 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rax], xAX
660 mov xCX, VAR_CALLER_CX
661 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rcx], xCX
662 mov xAX, VAR_CALLER_DX
663 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rdx], xAX
664 mov xAX, VAR_CALLER_BX
665 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rbx], xAX
666 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rsi], sSI
667 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rdi], sDI
668 mov xAX, VAR_CALLER_BP
669 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rbp], xAX
670%if TMPL_BITS != 64
671 mov ax, VAR_CALLER_DS
672 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.ds], ax
673%else
674 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.ds], ds
675%endif
676 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.es], es
677 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.fs], fs
678 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.gs], gs
679 mov xAX, [xBP + xCB]
680 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rip], xAX
681 mov ax, [xBP + xCB*2]
682 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.cs], ax
683%if TMPL_MODE != BS3_MODE_RM
684 and al, X86_SEL_RPL
685 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.bCpl], al
686 cmp al, 0
687 je .save_context_full_same
688 mov xAX, [xBP + xCB*4]
689 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rsp], xAX
690 mov ax, [xBP + xCB*5]
691 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.ss], ax
692 jmp .save_context_full_done_stack
693%else
694 mov byte [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.bCpl], 0
695%endif
696.save_context_full_same:
697 mov xAX, xBP
698 add xAX, xCB * (1 + 3)
699 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rsp], xAX
700 mov ax, ss
701 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.ss], ax
702.save_context_full_done_stack:
703 mov xAX, [xBP + xCB*3]
704 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rflags], xAX
705
706 mov al, VAR_CALLER_MODE
707 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.bMode], al
708%if TMPL_BITS == 64
709 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.r8], r8
710 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.r9], r9
711 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.r10], r10
712 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.r11], r11
713 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.r12], r12
714 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.r13], r13
715 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.r14], r14
716 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.r15], r15
717%endif
718 str [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.tr]
719 sldt [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.ldtr]
720 mov sAX, cr0
721 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.cr0], sAX
722 mov sAX, cr2
723 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.cr2], sAX
724 mov sAX, cr3
725 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.cr3], sAX
726%if TMPL_BITS != 64
727 test byte [BS3_DATA16_WRT(g_uBs3CpuDetected)], (BS3CPU_F_CPUID >> 8)
728 jnz .have_cr4
729 or byte [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_CR4
730 jmp .done_cr4
731.have_cr4:
732%endif
733 mov sAX, cr4
734 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.cr4], sAX
735%if TMPL_BITS != 64
736.done_cr4:
737 or byte [ss:xBX + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_AMD64
738
739 ; Deal with extended v8086 frame.
740 %if TMPL_BITS == 32
741 test dword [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rflags], X86_EFL_VM
742 jz .save_context_full_return
743 %else
744 test byte VAR_CALLER_MODE, BS3_MODE_CODE_V86
745 jz .save_context_full_return
746 mov dword [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rflags], X86_EFL_VM
747 %endif
748 mov xAX, [xBP + xCB*4]
749 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rsp], xAX
750 mov ax, [xBP + xCB*5]
751 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.ss], ax
752 mov ax, [xBP + xCB*6]
753 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.es], ax
754 mov ax, [xBP + xCB*7]
755 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.ds], ax
756 mov ax, [xBP + xCB*8]
757 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.fs], ax
758 mov ax, [xBP + xCB*9]
759 mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.gs], ax
760 mov byte [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.bCpl], 3
761 jmp .save_context_full_return
762
763%endif ; !64-bit
764
765.save_context_full_return:
766 ret
767
768%if TMPL_BITS == 16
769 CPU 286
770%endif
771
772 ;
773 ; Internal function for converting a syscall pointer parameter (cx:xSI)
774 ; to a pointer we can use here in this context.
775 ;
776 ; Returns the result in cx:xSI.
777 ; @uses xAX, xCX, xDX
778 ;
779.convert_ptr_arg_to_cx_xSI:
780 call .convert_ptr_arg_to_flat
781%if TMPL_BITS == 16
782 ; Convert to tiled address.
783 mov si, ax ; offset.
784 shl dx, X86_SEL_SHIFT
785 add dx, BS3_SEL_TILED
786 mov cx, dx
787%else
788 ; Just supply a flat selector.
789 mov xSI, xAX
790 mov cx, ds
791%endif
792 ret
793
794 ;
795 ; Internal function for converting a syscall pointer parameter (caller CX:xSI)
796 ; to a real mode pointer.
797 ;
798 ; Returns the result in AX:SI.
799 ; @uses xAX, xCX, xDX
800 ;
801.convert_ptr_arg_to_real_mode_ax_si:
802 call .convert_ptr_arg_to_flat
803 mov si, ax
804%if TMPL_BITS == 16
805 mov ax, dx
806%else
807 shr eax, 16
808%endif
809 shl ax, 12
810 ret
811
812 ;
813 ; Internal function for the above that wraps the Bs3SelProtFar32ToFlat32 call.
814 ;
815 ; @returns eax (32-bit, 64-bit), dx+ax (16-bit).
816 ; @uses eax, ecx, edx
817 ;
818.convert_ptr_arg_to_flat:
819%if TMPL_BITS == 16
820 ; Convert to (32-bit) flat address first.
821 test byte VAR_CALLER_MODE, BS3_MODE_CODE_V86
822 jz .convert_ptr_arg_to_flat_prot_16
823
824 mov ax, VAR_CALLER_CX
825 mov dx, ax
826 shl ax, 4
827 shr dx, 12
828 add ax, VAR_CALLER_SI
829 adc dx, 0
830 ret
831
832.convert_ptr_arg_to_flat_prot_16:
833 push es
834 push bx
835 push word VAR_CALLER_CX ; selector
836 xor ax, ax
837 test byte VAR_CALLER_MODE, BS3_MODE_CODE_16
838 jnz .caller_is_16_bit
839 mov ax, VAR_CALLER_SI_HI
840.caller_is_16_bit:
841 push ax ; offset high
842 push word VAR_CALLER_SI ; offset low
843 call Bs3SelProtFar32ToFlat32
844 add sp, 2*3
845 pop bx
846 pop es
847 ret
848
849%else ; 32 or 64 bit
850 test byte VAR_CALLER_MODE, BS3_MODE_CODE_V86
851 jz .convert_ptr_arg_to_cx_xSI_prot
852
853 ; Convert real mode address to flat address and return it.
854 movzx eax, word VAR_CALLER_CX
855 shl eax, 4
856 movzx edx, word VAR_CALLER_SI
857 add eax, edx
858 ret
859
860 ; Convert to (32-bit) flat address.
861.convert_ptr_arg_to_cx_xSI_prot:
862 %if TMPL_BITS == 64
863 push r11
864 push r10
865 push r9
866 push r8
867 sub rsp, 10h
868 %endif
869 movzx ecx, word VAR_CALLER_CX
870 push xCX
871 mov eax, VAR_CALLER_SI
872 test byte VAR_CALLER_MODE, BS3_MODE_CODE_16
873 jz .no_masking_offset
874 and eax, 0ffffh
875.no_masking_offset:
876 push xAX
877 BS3_CALL Bs3SelProtFar32ToFlat32,2
878 add xSP, xCB*2 BS3_ONLY_64BIT(+ 10h)
879 %if TMPL_BITS == 64
880 pop r8
881 pop r9
882 pop r10
883 pop r11
884 %endif
885%endif
886 ret
887
888BS3_PROC_END_MODE Bs3TrapSystemCallHandler
889
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette