VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/bootsectors/bootsector2-common-init-traps.mac@ 104620

Last change on this file since 104620 was 98103, checked in by vboxsync, 20 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: 55.1 KB
Line 
1; $Id: bootsector2-common-init-traps.mac 98103 2023-01-17 14:15:46Z vboxsync $
2;; @file
3; Common bootsector code init, traps.
4;
5; This is included from bootsector2-common-init-code.mac and was split out of
6; that file to keep the size manageable.
7;
8
9;
10; Copyright (C) 2007-2023 Oracle and/or its affiliates.
11;
12; This file is part of VirtualBox base platform packages, as
13; available from https://www.virtualbox.org.
14;
15; This program is free software; you can redistribute it and/or
16; modify it under the terms of the GNU General Public License
17; as published by the Free Software Foundation, in version 3 of the
18; License.
19;
20; This program is distributed in the hope that it will be useful, but
21; WITHOUT ANY WARRANTY; without even the implied warranty of
22; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23; General Public License for more details.
24;
25; You should have received a copy of the GNU General Public License
26; along with this program; if not, see <https://www.gnu.org/licenses>.
27;
28; The contents of this file may alternatively be used under the terms
29; of the Common Development and Distribution License Version 1.0
30; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
31; in the VirtualBox distribution, in which case the provisions of the
32; CDDL are applicable instead of those of the GPL.
33;
34; You may elect to license modified versions of this file under the
35; terms and conditions of either the GPL or the CDDL or both.
36;
37; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
38;
39
40%ifndef BS2_WITH_TRAPS
41 %error "huh? BS2_WITH_TRAPS is not defined!"
42%endif
43
44
45;*******************************************************************************
46;* Header Files *
47;*******************************************************************************
48%include "bootsector2-structures.mac"
49%include "bootsector2-api.mac"
50
51
52;*******************************************************************************
53;* Global Variables *
54;*******************************************************************************
55BEGINCODELOW
56ALIGNDATA(8)
57;; Where to resume execution after a trap (if g_fTrapPrepared is set).
58; @internal
59g_TrapResumeRIP:
60 dq 0
61;; Set if we've prepared for a trap.
62; @internal
63g_fTrapPrepared:
64 db 0
65;; Benchmark indicator.
66; This is set to the expected trap number when we're benchmarking and 0ffh when
67; we aren't benchmarking.
68; @internal
69g_u8TrapBenchmarkNo:
70 db 0ffh
71 db 0 ; alignment padding.
72;; The last trap number.
73GLOBALNAME g_u8LastTrapNo
74 db 0
75;; The number of traps since last call to Bs2TrapReset.
76GLOBALNAME g_u32cTraps
77 dd 0
78;; The last trap error code.
79GLOBALNAME g_u64LastTrapErr
80 dq 0
81;; The register frame of the last trap (BS2REGS).
82GLOBALNAME g_LastTrapRegs
83 times (BS2REGS_size) db 0
84
85;; The RFLAGS/EFLAGS inside last invoked trap handler.
86GLOBALNAME g_u64LastTrapHandlerRFlags
87 dq 0
88;; The CS inside last invoked trap handler.
89GLOBALNAME g_u16LastTrapHandlerCS
90 dw 0
91;; The SS inside last invoked trap handler.
92GLOBALNAME g_u16LastTrapHandlerSS
93 dw 0
94 dw 0,0 ; alignment
95;; The RSP inside the last invoked trap handler, i.e. when bs2Trap_XX_32bit is
96; entered, so including fake error code and vector number.
97GLOBALNAME g_u64LastTrapHandlerRSP
98 dq 0
99
100;;
101; Pointer to an array of BS2TRAPREC1 records.
102GLOBALNAME g_paTrapRecs
103 dq 0
104;; Number of entries in the array g_paTrapRecs points to.
105GLOBALNAME g_cTrapRecs
106 dd 0
107;; The index of the last BS2TRAPREC1 we hit.
108GLOBALNAME g_iTrapRecLast
109 dd 0
110;; The base address the BS2TRAPREC.offWhere values are relative to.
111GLOBALNAME g_pTrapRecBase
112 dq 0
113
114
115;;
116; Reset all the trap globals to default.
117;
118; This undos the effect of any previous Bs2TrapPrepare call.
119;
120; @uses nothing.
121;
122BEGINCODELOW
123BITS 16
124BEGINPROC Bs2TrapReset_rm16
125 push xBP
126 mov xBP, xSP
127 push ds
128 push word 0
129 pop ds
130
131 mov dword [g_u32cTraps], 0
132 mov byte [g_u8LastTrapNo], 0ffh
133 mov dword [g_u64LastTrapErr], 0
134 mov dword [g_u64LastTrapErr + 4], 0
135 mov dword [g_TrapResumeRIP], 0
136 mov dword [g_TrapResumeRIP + 4], 0
137 mov byte [g_u8TrapBenchmarkNo], 0ffh
138 mov byte [g_fTrapPrepared], 0
139
140 pop ds
141 leave
142 ret
143ENDPROC Bs2TrapReset_rm16
144
145
146;;
147; Reset all the trap globals to default.
148;
149; This undos the effect of any previous Bs2TrapPrepare call.
150;
151; @uses nothing.
152;
153BEGINCODELOW
154BITS 16
155BEGINPROC Bs2TrapReset_p16
156 push ds
157 push BS2_SEL_DS16
158 pop ds
159
160 mov dword [g_u32cTraps], 0
161 mov byte [g_u8LastTrapNo], 0ffh
162 mov dword [g_u64LastTrapErr], 0
163 mov dword [g_u64LastTrapErr + 4], 0
164 mov dword [g_TrapResumeRIP], 0
165 mov dword [g_TrapResumeRIP + 4], 0
166 mov byte [g_u8TrapBenchmarkNo], 0ffh
167 mov byte [g_fTrapPrepared], 0
168
169 pop ds
170 ret
171ENDPROC Bs2TrapReset_p16
172
173
174
175;;
176; Reset all the trap globals to default.
177;
178; This undos the effect of any previous Bs2TrapPrepare call.
179;
180; @uses nothing.
181;
182BEGINCODEHIGH
183BITS 32
184BEGINPROC Bs2TrapReset_p32
185 push ds
186 push BS2_SEL_DS32
187 pop ds
188
189 mov dword [g_u32cTraps], 0
190 mov byte [g_u8LastTrapNo], 0ffh
191 mov dword [g_u64LastTrapErr], 0
192 mov dword [g_u64LastTrapErr + 4], 0
193 mov dword [g_TrapResumeRIP], 0
194 mov dword [g_TrapResumeRIP + 4], 0
195 mov byte [g_u8TrapBenchmarkNo], 0ffh
196 mov byte [g_fTrapPrepared], 0
197
198 pop ds
199 ret
200ENDPROC Bs2TrapReset_p32
201
202
203;;
204; Reset all the trap globals to default.
205;
206; This undos the effect of any previous Bs2TrapPrepare call.
207;
208; @uses nothing.
209;
210BEGINCODEHIGH
211BITS 64
212BEGINPROC Bs2TrapReset_p64
213 mov dword [g_u32cTraps], 0
214 mov byte [g_u8LastTrapNo], 0ffh
215 mov qword [g_u64LastTrapErr], 0
216 mov qword [g_TrapResumeRIP], 0
217 mov byte [g_u8TrapBenchmarkNo], 0ffh
218 mov byte [g_fTrapPrepared], 0
219 ret
220ENDPROC Bs2TrapReset_p64
221
222
223
224;;
225; Prepare for a test that will trap.
226;
227; @param xAX Where to resume after the trap.
228; @param dl Set to 0ffh for tests and the expected trap number when
229; preparing a benchmark.
230; @uses nothing.
231;
232BEGINCODELOW
233BITS 16
234BEGINPROC Bs2TrapPrepare_rm16
235 push xBP
236 mov xBP, xSP
237 push ds
238 push word 0
239 pop ds
240
241 mov dword [g_u32cTraps], 0
242 mov byte [g_u8LastTrapNo], 0ffh
243 mov dword [g_u64LastTrapErr], 0
244 mov dword [g_u64LastTrapErr + 4], 0
245 mov word [g_TrapResumeRIP], ax
246 mov word [g_TrapResumeRIP + 2], 0
247 mov dword [g_TrapResumeRIP + 4], 0
248 mov byte [g_u8TrapBenchmarkNo], dl
249 mov byte [g_fTrapPrepared], 1
250
251 pop ds
252 leave
253 ret
254ENDPROC Bs2TrapPrepare_rm16
255
256
257;;
258; Prepare for a test that will trap.
259;
260; @param ax Where to resume after the trap.
261; @param dl Set to 0ffh for tests and the expected trap number when
262; preparing a benchmark.
263; @uses nothing.
264;
265BEGINCODELOW
266BITS 16
267BEGINPROC Bs2TrapPrepare_p16
268 push ds
269 push BS2_SEL_DS16
270 pop ds
271
272 mov dword [g_u32cTraps], 0
273 mov byte [g_u8LastTrapNo], 0ffh
274 mov dword [g_u64LastTrapErr], 0
275 mov dword [g_u64LastTrapErr + 4], 0
276 mov word [g_TrapResumeRIP], ax
277 mov word [g_TrapResumeRIP + 2], 0
278 mov dword [g_TrapResumeRIP + 4], 0
279 mov byte [g_u8TrapBenchmarkNo], dl
280 mov byte [g_fTrapPrepared], 1
281
282 pop ds
283 ret
284ENDPROC Bs2TrapPrepare_p16
285
286
287;;
288; Prepare for a test that will trap.
289;
290; @param eax Where to resume after the trap.
291; @param dl Set to 0ffh for tests and the expected trap number when
292; preparing a benchmark.
293; @uses nothing.
294;
295BEGINCODEHIGH
296BITS 32
297BEGINPROC Bs2TrapPrepare_p32
298 push ds
299 push BS2_SEL_DS32
300 pop ds
301
302 mov dword [g_u32cTraps], 0
303 mov byte [g_u8LastTrapNo], 0ffh
304 mov dword [g_u64LastTrapErr], 0
305 mov dword [g_u64LastTrapErr + 4], 0
306 mov dword [g_TrapResumeRIP], eax
307 mov dword [g_TrapResumeRIP + 4], 0
308 mov byte [g_u8TrapBenchmarkNo], dl
309 mov byte [g_fTrapPrepared], 1
310
311 pop ds
312 ret
313ENDPROC Bs2TrapPrepare_p32
314
315
316;;
317; Prepare for a test that will trap.
318;
319; @param rax Where to resume after the trap.
320; @param dl Set to 0ffh for tests and the expected trap number when
321; preparing a benchmark.
322; @uses nothing.
323;
324BEGINCODEHIGH
325BITS 64
326BEGINPROC Bs2TrapPrepare_p64
327 mov dword [g_u32cTraps], 0
328 mov byte [g_u8LastTrapNo], 0ffh
329 mov qword [g_u64LastTrapErr], 0
330 mov qword [g_TrapResumeRIP], rax
331 mov byte [g_u8TrapBenchmarkNo], dl
332 mov byte [g_fTrapPrepared], 1
333 ret
334ENDPROC Bs2TrapPrepare_p64
335
336
337BEGINCODELOW ; The TSSes, IDTs and handlers must be 16-bit addressable.
338
339%ifdef BS2_INC_CMN_PM
340;
341; 32-bit TSS (X86TSS32).
342;
343ALIGNDATA(16)
344bs2Tss32Bit:
345 dw 07fffh ; selPrev - Back link to previous task. (static)
346 dw 0h ; padding1;
347 dd BS2_R0_STACK_ADDR ; esp0 - Ring-0 stack pointer. (static)
348 dw BS2_SEL_SS32 ; ss0
349 dw 0 ; padding
350 dd BS2_R1_STACK_ADDR ; esp1 - Ring-1 stack pointer. (static)
351 dw 0 ; ss1
352 dw 0 ; padding
353 dd BS2_R2_STACK_ADDR ; esp2 - Ring-1 stack pointer. (static)
354 dw 0 ; ss2
355 dw 0 ; padding
356 dd 0ffffffffh ; cr3 - Page directory for the task. (static)
357 dd 0 ; eip - EIP before task switch.
358 dd 0 ; eflags - EFLAGS before task switch.
359 dd 0 ; eax - EAX before task switch.
360 dd 0 ; ecx - ECX before task switch.
361 dd 0 ; edx - EDX before task switch.
362 dd 0 ; ebx - EBX before task switch.
363 dd 0 ; esp - ESP before task switch.
364 dd 0 ; ebp - EBP before task switch.
365 dd 0 ; esi - ESI before task switch.
366 dd 0 ; edi - EDI before task switch.
367 dw 0, 0 ; es,pad - ES before task switch.
368 dw 0, 0 ; cs,pad - CS before task switch.
369 dw 0, 0 ; ss,pad - SS before task switch.
370 dw 0, 0 ; ds,pad - DS before task switch.
371 dw 0, 0 ; fs,pad - FS before task switch.
372 dw 0, 0 ; gs,pad - GS before task switch.
373 dw 0, 0 ; ldt,pad - LDTR before task switch.
374 dw 0 ; fDebugTrap - Debug trap flag.
375 dw 7fffh ; offIoBitmap - Offset relative to the TSS of the
376 ; start of the I/O Bitmap and the end of the
377 ; interrupt redirection bitmap.
378 ; IntRedirBitmap - 32 bytes for the virtual interrupt redirection bitmap. (VME)
379bs2Tss32BitEnd:
380times (68h - (bs2Tss32BitEnd - bs2Tss32Bit)) db 0
381times ((bs2Tss32BitEnd - bs2Tss32Bit) - 68h) db 0
382
383
384;
385; 32-bit TSS for #DF (X86TSS32).
386;
387ALIGNDATA(16)
388bs2Tss32BitDf:
389 dw 07fffh ; selPrev - Back link to previous task. (static)
390 dw 0h ; padding1;
391 dd BS2_DF_R0_STACK_ADDR ; esp0 - Ring-0 stack pointer. (static)
392 dw BS2_SEL_SS32 ; ss0
393 dw 0 ; padding
394 dd 0 ; esp1 - Ring-1 stack pointer. (static)
395 dw 0 ; ss1
396 dw 0 ; padding
397 dd 0 ; esp2 - Ring-1 stack pointer. (static)
398 dw 0 ; ss2
399 dw 0 ; padding
400 dd 0ffffffffh ; cr3 - Page directory for the task. (static)
401 dd bs2Trap_08h_32bit ; eip - EIP before task switch. */
402 dd 0 ; eflags - EFLAGS before task switch. */
403 dd 0 ; eax - EAX before task switch. */
404 dd 0 ; ecx - ECX before task switch. */
405 dd 0 ; edx - EDX before task switch. */
406 dd 0 ; ebx - EBX before task switch. */
407 dd BS2_DF_R0_STACK_ADDR ; esp - ESP before task switch. */
408 dd 0 ; ebp - EBP before task switch. */
409 dd 0 ; esi - ESI before task switch. */
410 dd 0 ; edi - EDI before task switch. */
411 dw BS2_SEL_DS32, 0 ; es,pad - ES before task switch. */
412 dw BS2_SEL_CS32, 0 ; cs,pad - CS before task switch. */
413 dw BS2_SEL_SS32, 0 ; ss,pad - SS before task switch. */
414 dw BS2_SEL_DS32, 0 ; ds,pad - DS before task switch. */
415 dw BS2_SEL_DS32, 0 ; fs,pad - FS before task switch. */
416 dw BS2_SEL_DS32, 0 ; gs,pad - GS before task switch. */
417 dw 0, 0 ; ldt,pad- LDTR before task switch. */
418 dw 0 ; fDebugTrap - Debug trap flag.
419 dw 7fffh ; offIoBitmap - Offset relative to the TSS of the
420 ; start of the I/O Bitmap and the end of the
421 ; interrupt redirection bitmap.
422 ; IntRedirBitmap - 32 bytes for the virtual interrupt redirection bitmap. (VME)
423bs2Tss32BitDfEnd:
424times (68h - (bs2Tss32BitDfEnd - bs2Tss32BitDf)) db 0
425times ((bs2Tss32BitDfEnd - bs2Tss32BitDf) - 68h) db 0
426
427
428;
429; 32-bit IDT (X86DESCGATE).
430;
431ALIGNDATA(16)
432bs2Idt32bit:
433 dw bs2Trap_00h_32bit, BS2_SEL_CS32, 08e00h, 00000h ; p=1 dpl=0 type=int32gate
434 dw bs2Trap_01h_32bit, BS2_SEL_CS32, 08e00h, 00000h ; p=1 dpl=0 type=int32gate
435 dw bs2Trap_02h_32bit, BS2_SEL_CS32, 08e00h, 00000h ; p=1 dpl=0 type=int32gate
436bs2Idt32bit_BP:
437 dw bs2Trap_03h_32bit, BS2_SEL_CS32, 08e00h, 00000h ; p=1 dpl=0 type=int32gate
438 dw bs2Trap_04h_32bit, BS2_SEL_CS32, 08e00h, 00000h ; p=1 dpl=0 type=int32gate
439 dw bs2Trap_05h_32bit, BS2_SEL_CS32, 08e00h, 00000h ; p=1 dpl=0 type=int32gate
440 dw bs2Trap_06h_32bit, BS2_SEL_CS32, 08e00h, 00000h ; p=1 dpl=0 type=int32gate
441 dw bs2Trap_07h_32bit, BS2_SEL_CS32, 08e00h, 00000h ; p=1 dpl=0 type=int32gate
442 dw 0, BS2_SEL_TSS32_DF, 08500h, 00000h ; p=1 dpl=0 type=taskgate
443 dw bs2Trap_09h_32bit, BS2_SEL_CS32, 08e00h, 00000h ; p=1 dpl=0 type=int32gate
444 dw bs2Trap_0ah_32bit, BS2_SEL_CS32, 08e00h, 00000h ; p=1 dpl=0 type=int32gate
445 dw bs2Trap_0bh_32bit, BS2_SEL_CS32, 08e00h, 00000h ; p=1 dpl=0 type=int32gate
446 dw bs2Trap_0ch_32bit, BS2_SEL_CS32, 08e00h, 00000h ; p=1 dpl=0 type=int32gate
447 dw bs2Trap_0dh_32bit, BS2_SEL_CS32, 08e00h, 00000h ; p=1 dpl=0 type=int32gate
448 dw bs2Trap_0eh_32bit, BS2_SEL_CS32, 08e00h, 00000h ; p=1 dpl=0 type=int32gate
449 dw bs2Trap_0fh_32bit, BS2_SEL_CS32, 08e00h, 00000h ; p=1 dpl=0 type=int32gate
450 dw bs2Trap_10h_32bit, BS2_SEL_CS32, 08e00h, 00000h ; p=1 dpl=0 type=int32gate
451 dw bs2Trap_11h_32bit, BS2_SEL_CS32, 08e00h, 00000h ; p=1 dpl=0 type=int32gate
452 dw bs2Trap_12h_32bit, BS2_SEL_CS32, 08e00h, 00000h ; p=1 dpl=0 type=int32gate
453 dw bs2Trap_13h_32bit, BS2_SEL_CS32, 08e00h, 00000h ; p=1 dpl=0 type=int32gate
454 dw bs2Trap_14h_32bit, BS2_SEL_CS32, 08e00h, 00000h ; p=1 dpl=0 type=int32gate
455 dw bs2Trap_15h_32bit, BS2_SEL_CS32, 08e00h, 00000h ; p=1 dpl=0 type=int32gate
456 dw bs2Trap_16h_32bit, BS2_SEL_CS32, 08e00h, 00000h ; p=1 dpl=0 type=int32gate
457 dw bs2Trap_17h_32bit, BS2_SEL_CS32, 08e00h, 00000h ; p=1 dpl=0 type=int32gate
458 dw bs2Trap_18h_32bit, BS2_SEL_CS32, 08e00h, 00000h ; p=1 dpl=0 type=int32gate
459 dw bs2Trap_19h_32bit, BS2_SEL_CS32, 08e00h, 00000h ; p=1 dpl=0 type=int32gate
460 dw bs2Trap_1ah_32bit, BS2_SEL_CS32, 08e00h, 00000h ; p=1 dpl=0 type=int32gate
461 dw bs2Trap_1bh_32bit, BS2_SEL_CS32, 08e00h, 00000h ; p=1 dpl=0 type=int32gate
462 dw bs2Trap_1ch_32bit, BS2_SEL_CS32, 08e00h, 00000h ; p=1 dpl=0 type=int32gate
463 dw bs2Trap_1dh_32bit, BS2_SEL_CS32, 08e00h, 00000h ; p=1 dpl=0 type=int32gate
464 dw bs2Trap_1eh_32bit, BS2_SEL_CS32, 08e00h, 00000h ; p=1 dpl=0 type=int32gate
465 dw bs2Trap_1fh_32bit, BS2_SEL_CS32, 08e00h, 00000h ; p=1 dpl=0 type=int32gate
466 dw bs2TrapService32bit,BS2_SEL_CS32,0ee00h, 00000h, 0, 0, 0, 0 ; p=1 dpl=3 type=int32gate
467%define BS2_TRAP_SERVICE_NO 30h
468;; @todo
469bs2Idt32bitEnd
470
471;
472; 32-bit trap handlers.
473;
474BITS 32
475%macro bs2Trap_XX_32bit_macro 1
476bs2Trap_ %+ %1 %+ _32bit:
477 push %1
478 jmp bs2Trap_XX_32bit
479%endmacro
480%macro bs2Trap_XX_32bit_macro_no_err 1
481bs2Trap_ %+ %1 %+ _32bit:
482 push 0
483 push %1
484 jmp bs2Trap_XX_32bit
485%endmacro
486 bs2Trap_XX_32bit_macro_no_err 00h
487 bs2Trap_XX_32bit_macro_no_err 01h
488 bs2Trap_XX_32bit_macro_no_err 02h
489 bs2Trap_XX_32bit_macro_no_err 03h
490 bs2Trap_XX_32bit_macro_no_err 04h
491 bs2Trap_XX_32bit_macro_no_err 05h
492 bs2Trap_XX_32bit_macro_no_err 06h
493 bs2Trap_XX_32bit_macro_no_err 07h
494 bs2Trap_XX_32bit_macro 08h
495 bs2Trap_XX_32bit_macro_no_err 09h
496 bs2Trap_XX_32bit_macro 0ah
497 bs2Trap_XX_32bit_macro 0bh
498 bs2Trap_XX_32bit_macro 0ch
499 bs2Trap_XX_32bit_macro 0dh
500 bs2Trap_XX_32bit_macro 0eh
501 bs2Trap_XX_32bit_macro_no_err 0fh
502 bs2Trap_XX_32bit_macro_no_err 10h
503 bs2Trap_XX_32bit_macro 11h
504 bs2Trap_XX_32bit_macro_no_err 12h
505 bs2Trap_XX_32bit_macro_no_err 13h
506 bs2Trap_XX_32bit_macro_no_err 14h
507 bs2Trap_XX_32bit_macro_no_err 15h
508 bs2Trap_XX_32bit_macro_no_err 16h
509 bs2Trap_XX_32bit_macro_no_err 17h
510 bs2Trap_XX_32bit_macro_no_err 18h
511 bs2Trap_XX_32bit_macro_no_err 19h
512 bs2Trap_XX_32bit_macro_no_err 1ah
513 bs2Trap_XX_32bit_macro_no_err 1bh
514 bs2Trap_XX_32bit_macro_no_err 1ch
515 bs2Trap_XX_32bit_macro_no_err 1dh
516 bs2Trap_XX_32bit_macro_no_err 1eh
517 bs2Trap_XX_32bit_macro_no_err 1fh
518
519;;
520; Common 32-bit trap handler.
521;
522; return GS ebp + 2ch - v86
523; return FS ebp + 28h - v86
524; return DS ebp + 24h - v86
525; return ES ebp + 20h - v86
526; return SS ebp + 1ch - higher privilege
527; return ESP ebp + 18h - higher privilege
528; return EFLAGS ebp + 14h
529; return CS ebp + 10h
530; return EIP ebp + 0ch
531; error code ebp + 08h
532; vector # ebp + 04h
533BITS 32
534BEGINCODEHIGH
535BEGINPROC bs2Trap_XX_32bit
536 push ebp ; ebp + 00h
537 mov ebp, esp
538 pushfd ; ebp - 04h
539 push eax ; ebp - 08h
540 push ebx ; ebp - 0ch
541 push ecx ; ebp - 10h
542 push ds ; ebp - 14h
543
544 mov eax, ss ; load flat DS. Using SS here because of conforming IDTE.CS tests.
545 mov ds, ax
546
547 pushfd ; Clear the AC flag.
548 and dword [esp], ~X86_EFL_AC
549 popfd
550
551 ;
552 ; Benchmark mode? Then resume the action right away!
553 ;
554 mov eax, [ebp + 04h]
555 cmp [g_u8TrapBenchmarkNo], al
556 jne .test_mode
557 cmp byte [g_fTrapPrepared], 0
558 je .test_mode
559 mov eax, [g_TrapResumeRIP]
560 mov [ebp + 0ch], eax
561
562 pop ds
563 pop ecx
564 pop ebx
565 ;pop eax
566 ;popfd
567 leave
568 add esp, 08h ; Skip the vector # and error code.
569 xor eax, eax
570 iret
571
572
573 ;
574 ; Update the globals.
575 ;
576.test_mode:
577 xor ecx, ecx ; zero register
578 inc dword [g_u32cTraps]
579 mov eax, [ebp + 04h]
580 mov [g_u8LastTrapNo], al
581 mov eax, [ebp + 08h]
582 mov [g_u64LastTrapErr], eax
583 mov [g_u64LastTrapErr + 4], ecx
584 mov eax, [ebp - 04h]
585 mov [g_u64LastTrapHandlerRFlags], eax
586 mov dword [g_u64LastTrapHandlerRFlags + 4], ecx
587 mov ax, cs
588 mov [g_u16LastTrapHandlerCS], ax
589 mov ax, ss
590 mov [g_u16LastTrapHandlerSS], ax
591 lea eax, [ebp + 4]
592 mov [g_u64LastTrapHandlerRSP], eax
593 mov [g_u64LastTrapHandlerRSP + 4], ecx
594
595 ;
596 ; Save the registers.
597 ;
598 lea ebx, [g_LastTrapRegs]
599 mov eax, [ebp - 08h]
600 mov [ebx + BS2REGS.rax], eax
601 mov [ebx + BS2REGS.rax + 4], ecx
602 mov eax, [ebp - 0ch]
603 mov [ebx + BS2REGS.rbx], eax
604 mov [ebx + BS2REGS.rbx + 4], ecx
605 mov eax, [ebp - 10h]
606 mov [ebx + BS2REGS.rcx], eax
607 mov [ebx + BS2REGS.rcx + 4], ecx
608 mov [ebx + BS2REGS.rdx], edx
609 mov [ebx + BS2REGS.rdx + 4], ecx
610 mov [ebx + BS2REGS.rdi], edi
611 mov [ebx + BS2REGS.rdi + 4], ecx
612 mov [ebx + BS2REGS.rsi], esi
613 mov [ebx + BS2REGS.rsi + 4], ecx
614 mov eax, [ebp]
615 mov [ebx + BS2REGS.rbp], eax
616 mov [ebx + BS2REGS.rbp + 4], ecx
617 mov eax, [ebp + 0ch]
618 mov [ebx + BS2REGS.rip], eax
619 mov [ebx + BS2REGS.rip + 4], ecx
620 mov [ebx + BS2REGS.r8], ecx
621 mov [ebx + BS2REGS.r8 + 4], ecx
622 mov [ebx + BS2REGS.r9], ecx
623 mov [ebx + BS2REGS.r9 + 4], ecx
624 mov [ebx + BS2REGS.r10], ecx
625 mov [ebx + BS2REGS.r10 + 4], ecx
626 mov [ebx + BS2REGS.r11], ecx
627 mov [ebx + BS2REGS.r11 + 4], ecx
628 mov [ebx + BS2REGS.r12], ecx
629 mov [ebx + BS2REGS.r12 + 4], ecx
630 mov [ebx + BS2REGS.r13], ecx
631 mov [ebx + BS2REGS.r13 + 4], ecx
632 mov [ebx + BS2REGS.r14], ecx
633 mov [ebx + BS2REGS.r14 + 4], ecx
634 mov [ebx + BS2REGS.r15], ecx
635 mov [ebx + BS2REGS.r15 + 4], ecx
636 mov eax, [ebp + 14h]
637 mov [ebx + BS2REGS.rflags], eax
638 mov [ebx + BS2REGS.rflags+4],ecx
639 mov eax, [ebp + 10h]
640 mov [ebx + BS2REGS.cs], ax
641 mov [ebx + BS2REGS.cBits], byte 32
642
643 ; Part of the stack varies depending on the trap context.
644 test dword [ebx + BS2REGS.rflags], X86_EFL_VM
645 jnz .v86
646 test ax, 7h
647 jz .ring0
648
649.ring0:
650 lea eax, [ebp + 18h]
651 mov [ebx + BS2REGS.rsp], eax
652 mov [ebx + BS2REGS.rsp + 4], ecx
653 mov [ebx + BS2REGS.ss], ss
654 mov eax, [ebp - 14h]
655 mov [ebx + BS2REGS.ds], ax
656 mov [ebx + BS2REGS.es], es
657 mov [ebx + BS2REGS.fs], fs
658 mov [ebx + BS2REGS.gs], gs
659 jmp .do_crX
660
661.higher_privilege:
662 mov eax, [ebp + 18h]
663 mov [ebx + BS2REGS.rsp], eax
664 mov [ebx + BS2REGS.rsp + 4], ecx
665 mov eax, [ebp + 20h]
666 mov [ebx + BS2REGS.ss], ax
667 mov eax, [ebp - 14h]
668 mov [ebx + BS2REGS.ds], ax
669 mov [ebx + BS2REGS.es], es
670 mov [ebx + BS2REGS.fs], fs
671 mov [ebx + BS2REGS.gs], gs
672 jmp .do_crX
673
674.v86:
675 mov eax, [ebp + 18h]
676 mov [ebx + BS2REGS.rsp], eax
677 mov [ebx + BS2REGS.rsp + 4], ecx
678 mov eax, [ebp + 1ch]
679 mov [ebx + BS2REGS.ss], ax
680 mov eax, [ebp + 24h]
681 mov [ebx + BS2REGS.ds], ax
682 mov eax, [ebp + 20h]
683 mov [ebx + BS2REGS.es], ax
684 mov eax, [ebp + 28h]
685 mov [ebx + BS2REGS.fs], ax
686 mov eax, [ebp + 2ch]
687 mov [ebx + BS2REGS.gs], ax
688 ;jmp .do_crX
689
690.do_crX:
691 ; The CRx registers are only accessible from ring-0 (CS=conforming, CPL < 0)
692 test byte [ebx + BS2REGS.ss], 3
693 jnz .skip_crX
694 mov eax, cr0
695 mov [ebx + BS2REGS.cr0], eax
696 mov [ebx + BS2REGS.cr0 + 4], ecx
697 mov eax, cr2
698 mov [ebx + BS2REGS.cr2], eax
699 mov [ebx + BS2REGS.cr2 + 4], ecx
700 mov eax, cr3
701 mov [ebx + BS2REGS.cr3], eax
702 mov [ebx + BS2REGS.cr3 + 4], ecx
703 mov eax, cr4
704 mov [ebx + BS2REGS.cr4], eax
705 mov [ebx + BS2REGS.cr4 + 4], ecx
706 mov [ebx + BS2REGS.cr8], ecx
707 mov [ebx + BS2REGS.cr8 + 4], ecx
708.skip_crX:
709
710 ;
711 ; Advance to a prepared resume position or panic.
712 ;
713 cmp byte [g_fTrapPrepared], 0
714 je .no_resume_pos
715 mov byte [g_fTrapPrepared], 0
716 mov eax, [g_TrapResumeRIP]
717 mov [ebp + 0ch], eax
718
719.resume:
720%ifdef BS2_WITH_XCPT_DB_CLEARING_TF
721 cmp byte [ebp + 04h], X86_XCPT_DB ; make sure we won't trap again due to a TF.
722 jne .resume_no_clear_trap_flags
723 and word [ebp + 14h], ~X86_EFL_TF
724.resume_no_clear_trap_flags:
725%endif
726 pop ds
727 pop ecx
728 pop ebx
729 pop eax
730 ;popfd
731 leave
732 add esp, 8h
733 iret
734
735
736.no_resume_pos:
737 ;
738 ; Look for a trap record.
739 ;
740 mov ecx, [g_cTrapRecs] ; the number of records.
741 test ecx, ecx
742 jz .panic
743 mov eax, [g_LastTrapRegs + BS2REGS.rip]
744 sub eax, [g_pTrapRecBase] ; the offWhere we're looking for.
745 jb .panic
746
747 ; Look starting at the previous record first.
748 mov ebx, [g_iTrapRecLast]
749 sub ecx, ebx
750 jbe .traprec_loop2 ; g_iTrapRecLast is out of range.
751 shl ebx, BS2TRAPREC_SIZE_SHIFT
752 add ebx, [g_paTrapRecs] ; ebx points to the record we hit last time.
753.traprec_loop1_next:
754 cmp [ebx + BS2TRAPREC.offWhere], eax
755 je .traprec_found
756 add ebx, BS2TRAPREC_size
757 dec ecx
758 jnz .traprec_loop1_next
759
760 ; Start searching from the start, stopping at the previous record.
761.traprec_loop2:
762 mov ecx, [g_iTrapRecLast]
763 or ecx, ecx
764 jz .panic ; not found.
765 mov ebx, [g_paTrapRecs]
766.traprec_loop2_next:
767 cmp [ebx + BS2TRAPREC.offWhere], eax
768 je .traprec_found
769 add ebx, BS2TRAPREC_size
770 dec ecx
771 jnz .traprec_loop2_next
772 jmp .panic ; not found
773
774.traprec_found:
775 ; Remember the hit for the next trap.
776 mov eax, ebx
777 sub eax, [g_paTrapRecs]
778 shr eax, BS2TRAPREC_SIZE_SHIFT
779 mov [g_iTrapRecLast], eax
780
781 ;
782 ; Fail the test if we got the wrong trap or error code.
783 ;
784 mov al, [g_u8LastTrapNo]
785 cmp al, [ebx + BS2TRAPREC.u8TrapNo]
786 je .traprec_ok_trap
787 push eax
788 movzx eax, byte [ebx + BS2TRAPREC.u8TrapNo]
789 push eax
790 push .s_szWrongTrap
791 call NAME(TestFailedF_p32)
792 add esp, 12
793
794.traprec_ok_trap:
795 mov ax, [g_u64LastTrapErr]
796 cmp ax, [ebx + BS2TRAPREC.u16ErrCd]
797 je .traprec_ok_err_cd
798 push eax
799 movzx eax, word [ebx + BS2TRAPREC.u16ErrCd]
800 push eax
801 push .s_szWrongErrCd
802 call NAME(TestFailedF_p32)
803 add esp, 12
804
805.traprec_ok_err_cd:
806 ;
807 ; Advance the EIP and resume execution.
808 ;
809 movzx eax, byte [ebx + BS2TRAPREC.offResumeAddend]
810 add eax, [g_LastTrapRegs + BS2REGS.rip]
811 mov [ebp + 0ch], eax
812 jmp .resume
813
814
815 ;
816 ; Write panic message and then halt.
817 ;
818.panic:
819 push dword [g_LastTrapRegs + BS2REGS.rflags]
820 push dword [g_LastTrapRegs + BS2REGS.ss]
821 push dword [g_LastTrapRegs + BS2REGS.gs]
822 push dword [g_LastTrapRegs + BS2REGS.fs]
823 push dword [g_LastTrapRegs + BS2REGS.es]
824 push dword [g_LastTrapRegs + BS2REGS.ds]
825 push dword [g_LastTrapRegs + BS2REGS.cs]
826 ; line break
827 push dword [g_LastTrapRegs + BS2REGS.cr4]
828 push dword [g_LastTrapRegs + BS2REGS.cr3]
829 push dword [g_LastTrapRegs + BS2REGS.cr0]
830 push dword [g_LastTrapRegs + BS2REGS.rbp]
831 push dword [g_LastTrapRegs + BS2REGS.rsp]
832 push dword [g_LastTrapRegs + BS2REGS.rip]
833 ; line break
834 push dword [g_LastTrapRegs + BS2REGS.rdi]
835 push dword [g_LastTrapRegs + BS2REGS.rsi]
836 push dword [g_LastTrapRegs + BS2REGS.rdx]
837 push dword [g_LastTrapRegs + BS2REGS.rcx]
838 push dword [g_LastTrapRegs + BS2REGS.rbx]
839 push dword [g_LastTrapRegs + BS2REGS.rax]
840 ; line break
841 mov eax, [ebp + 08h]
842 push eax
843 mov eax, cr2
844 push eax
845 mov eax, [ebp + 0ch]
846 push eax
847 movzx eax, word [ebp + 10h]
848 push eax
849 movzx eax, byte [ebp + 04h]
850 push eax
851 push .s_szPanicMsg
852 call NAME(TestFailedF_p32)
853
854 call Bs2Panic
855 jmp .panic ; paranoia
856
857.s_szPanicMsg:
858 db 'trap #%RX8 at %RX16:%RX32 cr2=%RX32 err=%RX32', 13, 10
859 db 'eax=%RX32 ebx=%RX32 ecx=%RX32 edx=%RX32 esi=%RX32 edi=%RX32', 13, 10
860 db 'eip=%RX32 esp=%RX32 ebp=%RX32 cr0=%RX32 cr3=%RX32 cr4=%RX32', 13, 10
861 db 'cs=%RX16 ds=%RX16 es=%RX16 fs=%RX16 gs=%RX16 ss=%RX16 eflags=%RX32', 13, 10
862 db 0
863.s_szWrongTrap:
864 db 'Expected trap %RX8 got %RX8', 13, 10, 0
865.s_szWrongErrCd:
866 db 'Expected errcd %RX16 got %RX16', 13, 10, 0
867ENDPROC bs2Trap_XX_32bit
868
869;;
870; Service IRQ handler, 32-bit version.
871;
872; Takes requests in eax and later maybe parameters in other registers.
873;
874; return GS ebp + 24h - v86
875; return FS ebp + 20h - v86
876; return DS ebp + 1ch - v86
877; return ES ebp + 18h - v86
878; return SS ebp + 14h - higher privilege
879; return ESP ebp + 10h - higher privilege
880; return EFLAGS ebp + 0ch
881; return CS ebp + 08h
882; return EIP ebp + 04h
883BEGINCODELOW
884BEGINPROC bs2TrapService32bit
885 jmp .highsegment
886BEGINCODEHIGH
887.highsegment:
888 push ebp ; ebp
889 mov ebp, esp
890 push eax ; ebp - 04h
891 push edx ; ebp - 08h
892 push ecx ; ebp - 0ch
893 push ebx ; ebp - 10h
894 push ds ; ebp - 14h
895
896 mov dx, ss
897 mov ds, dx
898
899 ;
900 ; Classify the caller context in cl.
901 ;; @todo What if CS on the stack is conforming?
902 ;
903%define BS2_TRP_SRV_CALLER_SAME_RING 0
904%define BS2_TRP_SRV_CALLER_OTHER_RING 1
905%define BS2_TRP_SRV_CALLER_VM 2
906 test dword [ebp + 0ch], X86_EFL_VM
907 jnz .vm_ctx
908
909 mov cx, ss
910 mov ch, [ebp + 08h] ; cs
911 and cx, 00303h
912 cmp ch, cl
913 jz .same_ctx
914 mov cl, BS2_TRP_SRV_CALLER_OTHER_RING
915 jmp .done_ctx
916.vm_ctx:
917 mov cl, BS2_TRP_SRV_CALLER_VM
918 jmp .done_ctx
919.same_ctx:
920 mov cl, BS2_TRP_SRV_CALLER_SAME_RING
921.done_ctx:
922
923 ;
924 ; Switch (eax).
925 ;
926 cmp eax, BS2_SYSCALL_TO_RING3
927 jbe .to_ringX
928
929 ; Unknown request.
930.failure:
931 mov eax, -1
932.return: ; careful with ebp here!
933 pop ds
934 pop ebx
935 pop ecx
936 pop edx
937 ;pop eax
938 leave
939 iretd
940
941 ;
942 ; Switching to the ring specified by eax.
943 ; Annoying that ss:esp isn't always restored.
944 ;
945.to_ringX:
946 cmp cl, BS2_TRP_SRV_CALLER_VM
947 je .failure
948 sub al, BS2_SYSCALL_TO_RING0
949
950 ; Fake missing stack registers if necessary.
951 cmp cl, BS2_TRP_SRV_CALLER_SAME_RING
952 jnz .have_stack_regs
953
954 sub esp, 8h
955 sub ebp, 8h
956 xor ebx, ebx
957.move_more:
958 mov edx, [esp + 8 + ebx]
959 mov [esp + ebx], edx
960 add ebx, 4
961 cmp ebx, 9*4
962 jb .move_more
963
964 mov dx, ss
965 mov [ebp + 14h], edx
966 lea edx, [ebp + 18h]
967 mov [ebp + 10h], edx
968
969.have_stack_regs:
970 ; Translate the selector registers
971 mov dx, [ebp - 14h]
972 call bs2SRegToRing
973 mov [ebp - 14h], dx
974
975 mov dx, es
976 call bs2SRegToRing
977 mov es, dx
978
979 mov dx, fs
980 call bs2SRegToRing
981 mov fs, dx
982
983 mov dx, gs
984 call bs2SRegToRing
985 mov gs, dx
986
987 mov dx, [ebp + 08h] ; cs
988 call bs2SRegToRing
989 mov [ebp + 08h], dx
990
991 mov dx, [ebp + 14h] ; ss
992 call bs2SRegToRing
993 mov [ebp + 14h], dx
994
995 or dword [ebp + 0ch], X86_EFL_IOPL ; set IOPL=3
996
997 ; If the desired target is ring-0 we cannot use iret.
998 cmp al, 0
999 je .iret_to_ring_with_stack
1000
1001.done_success:
1002 xor eax, eax
1003 jmp .return
1004
1005.iret_to_ring_with_stack:
1006 ;
1007 ; Move the iret-to-same-ring to the desired return position. By also
1008 ; moving the saved ebp we make the leave instruction do stack
1009 ; adjusting/switching for us.
1010 ;
1011 cli ; paranoia, it's disable already.
1012 mov eax, [ebp + 10h]
1013 lea edx, [ebp + 18h]
1014 cmp eax, edx
1015 lea ecx, [ebp + 08h] ; same stack, just shifted 8 bytes
1016 je .move_iret_and_ebp
1017 mov ecx, [ebp + 10h] ; different stack.
1018 sub ecx, 10h
1019.move_iret_and_ebp:
1020 mov edx, [ebp + 0ch]
1021 mov eax, [ebp + 08h]
1022 mov [ecx + 0ch], edx
1023 mov [ecx + 08h], eax
1024 mov edx, [ebp + 04h]
1025 mov eax, [ebp + 00h]
1026 mov [ecx + 04h], edx
1027 mov [ecx + 00h], eax
1028 mov ebp, ecx
1029 xor eax, eax
1030 jmp .return
1031
1032ENDPROC bs2TrapService32bit
1033
1034%endif ; BS2_INC_CMN_PM
1035
1036
1037%ifdef BS2_INC_CMN_LM
1038;
1039; 64-bit TSS (X86TSS64).
1040;
1041BEGINCODELOW
1042ALIGNDATA(16)
1043bs2Tss64Bit:
1044 dd 0 ; 00h - u32Reserved - Reserved.
1045 dq BS2_R0_STACK_ADDR ; 04h - rsp0 - Ring-0 stack pointer. (static)
1046 dq BS2_R1_STACK_ADDR ; 1ch - rsp1 - Ring-1 stack pointer. (static)
1047 dq BS2_R2_STACK_ADDR ; 14h - rsp2 - Ring-2 stack pointer. (static)
1048 dq 0 ; 2ch - reserved
1049 dq BS2_DF_R0_STACK_ADDR ; 24h - ist1;
1050 dq BS2_R0_STACK_ADDR ; 3ch - ist2;
1051 dq BS2_R0_STACK_ADDR ; 34h - ist3;
1052 dq BS2_R0_STACK_ADDR ; 4ch - ist4;
1053 dq BS2_R0_STACK_ADDR ; 44h - ist5;
1054 dq BS2_R0_STACK_ADDR ; 5ch - ist6;
1055 dq BS2_R0_STACK_ADDR ; 54h - ist7;
1056 dw 0,0,0,0,0 ; 6ch - reserved
1057 dw 0 ; 76h - offIoBitmap - Offset relative to the TSS of the
1058 ; 00h - start of the I/O Bitmap and the end of the
1059 ; 00h - interrupt redirection bitmap.
1060bs2Tss64BitEnd:
1061times (68h - (bs2Tss64BitEnd - bs2Tss64Bit)) db 0
1062times ((bs2Tss64BitEnd - bs2Tss64Bit) - 68h) db 0
1063
1064;
1065; 64-bit IDT (X86DESC64GATE).
1066;
1067BEGINCODELOW
1068ALIGNDATA(16)
1069bs2Idt64bit:
1070 dw bs2Trap_00h_64bit, BS2_SEL_CS64, 08e00h, 00000h, 0, 0, 0, 0 ; p=1 dpl=0 type=int64gate
1071 dw bs2Trap_01h_64bit, BS2_SEL_CS64, 08e00h, 00000h, 0, 0, 0, 0 ; p=1 dpl=0 type=int64gate
1072 dw bs2Trap_02h_64bit, BS2_SEL_CS64, 08e00h, 00000h, 0, 0, 0, 0 ; p=1 dpl=0 type=int64gate
1073bs2Idt64bit_BP:
1074 dw bs2Trap_03h_64bit, BS2_SEL_CS64, 08e00h, 00000h, 0, 0, 0, 0 ; p=1 dpl=0 type=int64gate
1075 dw bs2Trap_04h_64bit, BS2_SEL_CS64, 08e00h, 00000h, 0, 0, 0, 0 ; p=1 dpl=0 type=int64gate
1076 dw bs2Trap_05h_64bit, BS2_SEL_CS64, 08e00h, 00000h, 0, 0, 0, 0 ; p=1 dpl=0 type=int64gate
1077 dw bs2Trap_06h_64bit, BS2_SEL_CS64, 08e00h, 00000h, 0, 0, 0, 0 ; p=1 dpl=0 type=int64gate
1078 dw bs2Trap_07h_64bit, BS2_SEL_CS64, 08e00h, 00000h, 0, 0, 0, 0 ; p=1 dpl=0 type=int64gate
1079 dw bs2Trap_08h_64bit, BS2_SEL_CS64, 08e00h, 00000h, 0, 0, 0, 0 ; p=1 dpl=0 type=int64gate
1080 dw bs2Trap_09h_64bit, BS2_SEL_CS64, 08e00h, 00000h, 0, 0, 0, 0 ; p=1 dpl=0 type=int64gate
1081 dw bs2Trap_0ah_64bit, BS2_SEL_CS64, 08e00h, 00000h, 0, 0, 0, 0 ; p=1 dpl=0 type=int64gate
1082 dw bs2Trap_0bh_64bit, BS2_SEL_CS64, 08e00h, 00000h, 0, 0, 0, 0 ; p=1 dpl=0 type=int64gate
1083 dw bs2Trap_0ch_64bit, BS2_SEL_CS64, 08e00h, 00000h, 0, 0, 0, 0 ; p=1 dpl=0 type=int64gate
1084 dw bs2Trap_0dh_64bit, BS2_SEL_CS64, 08e00h, 00000h, 0, 0, 0, 0 ; p=1 dpl=0 type=int64gate
1085 dw bs2Trap_0eh_64bit, BS2_SEL_CS64, 08e00h, 00000h, 0, 0, 0, 0 ; p=1 dpl=0 type=int64gate
1086 dw bs2Trap_0fh_64bit, BS2_SEL_CS64, 08e00h, 00000h, 0, 0, 0, 0 ; p=1 dpl=0 type=int64gate
1087 dw bs2Trap_10h_64bit, BS2_SEL_CS64, 08e00h, 00000h, 0, 0, 0, 0 ; p=1 dpl=0 type=int64gate
1088 dw bs2Trap_11h_64bit, BS2_SEL_CS64, 08e00h, 00000h, 0, 0, 0, 0 ; p=1 dpl=0 type=int64gate
1089 dw bs2Trap_12h_64bit, BS2_SEL_CS64, 08e00h, 00000h, 0, 0, 0, 0 ; p=1 dpl=0 type=int64gate
1090 dw bs2Trap_13h_64bit, BS2_SEL_CS64, 08e00h, 00000h, 0, 0, 0, 0 ; p=1 dpl=0 type=int64gate
1091 dw bs2Trap_14h_64bit, BS2_SEL_CS64, 08e00h, 00000h, 0, 0, 0, 0 ; p=1 dpl=0 type=int64gate
1092 dw bs2Trap_15h_64bit, BS2_SEL_CS64, 08e00h, 00000h, 0, 0, 0, 0 ; p=1 dpl=0 type=int64gate
1093 dw bs2Trap_16h_64bit, BS2_SEL_CS64, 08e00h, 00000h, 0, 0, 0, 0 ; p=1 dpl=0 type=int64gate
1094 dw bs2Trap_17h_64bit, BS2_SEL_CS64, 08e00h, 00000h, 0, 0, 0, 0 ; p=1 dpl=0 type=int64gate
1095 dw bs2Trap_18h_64bit, BS2_SEL_CS64, 08e00h, 00000h, 0, 0, 0, 0 ; p=1 dpl=0 type=int64gate
1096 dw bs2Trap_19h_64bit, BS2_SEL_CS64, 08e00h, 00000h, 0, 0, 0, 0 ; p=1 dpl=0 type=int64gate
1097 dw bs2Trap_1ah_64bit, BS2_SEL_CS64, 08e00h, 00000h, 0, 0, 0, 0 ; p=1 dpl=0 type=int64gate
1098 dw bs2Trap_1bh_64bit, BS2_SEL_CS64, 08e00h, 00000h, 0, 0, 0, 0 ; p=1 dpl=0 type=int64gate
1099 dw bs2Trap_1ch_64bit, BS2_SEL_CS64, 08e00h, 00000h, 0, 0, 0, 0 ; p=1 dpl=0 type=int64gate
1100 dw bs2Trap_1dh_64bit, BS2_SEL_CS64, 08e00h, 00000h, 0, 0, 0, 0 ; p=1 dpl=0 type=int64gate
1101 dw bs2Trap_1eh_64bit, BS2_SEL_CS64, 08e00h, 00000h, 0, 0, 0, 0 ; p=1 dpl=0 type=int64gate
1102 dw bs2Trap_1fh_64bit, BS2_SEL_CS64, 08e00h, 00000h, 0, 0, 0, 0 ; p=1 dpl=0 type=int64gate
1103 dw bs2TrapService64bit,BS2_SEL_CS64,0ee00h, 00000h, 0, 0, 0, 0 ; p=1 dpl=3 type=int64gate
1104bs2Idt64bitEnd
1105
1106
1107;
1108; 64-bit trap handlers.
1109;
1110BITS 64
1111%macro bs2Trap_XX_64bit_macro 1
1112BEGINCODELOW
1113bs2Trap_ %+ %1 %+ _64bit:
1114 push %1
1115 jmp bs2Trap_XX_64bit
1116%endmacro
1117%macro bs2Trap_XX_64bit_macro_no_err 1
1118bs2Trap_ %+ %1 %+ _64bit:
1119 push 0
1120 push %1
1121 jmp bs2Trap_XX_64bit
1122%endmacro
1123 bs2Trap_XX_64bit_macro_no_err 00h
1124 bs2Trap_XX_64bit_macro_no_err 01h
1125 bs2Trap_XX_64bit_macro_no_err 02h
1126 bs2Trap_XX_64bit_macro_no_err 03h
1127 bs2Trap_XX_64bit_macro_no_err 04h
1128 bs2Trap_XX_64bit_macro_no_err 05h
1129 bs2Trap_XX_64bit_macro_no_err 06h
1130 bs2Trap_XX_64bit_macro_no_err 07h
1131 bs2Trap_XX_64bit_macro 08h
1132 bs2Trap_XX_64bit_macro_no_err 09h
1133 bs2Trap_XX_64bit_macro 0ah
1134 bs2Trap_XX_64bit_macro 0bh
1135 bs2Trap_XX_64bit_macro 0ch
1136 bs2Trap_XX_64bit_macro 0dh
1137 bs2Trap_XX_64bit_macro 0eh
1138 bs2Trap_XX_64bit_macro_no_err 0fh
1139 bs2Trap_XX_64bit_macro_no_err 10h
1140 bs2Trap_XX_64bit_macro 11h
1141 bs2Trap_XX_64bit_macro_no_err 12h
1142 bs2Trap_XX_64bit_macro_no_err 13h
1143 bs2Trap_XX_64bit_macro_no_err 14h
1144 bs2Trap_XX_64bit_macro_no_err 15h
1145 bs2Trap_XX_64bit_macro_no_err 16h
1146 bs2Trap_XX_64bit_macro_no_err 17h
1147 bs2Trap_XX_64bit_macro_no_err 18h
1148 bs2Trap_XX_64bit_macro_no_err 19h
1149 bs2Trap_XX_64bit_macro_no_err 1ah
1150 bs2Trap_XX_64bit_macro_no_err 1bh
1151 bs2Trap_XX_64bit_macro_no_err 1ch
1152 bs2Trap_XX_64bit_macro_no_err 1dh
1153 bs2Trap_XX_64bit_macro_no_err 1eh
1154 bs2Trap_XX_64bit_macro_no_err 1fh
1155
1156;;
1157; Common 64-bit trap handler.
1158;
1159; return SS rbp + 38h
1160; return RSP rbp + 30h
1161; return RFLAGS rbp + 28h
1162; return CS rbp + 20h
1163; return RIP rbp + 18h
1164; error code rbp + 10h
1165; vector # rbp + 08h
1166BEGINCODEHIGH
1167BEGINPROC bs2Trap_XX_64bit
1168 push rbp ; rbp + 00h
1169 mov rbp, rsp
1170 pushfq ; rbp - 08h
1171 push rax ; rbp - 10h
1172 push rbx ; rbp - 18h
1173
1174 ;
1175 ; Benchmark mode? Then resume the action right away!
1176 ;
1177 mov rax, [rbp + 08h]
1178 cmp [g_u8TrapBenchmarkNo], al
1179 jne .test_mode
1180 cmp byte [g_fTrapPrepared], 0
1181 je .test_mode
1182 mov rax, [g_TrapResumeRIP]
1183 mov [rbp + 18h], rax
1184
1185 pop rbx
1186 ;pop rax
1187 ;popfq
1188 leave
1189 add rsp, 10h ; Skip the vector # and error code.
1190 xor rax, rax
1191 iretq
1192
1193 ;
1194 ; Save the trap information
1195 ;
1196.test_mode:
1197 inc dword [g_u32cTraps]
1198 mov rax, [rbp + 08h]
1199 mov [g_u8LastTrapNo], al
1200 mov rax, [rbp + 10h]
1201 mov [g_u64LastTrapErr], rax
1202 mov rax, [rbp - 08h]
1203 mov [g_u64LastTrapHandlerRFlags], rax
1204 mov ax, cs
1205 mov [g_u16LastTrapHandlerCS], ax
1206 mov ax, ss
1207 mov [g_u16LastTrapHandlerSS], ax
1208 lea rax, [rbp + 8]
1209 mov [g_u64LastTrapHandlerRSP], rax
1210
1211 ; Save the registers.
1212 lea rbx, [g_LastTrapRegs]
1213 mov rax, [rbp - 10h]
1214 mov [rbx + BS2REGS.rax], rax
1215 mov rax, [rbp - 18h]
1216 mov [rbx + BS2REGS.rbx], rax
1217 mov [rbx + BS2REGS.rcx], rcx
1218 mov [rbx + BS2REGS.rdx], rdx
1219 mov [rbx + BS2REGS.rdi], rdi
1220 mov [rbx + BS2REGS.rsi], rsi
1221 mov rax, [rbp]
1222 mov [rbx + BS2REGS.rbp], rax
1223 mov rax, [rbp + 30h]
1224 mov [rbx + BS2REGS.rsp], rax
1225 mov rax, [rbp + 18h]
1226 mov [rbx + BS2REGS.rip], rax
1227 mov [rbx + BS2REGS.r8], r8
1228 mov [rbx + BS2REGS.r9], r9
1229 mov [rbx + BS2REGS.r10], r10
1230 mov [rbx + BS2REGS.r11], r11
1231 mov [rbx + BS2REGS.r12], r12
1232 mov [rbx + BS2REGS.r13], r13
1233 mov [rbx + BS2REGS.r14], r14
1234 mov [rbx + BS2REGS.r15], r15
1235 mov rax, [rbp + 28h]
1236 mov [rbx + BS2REGS.rflags], rax
1237 mov rax, [rbp + 20h]
1238 mov [rbx + BS2REGS.cs], ax
1239 mov [rbx + BS2REGS.ds], ds
1240 mov [rbx + BS2REGS.es], es
1241 mov [rbx + BS2REGS.fs], fs
1242 mov [rbx + BS2REGS.gs], gs
1243 mov rax, [rbp + 38h]
1244 mov [rbx + BS2REGS.ss], ax
1245 mov [rbx + BS2REGS.cBits], byte 64
1246
1247 ; The CRx registers are only accessible from ring-0 (CS=conforming, CPL < 0)
1248 test byte [rbx + BS2REGS.ss], 3
1249 jnz .skip_crX
1250 mov rax, cr0
1251 mov [rbx + BS2REGS.cr0], rax
1252 mov rax, cr2
1253 mov [rbx + BS2REGS.cr2], rax
1254 mov rax, cr3
1255 mov [rbx + BS2REGS.cr3], rax
1256 mov rax, cr4
1257 mov [rbx + BS2REGS.cr4], rax
1258 mov rax, cr8
1259 mov [rbx + BS2REGS.cr8], rax
1260.skip_crX:
1261
1262 ;
1263 ; Advance to a prepared resume position or panic.
1264 ;
1265 cmp byte [g_fTrapPrepared], 0
1266 je .no_resume_pos
1267 mov byte [g_fTrapPrepared], 0
1268 mov rax, [g_TrapResumeRIP]
1269 mov [rbp + 18h], rax
1270 jmp .resume
1271
1272.resume:
1273%ifdef BS2_WITH_XCPT_DB_CLEARING_TF
1274 cmp byte [rbp + 08h], X86_XCPT_DB ; make sure we won't trap again due to a TF.
1275 jne .resume_no_clear_trap_flags
1276 and word [rbp + 28h], ~X86_EFL_TF
1277.resume_no_clear_trap_flags:
1278%endif
1279 pop rbx
1280 pop rax
1281 ;popfq
1282 leave
1283 add rsp, 10h
1284 iretq
1285
1286
1287.no_resume_pos:
1288 ;
1289 ; Look for a trap record.
1290 ;
1291 push rcx
1292
1293 mov ecx, [g_cTrapRecs] ; the number of records.
1294 test ecx, ecx
1295 jz .panic
1296 mov rax, [g_LastTrapRegs + BS2REGS.rip]
1297 sub rax, [g_pTrapRecBase] ; the offWhere we're looking for.
1298 jb .panic
1299 mov rbx, _4G
1300 cmp rax, rbx
1301 jae .panic ; out of range.
1302
1303 ; Look starting at the previous record first.
1304 mov ebx, [g_iTrapRecLast]
1305 sub ecx, ebx
1306 jbe .traprec_loop2 ; g_iTrapRecLast is out of range.
1307 shl rbx, BS2TRAPREC_SIZE_SHIFT
1308 add rbx, [g_paTrapRecs] ; ebx points to the record we hit last time.
1309.traprec_loop1_next:
1310 cmp [rbx + BS2TRAPREC.offWhere], eax
1311 je .traprec_found
1312 add rbx, BS2TRAPREC_size
1313 dec ecx
1314 jnz .traprec_loop1_next
1315
1316 ; Start searching from the start, stopping at the previous record.
1317.traprec_loop2:
1318 mov ecx, [g_iTrapRecLast]
1319 or ecx, ecx
1320 jz .panic ; not found.
1321 mov rbx, [g_paTrapRecs]
1322.traprec_loop2_next:
1323 cmp [rbx + BS2TRAPREC.offWhere], eax
1324 je .traprec_found
1325 add rbx, BS2TRAPREC_size
1326 dec ecx
1327 jnz .traprec_loop2_next
1328 jmp .panic ; not found
1329
1330.traprec_found:
1331 ; Remember the hit for the next trap.
1332 mov rax, rbx
1333 sub rax, [g_paTrapRecs]
1334 shr rax, BS2TRAPREC_SIZE_SHIFT
1335 mov [g_iTrapRecLast], eax
1336
1337 ;
1338 ; Fail the test if we got the wrong trap or error code.
1339 ;
1340 mov al, [g_u8LastTrapNo wrt rip]
1341 cmp al, [rbx + BS2TRAPREC.u8TrapNo]
1342 je .traprec_ok_trap
1343 push rax
1344 movzx rax, byte [rbx + BS2TRAPREC.u8TrapNo]
1345 push rax
1346 push .s_szWrongTrap
1347 call NAME(TestFailedF_p64)
1348 add rsp, 24
1349
1350.traprec_ok_trap:
1351 mov ax, [g_u64LastTrapErr wrt rip]
1352 cmp ax, [rbx + BS2TRAPREC.u16ErrCd]
1353 je .traprec_ok_err_cd
1354 push rax
1355 movzx rax, word [rbx + BS2TRAPREC.u16ErrCd]
1356 push rax
1357 push .s_szWrongErrCd
1358 call NAME(TestFailedF_p64)
1359 add rsp, 24
1360
1361.traprec_ok_err_cd:
1362 ;
1363 ; Advance the EIP and resume execution.
1364 ;
1365 movzx rax, byte [rbx + BS2TRAPREC.offResumeAddend]
1366 add rax, [g_LastTrapRegs + BS2REGS.rip]
1367 mov [rbp + 18h], rax
1368
1369 pop rcx
1370 jmp .resume
1371
1372
1373 ;
1374 ; Format a panic message and halt.
1375 ;
1376.panic:
1377 lea rbx, [g_LastTrapRegs]
1378 ; line break
1379 movzx eax, word [rbx + BS2REGS.ss]
1380 push rax
1381 movzx eax, word [rbx + BS2REGS.gs]
1382 push rax
1383 movzx eax, word [rbx + BS2REGS.fs]
1384 push rax
1385 movzx eax, word [rbx + BS2REGS.es]
1386 push rax
1387 movzx eax, word [rbx + BS2REGS.ds]
1388 push rax
1389 movzx eax, word [rbx + BS2REGS.cs]
1390 push rax
1391 ; line break
1392 push qword [rbx + BS2REGS.rbp]
1393 push qword [rbx + BS2REGS.rsp]
1394 push qword [rbx + BS2REGS.rip]
1395 ; line break
1396 push qword [rbx + BS2REGS.rflags]
1397 push qword [rbx + BS2REGS.r15]
1398 push qword [rbx + BS2REGS.r14]
1399 ; line break
1400 push qword [rbx + BS2REGS.r13]
1401 push qword [rbx + BS2REGS.r12]
1402 push qword [rbx + BS2REGS.r11]
1403 ; line break
1404 push qword [rbx + BS2REGS.r10]
1405 push qword [rbx + BS2REGS.r9]
1406 push qword [rbx + BS2REGS.r8]
1407 ; line break
1408 push qword [rbx + BS2REGS.rdi]
1409 push qword [rbx + BS2REGS.rsi]
1410 push qword [rbx + BS2REGS.rdx]
1411 ; line break
1412 push qword [rbx + BS2REGS.rcx]
1413 push qword [rbx + BS2REGS.rbx]
1414 push qword [rbx + BS2REGS.rax]
1415 ; line break
1416 mov eax, [rbx + BS2REGS.cr8]
1417 push rax
1418 mov eax, [rbx + BS2REGS.cr4]
1419 push rax
1420 mov eax, [rbx + BS2REGS.cr3]
1421 push rax
1422 mov eax, [rbx + BS2REGS.cr0]
1423 push rax
1424 ; line break
1425 push qword [rbp + 10h]
1426 push qword [rbx + BS2REGS.cr2]
1427 push qword [rbx + BS2REGS.rip]
1428 movzx eax, word [rbp + BS2REGS.ss]
1429 push rax
1430 movzx eax, byte [rbp + 08h]
1431 push rax
1432 push .s_szPanicMsg
1433 call NAME(TestFailedF_p64)
1434
1435 call Bs2Panic
1436 jmp .panic ; paranoia
1437
1438.s_szPanicMsg:
1439 db 'trap #%RX8 at %RX16:%RX64 cr2=%RX64 err=%RX64', 13, 10
1440 db 'cr0=%RX64 cr3=%RX64 cr4=%RX64 cr8=%RX16', 13, 10
1441 db 'rax=%RX64 rbx=%RX64 rcx=%RX64', 13, 10
1442 db 'rdx=%RX64 rsi=%RX64 rdi=%RX64', 13, 10
1443 db 'r8 =%RX64 r9 =%RX64 r10=%RX64', 13, 10
1444 db 'r11=%RX64 r12=%RX64 r13=%RX64', 13, 10
1445 db 'r14=%RX64 r15=%RX64 rfl=%RX64', 13, 10
1446 db 'rip=%RX64 rsp=%RX64 rbp=%RX64 ', 13, 10
1447 db 'cs=%RX16 ds=%RX16 es=%RX16 fs=%RX16 gs=%RX16 ss=%RX16', 13, 10
1448 db 0
1449.s_szWrongTrap:
1450 db 'Expected trap %RX8 got %RX8', 13, 10, 0
1451.s_szWrongErrCd:
1452 db 'Expected errcd %RX16 got %RX16', 13, 10, 0
1453ENDPROC bs2Trap_XX_64bit
1454
1455
1456;;
1457; Service IRQ handler.
1458;
1459; Takes requests in eax and later maybe parameters in other registers.
1460;
1461; return SS rbp + 28h
1462; return RSP rbp + 20h
1463; return RFLAGS rbp + 18h
1464; return CS rbp + 10h
1465; return RIP rbp + 08h
1466BEGINCODELOW
1467BEGINPROC bs2TrapService64bit
1468 jmp .highsegment
1469BEGINCODEHIGH
1470.highsegment:
1471 push rbp
1472 mov rbp, rsp
1473 push rax
1474 push rdx
1475 push rcx
1476
1477
1478 ;
1479 ; Switch (eax).
1480 ;
1481 cmp eax, BS2_SYSCALL_TO_RING3
1482 jbe .to_ringX
1483
1484 ; Unknown request.
1485 mov rax, -1
1486.return:
1487 pop rcx
1488 pop rdx
1489 ;pop rax
1490 leave
1491 iretq
1492
1493 ;
1494 ; Switching to the ring specified by eax.
1495 ;
1496.to_ringX:
1497 sub eax, BS2_SYSCALL_TO_RING0 ; al = new ring number.
1498
1499 mov dx, ds
1500 call bs2SRegToRing
1501 mov ds, dx
1502
1503 mov dx, es
1504 call bs2SRegToRing
1505 mov es, dx
1506
1507 mov dx, fs
1508 call bs2SRegToRing
1509 mov fs, dx
1510
1511 mov dx, gs
1512 call bs2SRegToRing
1513 mov gs, dx
1514
1515 mov dx, [rbp + 10h] ; cs
1516 call bs2SRegToRing
1517 mov [rbp + 10h], dx
1518
1519 mov dx, [rbp + 28h] ; ss
1520 call bs2SRegToRing
1521 mov [rbp + 28h], dx
1522
1523 or dword [ebp + 18h], X86_EFL_IOPL ; set IOPL=3
1524
1525 jmp .done_success
1526
1527.done_success:
1528 xor eax, eax
1529 jmp .return
1530
1531ENDPROC bs2TrapService64bit
1532
1533%endif ; BS2_INC_CMN_LM
1534
1535
1536;;
1537; Converts a segment value (dx) to the ring specified by al.
1538;
1539; If the selector isn't a known CS, DS or SS selector it will be set to null.
1540;
1541; @returns dx
1542; @param al The desired ring.
1543; @param dx The segment to convert.
1544;
1545; @remarks WARNING! This has to work exactly the same both in 32-bit and 64-bit mode.
1546;
1547BEGINCODEHIGH
1548BITS 32
1549BEGINPROC bs2SRegToRing
1550 ;
1551 ; Classify the incoming selector.
1552 ;
1553 cmp dx, BS2_SEL_R0_BASE
1554 jb .null
1555 cmp dx, BS2_SEL_R0_BASE + BS2_SEL_GRP_SIZE
1556 jb .ring0
1557
1558 cmp dx, BS2_SEL_R1_BASE
1559 jb .miss
1560 cmp dx, BS2_SEL_R1_BASE + BS2_SEL_GRP_SIZE
1561 jb .ring1
1562
1563 cmp dx, BS2_SEL_R2_BASE
1564 jb .miss
1565 cmp dx, BS2_SEL_R2_BASE + BS2_SEL_GRP_SIZE
1566 jb .ring2
1567
1568 cmp dx, BS2_SEL_R3_BASE
1569 jb .miss
1570 cmp dx, BS2_SEL_R3_BASE + BS2_SEL_GRP_SIZE
1571 jb .ring3
1572 jmp .miss
1573
1574 ;
1575 ; Convert the incoming selector to ring-0 and then from ring-0 to the
1576 ; desired one.
1577 ;
1578.ring0:
1579 cmp al, 0
1580 je .done
1581
1582 add dx, BS2_SEL_R1_BASE - BS2_SEL_R0_BASE
1583 cmp al, 1
1584 je .done
1585
1586 add dx, BS2_SEL_R2_BASE - BS2_SEL_R1_BASE
1587 cmp al, 2
1588 je .done
1589
1590 add dx, BS2_SEL_R3_BASE - BS2_SEL_R2_BASE
1591 cmp al, 3
1592 je .done
1593.panic:
1594 hlt
1595 jmp .panic
1596
1597.ring1:
1598 sub dx, BS2_SEL_R1_BASE - BS2_SEL_R0_BASE
1599 jmp .ring0
1600.ring2:
1601 sub dx, BS2_SEL_R2_BASE - BS2_SEL_R0_BASE
1602 jmp .ring0
1603.ring3:
1604 sub dx, BS2_SEL_R3_BASE - BS2_SEL_R0_BASE
1605 jmp .ring0
1606
1607.done:
1608 and dl, ~3h
1609 or dl, al ; set the RPL
1610 ret
1611
1612.miss:
1613.null:
1614 xor dx, dx
1615 ret
1616ENDPROC bs2SRegToRing
1617
1618BEGINCODELOW
1619
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