VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c16-Trap16Generic.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: 26.3 KB
Line 
1; $Id: bs3-c16-Trap16Generic.asm 106061 2024-09-16 14:03:52Z vboxsync $
2;; @file
3; BS3Kit - Trap, 16-bit assembly handlers.
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%ifndef TMPL_16BIT
43 %error "16-bit only template"
44%endif
45
46
47;*********************************************************************************************************************************
48;* External Symbols *
49;*********************************************************************************************************************************
50BS3_EXTERN_DATA16 g_bBs3CurrentMode
51BS3_EXTERN_DATA16 g_uBs3TrapEipHint
52BS3_EXTERN_DATA16 g_uBs3CpuDetected
53BS3_EXTERN_DATA16 g_apfnBs3TrapHandlers_c16
54BS3_EXTERN_SYSTEM16 Bs3Gdt
55TMPL_BEGIN_TEXT
56BS3_EXTERN_CMN Bs3TrapDefaultHandler
57BS3_EXTERN_CMN Bs3RegCtxRestore
58TMPL_BEGIN_TEXT
59
60
61;;
62; Generic entry points for IDT handlers, 8 byte spacing.
63;
64BS3_PROC_BEGIN _Bs3Trap16GenericEntries
65BS3_PROC_BEGIN Bs3Trap16GenericEntries
66%macro Bs3Trap16GenericEntryNoErr 1
67 push byte 0 ; 2 byte: fake error code
68 db 06ah, i ; 2 byte: push imm8 - note that this is a signextended value.
69 jmp %1 ; 3 byte
70 ALIGNCODE(8)
71%assign i i+1
72%endmacro
73
74%macro Bs3Trap16GenericEntryErrCd 1
75 db 06ah, i ; 2 byte: push imm8 - note that this is a signextended value.
76 jmp %1 ; 3 byte
77 ALIGNCODE(8)
78%assign i i+1
79%endmacro
80
81%assign i 0 ; start counter.
82 Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 0
83 Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 1
84 Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 2
85 Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 3
86 Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 4
87 Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 5
88 Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 6
89 Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 7
90 Bs3Trap16GenericEntryErrCd bs3Trap16GenericTrapOrInt ; 8
91 Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 9
92 Bs3Trap16GenericEntryErrCd bs3Trap16GenericTrapOrInt ; a
93 Bs3Trap16GenericEntryErrCd bs3Trap16GenericTrapOrInt ; b
94 Bs3Trap16GenericEntryErrCd bs3Trap16GenericTrapOrInt ; c
95 Bs3Trap16GenericEntryErrCd bs3Trap16GenericTrapOrInt ; d
96 Bs3Trap16GenericEntryErrCd bs3Trap16GenericTrapOrInt ; e
97 Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; f (reserved)
98 Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 10
99 Bs3Trap16GenericEntryErrCd bs3Trap16GenericTrapOrInt ; 11
100 Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 12
101 Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 13
102 Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 14
103 Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 15 (reserved)
104 Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 16 (reserved)
105 Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 17 (reserved)
106 Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 18 (reserved)
107 Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 19 (reserved)
108 Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 1a (reserved)
109 Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 1b (reserved)
110 Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 1c (reserved)
111 Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 1d (reserved)
112 Bs3Trap16GenericEntryErrCd bs3Trap16GenericTrapOrInt ; 1e
113 Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 1f (reserved)
114%rep 224
115 Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt
116%endrep
117BS3_PROC_END Bs3Trap16GenericEntries
118AssertCompile(Bs3Trap16GenericEntries_EndProc - Bs3Trap16GenericEntries == 8*256)
119
120
121;;
122; Trap or interrupt with error code, faked if necessary.
123;
124; Note! This code is going to "misbehave" if the high word of ESP is not cleared.
125;
126BS3_PROC_BEGIN _bs3Trap16GenericTrapOrInt
127BS3_PROC_BEGIN bs3Trap16GenericTrapOrInt
128CPU 386
129 jmp near bs3Trap16GenericTrapErrCode80286 ; Bs3Trap16Init adjusts this on 80386+
130 push ebp
131 movzx ebp, sp
132 push ebx ; BP - 04h
133 pushfd ; BP - 08h
134 cld
135 push edx ; BP - 0ch
136 push ss ; BP - 0eh
137 push esp ; BP - 12h
138
139 ;
140 ; We may be comming from 32-bit code where SS is flat and ESP has a non-
141 ; zero high word. We need to thunk it for C code to work correctly with
142 ; [BP+xx] and [SS:BX+xx] style addressing that leaves out the high word.
143 ;
144 ; Note! Require ring-0 handler for non-standard stacks (SS.DPL must equal CPL).
145 ;
146 mov bx, ss
147 lar ebx, bx
148 test ebx, X86LAR_F_D
149 jz .stack_fine
150 test esp, 0ffff0000h
151 jnz .stack_thunk
152.stack_load_r0_ss16:
153 mov bx, ss
154 and bl, 3
155 AssertCompile(BS3_SEL_RING_SHIFT == 8)
156 mov bh, bl
157 add bx, BS3_SEL_R0_SS16
158 jmp .stack_load_bx_into_ss
159.stack_thunk:
160 mov ebx, esp
161 shr ebx, 16
162 shl ebx, X86_SEL_SHIFT
163 add ebx, BS3_SEL_TILED_R0
164 cmp ebx, BS3_SEL_TILED_R0_LAST
165 ja .stack_esp_out_of_bounds
166.stack_load_bx_into_ss:
167 mov ss, bx
168.stack_fine:
169 movzx esp, sp
170
171 ; Reserve space for the register and trap frame.
172 mov bx, (BS3TRAPFRAME_size + 7) / 8
173.more_zeroed_space:
174 push 0
175 push 0
176 push 0
177 push 0
178 dec bx
179 jnz .more_zeroed_space
180 movzx ebx, sp
181
182 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rax], eax
183 mov edx, [bp - 12h] ; This isn't quite right for wrap arounds, but close enough for now
184 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsp], edx ; high bits
185 mov [ss:bx + BS3TRAPFRAME.uHandlerRsp], edx ; high bits
186 mov dx, [bp - 0eh]
187 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ss], dx
188 mov [ss:bx + BS3TRAPFRAME.uHandlerSs], dx
189 mov edx, [bp - 0ch]
190 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rdx], edx
191 mov edx, [bp - 8]
192 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rflags], edx ; high bits
193 mov [ss:bx + BS3TRAPFRAME.fHandlerRfl], edx
194 mov edx, [bp - 4]
195 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbx], edx
196 mov edx, [bp]
197 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbp], edx
198
199 mov dl, [bp + 4]
200 mov [ss:bx + BS3TRAPFRAME.bXcpt], dl
201
202 mov dx, [bp + 6]
203;; @todo Do voodoo checks for 'int xx' or misguided hardware interrupts.
204 mov [ss:bx + BS3TRAPFRAME.uErrCd], dx
205
206 add bp, 6 ; adjust so it points to the word before the iret frame.
207 xor dx, dx
208 jmp bs3Trap16GenericCommon
209
210.stack_esp_out_of_bounds:
211%ifdef BS3_STRICT
212 int3
213%endif
214 jmp .stack_esp_out_of_bounds
215BS3_PROC_END bs3Trap16GenericTrapErrCode
216
217;;
218; Trap with error code - 80286 code variant.
219;
220BS3_PROC_BEGIN bs3Trap16GenericTrapErrCode80286
221CPU 286
222 push bp
223 mov bp, sp
224 push bx
225 pushf
226 cld
227
228 ; Reserve space for the register and trap frame.
229 mov bx, (BS3TRAPFRAME_size + 7) / 8
230.more_zeroed_space:
231 push 0
232 push 0
233 push 0
234 push 0
235 dec bx
236 jnz .more_zeroed_space
237 mov bx, sp
238
239 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rax], ax
240 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ss], ss
241 mov [ss:bx + BS3TRAPFRAME.uHandlerSs], ss
242 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rdx], dx
243 mov dx, [bp - 4]
244 mov [ss:bx + BS3TRAPFRAME.fHandlerRfl], dx
245 mov dx, [bp - 2]
246 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbx], dx
247 mov dx, [bp]
248 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbp], dx
249
250 mov dl, [bp + 2]
251 mov [ss:bx + BS3TRAPFRAME.bXcpt], dl
252
253 mov dx, [bp + 4]
254;; @todo Do voodoo checks for 'int xx' or misguided hardware interrupts.
255 mov [ss:bx + BS3TRAPFRAME.uErrCd], dx
256
257 add bp, 4 ; adjust so it points to the word before the iret frame.
258 mov dl, 1
259 jmp bs3Trap16GenericCommon
260BS3_PROC_END bs3Trap16GenericTrapErrCode80286
261
262
263;;
264; Common context saving code and dispatching.
265;
266; @param bx Pointer to the trap frame, zero filled. The following members
267; have been filled in by the previous code:
268; - bXcpt
269; - uErrCd
270; - fHandlerRFL
271; - Ctx.eax
272; - Ctx.edx
273; - Ctx.ebx
274; - Ctx.ebp
275; - Ctx.rflags - high bits only.
276; - Ctx.esp - high bits only.
277; - Ctx.ss - for same cpl frames
278; - All other bytes are zeroed.
279;
280; @param bp Pointer to the word before the iret frame, i.e. where bp
281; would be saved if this was a normal near call.
282; @param dx One (1) if 286, zero (0) if 386+.
283;
284BS3_PROC_BEGIN bs3Trap16GenericCommon
285CPU 286
286 ;
287 ; Fake EBP frame.
288 ;
289 mov ax, [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbp]
290 mov [bp], ax
291
292 ;
293 ; Save the remaining GPRs and segment registers.
294 ;
295 test dx, dx
296 jnz .save_word_grps
297CPU 386
298 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rcx], ecx
299 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rdi], edi
300 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsi], esi
301 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.fs], fs
302 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.gs], gs
303 jmp .save_segment_registers
304.save_word_grps:
305CPU 286
306 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rcx], cx
307 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rdi], di
308 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsi], si
309.save_segment_registers:
310 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ds], ds
311 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.es], es
312 mov [ss:bx + BS3TRAPFRAME.uHandlerCs], cs
313
314 ;
315 ; Load 16-bit data selector for the DPL we're executing at into DS and ES.
316 ;
317 mov ax, ss
318 and ax, 3
319 mov cx, ax
320 shl ax, BS3_SEL_RING_SHIFT
321 or ax, cx
322 add ax, BS3_SEL_R0_DS16
323 mov ds, ax
324 mov es, ax
325
326 ;
327 ; Copy and update the mode now that we've got a flat DS.
328 ;
329 mov al, [BS3_DATA16_WRT(g_bBs3CurrentMode)]
330 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.bMode], al
331 mov cl, al
332 and cl, ~BS3_MODE_CODE_MASK
333 or cl, BS3_MODE_CODE_16
334 mov [BS3_DATA16_WRT(g_bBs3CurrentMode)], cl
335
336 ;
337 ; Copy iret info.
338 ;
339 lea cx, [bp + 2]
340 mov [ss:bx + BS3TRAPFRAME.uHandlerRsp], cx
341 mov cx, [bp + 2]
342 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rip], cx
343 mov cx, [bp + 6]
344 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rflags], cx
345 mov cx, [bp + 4]
346 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cs], cx
347
348 test al, BS3_MODE_CODE_V86
349 jnz .iret_frame_v8086
350
351 mov ax, ss
352 and al, 3
353 and cl, 3
354 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.bCpl], cl
355 cmp cl, al
356 je .iret_frame_same_cpl
357
358.ret_frame_different_cpl:
359 mov cx, [bp + 10]
360 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ss], cx
361 mov cx, [bp + 8]
362 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsp], cx
363 mov byte [ss:bx + BS3TRAPFRAME.cbIretFrame], 5*2
364 test dx, dx
365 jnz .iret_frame_done
366 jmp .iret_frame_seed_high_eip_word
367
368.iret_frame_same_cpl: ; (ss and high bits was saved by CPU specific part)
369 lea cx, [bp + 8]
370 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsp], cx
371 mov byte [ss:bx + BS3TRAPFRAME.cbIretFrame], 3*2
372 test dx, dx
373 jnz .iret_frame_done
374 jmp .iret_frame_seed_high_eip_word
375
376.iret_frame_v8086:
377CPU 386
378 or dword [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rflags], X86_EFL_VM
379 mov byte [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.bCpl], 3
380 or byte [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.bMode], BS3_MODE_CODE_V86 ; paranoia ^ 2
381%if 0 ;; @todo testcase: high ESP word from V86 mode, 16-bit TSS.
382 movzx ecx, word [bp + 8]
383 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsp], ecx
384%else
385 mov cx, word [bp + 8]
386 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsp], cx
387%endif
388 mov cx, [bp + 10]
389 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ss], cx
390 mov cx, [bp + 12]
391 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.es], cx
392 mov cx, [bp + 14]
393 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ds], cx
394 mov cx, [bp + 16]
395 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.fs], cx
396 mov cx, [bp + 18]
397 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.gs], cx
398 mov byte [ss:bx + BS3TRAPFRAME.cbIretFrame], 9*2
399 jmp .iret_frame_done
400
401 ;
402 ; For 386 we do special tricks to supply the high word of EIP when
403 ; arriving here from 32-bit code. (ESP was seeded earlier.)
404 ;
405.iret_frame_seed_high_eip_word:
406 lar eax, [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cs]
407 jnz .iret_frame_done
408 test eax, X86LAR_F_D
409 jz .iret_frame_done
410 mov ax, [g_uBs3TrapEipHint+2]
411 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rip + 2], ax
412
413.iret_frame_done:
414 ;
415 ; Control registers.
416 ;
417 str [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.tr]
418 sldt [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ldtr]
419 test dx, dx
420 jnz .save_286_control_registers
421.save_386_control_registers:
422CPU 386
423 mov ax, ss
424 test al, 3
425 jnz .skip_crX_because_cpl_not_0
426 mov eax, cr0
427 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr0], eax
428 mov eax, cr2
429 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr2], eax
430 mov eax, cr3
431 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr3], eax
432
433 test byte [1 + BS3_DATA16_WRT(g_uBs3CpuDetected)], (BS3CPU_F_CPUID >> 8) ; CR4 first appeared in later 486es.
434 jz .skip_cr4_because_not_there
435 mov eax, cr4
436 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr4], eax
437 jmp .set_flags
438
439.skip_cr4_because_not_there:
440 mov byte [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_CR4
441 jmp .set_flags
442
443.skip_crX_because_cpl_not_0:
444 or byte [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.fbFlags], \
445 BS3REG_CTX_F_NO_CR2_CR3 | BS3REG_CTX_F_NO_CR4 | BS3REG_CTX_F_NO_CR0_IS_MSW
446
447CPU 286
448.save_286_control_registers:
449 smsw [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr0]
450
451.set_flags: ; The double fault code joins us here.
452 or byte [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_AMD64
453
454 ;
455 ; Dispatch it to C code.
456 ;
457.dispatch_to_handler:
458 mov di, bx
459 mov bl, byte [ss:bx + BS3TRAPFRAME.bXcpt]
460 mov bh, 0
461 shl bx, 1
462 mov bx, [bx + BS3_DATA16_WRT(_g_apfnBs3TrapHandlers_c16)]
463 or bx, bx
464 jnz .call_handler
465 mov bx, Bs3TrapDefaultHandler
466.call_handler:
467 push ss
468 push di
469 call bx
470
471 ;
472 ; Resume execution using trap frame.
473 ;
474 push 0
475 push ss
476 add di, BS3TRAPFRAME.Ctx
477 push di
478 call Bs3RegCtxRestore
479.panic:
480 hlt
481 jmp .panic
482BS3_PROC_END bs3Trap16GenericCommon
483
484
485;;
486; Helper.
487;
488; @retruns Flat address in es:di.
489; @param di
490; @uses eax
491;
492bs3Trap16TssInDiToFar1616InEsDi:
493CPU 286
494 push ax
495
496 ; ASSUME Bs3Gdt is being used.
497 push BS3_SEL_SYSTEM16
498 pop es
499 and di, 0fff8h
500 add di, Bs3Gdt wrt BS3SYSTEM16
501
502 ; Load the TSS base into ax:di (di is low, ax high)
503 mov al, [es:di + (X86DESCGENERIC_BIT_OFF_BASE_HIGH1 / 8)]
504 mov ah, [es:di + (X86DESCGENERIC_BIT_OFF_BASE_HIGH2 / 8)]
505 mov di, [es:di + (X86DESCGENERIC_BIT_OFF_BASE_LOW / 8)]
506
507 ; Convert ax to tiled selector, if not within the tiling area we read
508 ; random BS3SYSTEM16 bits as that's preferable to #GP'ing.
509 shl ax, X86_SEL_SHIFT
510 cmp ax, BS3_SEL_TILED_LAST - BS3_SEL_TILED
511%ifdef BS3_STRICT
512 jbe .tiled
513 int3
514%endif
515 ja .return ; don't crash again.
516.tiled:
517 add ax, BS3_SEL_TILED
518 mov es, ax
519.return:
520 pop ax
521 ret
522
523
524;;
525; Double fault handler.
526;
527; We don't have to load any selectors or clear anything in EFLAGS because the
528; TSS specified sane values which got loaded during the task switch.
529;
530; @param dx Zero (0) for indicating 386+ to the common code.
531;
532BS3_PROC_BEGIN _Bs3Trap16DoubleFaultHandler80386
533BS3_PROC_BEGIN Bs3Trap16DoubleFaultHandler80386
534CPU 386
535 push 0 ; We'll copy the rip from the other TSS here later to create a more sensible call chain.
536 push ebp
537 mov bp, sp
538 pushfd ; Handler flags.
539
540 ; Reserve space for the register and trap frame.
541 mov bx, (BS3TRAPFRAME_size + 15) / 16
542.more_zeroed_space:
543 push dword 0
544 push dword 0
545 push dword 0
546 push dword 0
547 dec bx
548 jz .more_zeroed_space
549 mov bx, sp
550
551 ;
552 ; Fill in the high GRP register words before we mess them up.
553 ;
554 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rax], eax
555 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbx], ebx
556 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rcx], ecx
557 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rdx], edx
558 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsi], esi
559 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rdi], edi
560 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbp], ebp
561 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsp], esp
562
563 ;
564 ; FS and GS are not part of the 16-bit TSS because they are 386+ specfic.
565 ;
566 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.fs], fs
567 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.gs], gs
568
569 ;
570 ; Fill in the non-context trap frame bits.
571 ;
572 mov ecx, [bp - 4]
573 mov [ss:bx + BS3TRAPFRAME.fHandlerRfl], ecx
574 mov byte [ss:bx + BS3TRAPFRAME.bXcpt], X86_XCPT_DF
575 mov [ss:bx + BS3TRAPFRAME.uHandlerCs], cs
576 mov [ss:bx + BS3TRAPFRAME.uHandlerSs], ss
577 mov ecx, esp
578 lea cx, [bp + 8]
579 mov [ss:bx + BS3TRAPFRAME.uHandlerRsp], ecx
580 mov cx, [bp + 6]
581 mov [ss:bx + BS3TRAPFRAME.uErrCd], cx
582
583 ;
584 ; Copy 80386+ control registers.
585 ;
586 mov ecx, cr0
587 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr0], ecx
588 mov ecx, cr2
589 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr2], ecx
590 mov ecx, cr3
591 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr3], ecx
592
593 test byte [1 + BS3_DATA16_WRT(g_uBs3CpuDetected)], (BS3CPU_F_CPUID >> 8) ; CR4 first appeared in later 486es.
594 jz .skip_cr4_because_not_there
595 mov ecx, cr4
596 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr4], ecx
597 jmp .common
598
599.skip_cr4_because_not_there:
600 mov byte [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_CR4
601
602 ;
603 ; Copy the register state from the previous task segment.
604 ; The 80286 code with join us here.
605 ;
606.common:
607CPU 286
608 ; Find our TSS.
609 str di
610 call bs3Trap16TssInDiToFar1616InEsDi
611
612 ; Find the previous TSS.
613 mov di, [es:di + X86TSS32.selPrev]
614 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.tr], ax
615 call bs3Trap16TssInDiToFar1616InEsDi
616
617 ; Do the copying.
618 mov cx, [es:di + X86TSS16.ax]
619 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rax], cx
620 mov cx, [es:di + X86TSS16.cx]
621 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rcx], cx
622 mov cx, [es:di + X86TSS16.dx]
623 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rdx], cx
624 mov cx, [es:di + X86TSS16.bx]
625 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbx], cx
626 mov cx, [es:di + X86TSS16.sp]
627 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsp], cx
628 mov cx, [es:di + X86TSS16.bp]
629 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbp], cx
630 mov [bp], cx ; For better call stacks.
631 mov cx, [es:di + X86TSS16.si]
632 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsi], cx
633 mov cx, [es:di + X86TSS16.di]
634 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rdi], cx
635 mov cx, [es:di + X86TSS16.si]
636 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsi], cx
637 mov cx, [es:di + X86TSS16.flags]
638 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rflags], cx
639 mov cx, [es:di + X86TSS16.ip]
640 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rip], cx
641 mov [bp + 2], cx ; For better call stacks.
642 mov cx, [es:di + X86TSS16.cs]
643 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cs], cx
644 mov cx, [es:di + X86TSS16.ds]
645 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ds], cx
646 mov cx, [es:di + X86TSS16.es]
647 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.es], cx
648 mov cx, [es:di + X86TSS16.ss]
649 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ss], cx
650 mov cx, [es:di + X86TSS16.selLdt] ; Note! This isn't necessarily the ldtr at the time of the fault.
651 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ldtr], cx
652
653 ;
654 ; Set CPL; copy and update mode.
655 ;
656 mov cl, [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ss]
657 and cl, 3
658 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.bCpl], cl
659
660 mov cl, [BS3_DATA16_WRT(g_bBs3CurrentMode)]
661 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.bMode], cl
662 and cl, ~BS3_MODE_CODE_MASK
663 or cl, BS3_MODE_CODE_16
664 mov [BS3_DATA16_WRT(g_bBs3CurrentMode)], cl
665
666 ;
667 ; Join code paths with the generic handler code.
668 ;
669 jmp bs3Trap16GenericCommon.set_flags
670BS3_PROC_END Bs3Trap16DoubleFaultHandler
671
672
673;;
674; Double fault handler.
675;
676; We don't have to load any selectors or clear anything in EFLAGS because the
677; TSS specified sane values which got loaded during the task switch.
678;
679; @param dx One (1) for indicating 386+ to the common code.
680;
681BS3_PROC_BEGIN _Bs3Trap16DoubleFaultHandler80286
682BS3_PROC_BEGIN Bs3Trap16DoubleFaultHandler80286
683CPU 286
684 push 0 ; We'll copy the rip from the other TSS here later to create a more sensible call chain.
685 push bp
686 mov bp, sp
687 pushf ; Handler flags.
688
689 ; Reserve space for the register and trap frame.
690 mov bx, (BS3TRAPFRAME_size + 7) / 8
691.more_zeroed_space:
692 push 0
693 push 0
694 push 0
695 push 0
696 dec bx
697 jz .more_zeroed_space
698 mov bx, sp
699
700 ;
701 ; Fill in the non-context trap frame bits.
702 ;
703 mov cx, [bp - 2]
704 mov [ss:bx + BS3TRAPFRAME.fHandlerRfl], cx
705 mov byte [ss:bx + BS3TRAPFRAME.bXcpt], X86_XCPT_DF
706 mov [ss:bx + BS3TRAPFRAME.uHandlerCs], cs
707 mov [ss:bx + BS3TRAPFRAME.uHandlerSs], ss
708 lea cx, [bp + 8]
709 mov [ss:bx + BS3TRAPFRAME.uHandlerRsp], cx
710 mov cx, [bp + 6]
711 mov [ss:bx + BS3TRAPFRAME.uErrCd], cx
712
713 ;
714 ; Copy 80286 specific control register.
715 ;
716 smsw [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr0]
717
718 jmp Bs3Trap16DoubleFaultHandler80386.common
719BS3_PROC_END Bs3Trap16DoubleFaultHandler80286
720
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