VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c16-TrapRmV86Generic.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: 15.6 KB
Line 
1; $Id: bs3-c16-TrapRmV86Generic.asm 106061 2024-09-16 14:03:52Z vboxsync $
2;; @file
3; BS3Kit - Trap, 16-bit assembly handlers for real mode and v8086.
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
54TMPL_BEGIN_TEXT
55BS3_EXTERN_CMN Bs3TrapDefaultHandler
56BS3_EXTERN_CMN Bs3RegCtxRestore
57TMPL_BEGIN_TEXT
58
59
60;;
61; Generic entry points for IDT handlers, 8 byte spacing.
62;
63BS3_PROC_BEGIN _Bs3TrapRmV86GenericEntries
64BS3_PROC_BEGIN Bs3TrapRmV86GenericEntries
65%macro Bs3TrapRmV86GenericEntryNoErr 1
66 push ax ; 1 byte: Reserve space for fake error cd. (BP(+2) + 4)
67 push ax ; 1 byte: Save AX (BP(+2) + 2)
68 mov ax, i | 00000h ; 2 bytes: AL = trap/interrupt number; AH=indicate no error code
69 jmp %1 ; 3 bytes: Jump to handler code
70 ALIGNCODE(8)
71%assign i i+1
72%endmacro
73
74%macro Bs3TrapRmV86GenericEntryErrCd 1
75 Bs3TrapRmV86GenericEntryNoErr %1 ; No error code pushed in real mode or V86 mode.
76%endmacro
77
78%assign i 0 ; start counter.
79 Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 0
80 Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 1
81 Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 2
82 Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 3
83 Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 4
84 Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 5
85 Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 6
86 Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 7
87 Bs3TrapRmV86GenericEntryErrCd bs3TrapRmV86GenericTrapOrInt ; 8
88 Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 9
89 Bs3TrapRmV86GenericEntryErrCd bs3TrapRmV86GenericTrapOrInt ; a
90 Bs3TrapRmV86GenericEntryErrCd bs3TrapRmV86GenericTrapOrInt ; b
91 Bs3TrapRmV86GenericEntryErrCd bs3TrapRmV86GenericTrapOrInt ; c
92 Bs3TrapRmV86GenericEntryErrCd bs3TrapRmV86GenericTrapOrInt ; d
93 Bs3TrapRmV86GenericEntryErrCd bs3TrapRmV86GenericTrapOrInt ; e
94 Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; f (reserved)
95 Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 10
96 Bs3TrapRmV86GenericEntryErrCd bs3TrapRmV86GenericTrapOrInt ; 11
97 Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 12
98 Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 13
99 Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 14
100 Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 15 (reserved)
101 Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 16 (reserved)
102 Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 17 (reserved)
103 Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 18 (reserved)
104 Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 19 (reserved)
105 Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 1a (reserved)
106 Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 1b (reserved)
107 Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 1c (reserved)
108 Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 1d (reserved)
109 Bs3TrapRmV86GenericEntryErrCd bs3TrapRmV86GenericTrapOrInt ; 1e
110 Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 1f (reserved)
111%rep 224
112 Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt
113%endrep
114BS3_PROC_END Bs3TrapRmV86GenericEntries
115AssertCompile(Bs3TrapRmV86GenericEntries_EndProc - Bs3TrapRmV86GenericEntries == 8*256)
116
117
118;;
119; Trap or interrupt with error code, faked if necessary.
120;
121; early 386+ stack (movzx ebp, sp):
122; [bp + 000h] ebp
123; [bp + 004h] ax
124; [bp + 006h] errcd [bp'+0] <--- bp at jmp to common code.
125; [bp + 008h] cs [bp'+2]
126; [bp + 00ah] ip [bp'+4]
127; [bp + 00ch] flags [bp'+6]
128; ([bp + 00eh] post-iret sp value) [bp'+8]
129;
130BS3_PROC_BEGIN _bs3TrapRmV86GenericTrapOrInt
131BS3_PROC_BEGIN bs3TrapRmV86GenericTrapOrInt
132CPU 386
133 jmp near bs3TrapRmV86GenericTrapErrCode8086 ; Bs3TrapRmV86Init adjusts this on 80386+
134 push ebp
135 movzx ebp, sp
136 push ebx ; BP - 04h
137 pushfd ; BP - 08h
138 cld
139 push edx ; BP - 0ch
140 push ss ; BP - 0eh
141 push esp ; BP - 12h
142
143 ; Reserve space for the register and trap frame.
144 mov bx, (BS3TRAPFRAME_size + 7) / 8
145.more_zeroed_space:
146 push 0
147 push 0
148 push 0
149 push 0
150 dec bx
151 jnz .more_zeroed_space
152 movzx ebx, sp
153
154
155 mov edx, [bp - 12h]
156 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsp], edx ; high bits
157 mov [ss:bx + BS3TRAPFRAME.uHandlerRsp], edx ; high bits
158 mov dx, [bp - 0eh]
159 mov [ss:bx + BS3TRAPFRAME.uHandlerSs], dx
160 mov edx, [bp - 0ch]
161 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rdx], edx
162 mov edx, [bp - 8]
163 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rflags], edx ; high bits
164 mov [ss:bx + BS3TRAPFRAME.fHandlerRfl], edx
165 mov edx, [bp - 4]
166 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbx], edx
167 mov edx, [bp]
168 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbp], edx
169 mov edx, eax ; high bits
170 mov dx, [bp + 4]
171 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rax], edx
172
173 mov [ss:bx + BS3TRAPFRAME.bXcpt], al
174
175 test ah, 0ffh
176 jz .no_error_code
177 mov dx, [bp + 6]
178 mov [ss:bx + BS3TRAPFRAME.uErrCd], dx
179.no_error_code:
180
181 add bp, 6 ; adjust so it points to the word before the iret frame.
182 xor dx, dx
183 jmp bs3TrapRmV86GenericCommon
184BS3_PROC_END bs3TrapRmV86GenericTrapErrCode
185
186;;
187; Trap with error code - 8086/V20/80186/80286 code variant.
188;
189BS3_PROC_BEGIN bs3TrapRmV86GenericTrapErrCode8086
190CPU 8086
191 push bp
192 mov bp, sp
193 push bx ; BP - 2
194 pushf ; BP - 4
195 push ax ; BP - 6
196 cld
197
198 ; Reserve space for the register and trap frame.
199 mov bx, (BS3TRAPFRAME_size + 7) / 8
200 xor ax, ax
201.more_zeroed_space:
202 push ax
203 push ax
204 push ax
205 push ax
206 dec bx
207 jnz .more_zeroed_space
208 mov bx, sp
209
210 mov [ss:bx + BS3TRAPFRAME.uHandlerSs], ss
211 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rdx], dx
212 mov dx, [bp - 4]
213 mov [ss:bx + BS3TRAPFRAME.fHandlerRfl], dx
214 mov dx, [bp - 2]
215 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbx], dx
216 mov dx, [bp]
217 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbp], dx
218
219 mov dx, [bp + 2]
220 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rax], dx
221
222 mov ax, [bp - 6]
223 mov [ss:bx + BS3TRAPFRAME.bXcpt], al
224
225 test ah, 0ffh
226 jz .no_error_code
227 mov dx, [bp + 4]
228 mov [ss:bx + BS3TRAPFRAME.uErrCd], dx
229.no_error_code:
230
231 add bp, 4 ; adjust so it points to the word before the iret frame.
232 mov dl, 1
233 jmp bs3TrapRmV86GenericCommon
234BS3_PROC_END bs3TrapRmV86GenericTrapErrCode8086
235
236
237;;
238; Common context saving code and dispatching.
239;
240; @param ss:bx Pointer to the trap frame, zero filled. The following members
241; have been filled in by the previous code:
242; - bXcpt
243; - uErrCd
244; - fHandlerRFL
245; - Ctx.eax
246; - Ctx.edx
247; - Ctx.ebx
248; - Ctx.ebp
249; - Ctx.rflags - high bits only.
250; - Ctx.esp - high bits only.
251; - All other bytes are zeroed.
252;
253; @param bp Pointer to the word before the iret frame, i.e. where bp
254; would be saved if this was a normal near call.
255; @param dx One (1) if 286, zero (0) if 386+.
256;
257BS3_PROC_BEGIN bs3TrapRmV86GenericCommon
258CPU 8086
259 ;
260 ; Fake EBP frame.
261 ;
262 mov ax, [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbp]
263 mov [bp], ax
264
265 ;
266 ; Save the remaining GPRs and segment registers.
267 ;
268 test dx, dx
269 jnz .save_word_grps
270CPU 386
271 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rcx], ecx
272 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rdi], edi
273 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsi], esi
274 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.fs], fs
275 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.gs], gs
276 jmp .save_segment_registers
277.save_word_grps:
278CPU 8086
279 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rcx], cx
280 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rdi], di
281 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsi], si
282.save_segment_registers:
283 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ds], ds
284 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.es], es
285 mov [ss:bx + BS3TRAPFRAME.uHandlerCs], cs
286
287 ;
288 ; Load 16-bit BS3KIT_GRPNM_DATA16 into DS and ES so we can access globals.
289 ;
290 mov ax, BS3KIT_GRPNM_DATA16
291 mov ds, ax
292 mov es, ax
293
294 ;
295 ; Copy the mode now that we've got a flat DS. We don't need to update
296 ; it as it didn't change.
297 ;
298 mov al, [BS3_DATA16_WRT(g_bBs3CurrentMode)]
299 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.bMode], al
300
301 ;
302 ; Copy iret info.
303 ;
304 lea cx, [bp + 2]
305 mov [ss:bx + BS3TRAPFRAME.uHandlerRsp], cx
306 mov cx, [bp + 2]
307 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rip], cx
308 mov cx, [bp + 6]
309 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rflags], cx
310 mov cx, [bp + 4]
311 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cs], cx
312 mov cx, ss
313 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ss], cx
314 lea cx, [bp + 8]
315 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsp], cx
316 mov byte [ss:bx + BS3TRAPFRAME.cbIretFrame], 3*2
317
318 ; The VM flag and CPL.
319 test al, BS3_MODE_CODE_V86
320 jz .dont_set_vm
321 or byte [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rflags + 2], X86_EFL_VM >> 16
322 mov byte [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.bCpl], 3
323.dont_set_vm:
324
325
326 ;
327 ; Control registers.
328 ;
329 ; Since we're in real or v8086 here, we cannot save TR and LDTR.
330 ; But get MSW (CR0) first since that's always accessible and we
331 ; need it even on a 386 to check whether we're in v8086 mode or not.
332 ;
333 cmp byte [BS3_DATA16_WRT(g_uBs3CpuDetected)], BS3CPU_80286
334 jb .skip_control_registers_because_80186_or_older
335CPU 286
336 smsw ax
337 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr0], ax
338
339 test dx, dx
340 jnz .set_flags
341.save_386_control_registers:
342CPU 386
343 ; 386 control registers are not accessible from virtual 8086 mode.
344 test al, X86_CR0_PE
345 jnz .skip_crX_because_v8086
346 mov eax, cr0
347 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr0], eax
348 mov eax, cr2
349 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr2], eax
350 mov eax, cr3
351 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr3], eax
352
353 test byte [1 + BS3_DATA16_WRT(g_uBs3CpuDetected)], (BS3CPU_F_CPUID >> 8) ; CR4 first appeared in later 486es.
354 jz .skip_cr4_because_not_there
355 mov eax, cr4
356 mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr4], eax
357 jmp .set_flags
358
359.skip_cr4_because_not_there:
360 mov byte [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_CR4
361 jmp .set_flags
362
363CPU 8086
364.skip_control_registers_because_80186_or_older:
365.skip_crX_because_v8086:
366 or byte [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.fbFlags], \
367 BS3REG_CTX_F_NO_CR0_IS_MSW | BS3REG_CTX_F_NO_CR2_CR3 | BS3REG_CTX_F_NO_CR4
368.set_flags: ; The double fault code joins us here.
369 or byte [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_AMD64 | BS3REG_CTX_F_NO_TR_LDTR
370
371 ;
372 ; Dispatch it to C code.
373 ;
374.dispatch_to_handler:
375 mov di, bx
376 mov bl, byte [ss:bx + BS3TRAPFRAME.bXcpt]
377 mov bh, 0
378 shl bx, 1
379 mov bx, [bx + BS3_DATA16_WRT(_g_apfnBs3TrapHandlers_c16)]
380 or bx, bx
381 jnz .call_handler
382 mov bx, Bs3TrapDefaultHandler
383.call_handler:
384 push ss
385 push di
386 call bx
387
388 ;
389 ; Resume execution using trap frame.
390 ;
391 xor ax, ax
392 push ax
393 push ss
394 add di, BS3TRAPFRAME.Ctx
395 push di
396 call Bs3RegCtxRestore
397.panic:
398 hlt
399 jmp .panic
400BS3_PROC_END bs3TrapRmV86GenericCommon
401
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