VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapDefaultHandler.c@ 105590

Last change on this file since 105590 was 105094, checked in by vboxsync, 5 months ago

VMM/IEM,ValKit/bs3-cpu-weird-1: syscall TF & debug event fixes; extended bs3-cpu-weird-1 with syscall (only tested on intel). bugref:10715

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.9 KB
Line 
1/* $Id: bs3-cmn-TrapDefaultHandler.c 105094 2024-07-02 09:33:52Z vboxsync $ */
2/** @file
3 * BS3Kit - Bs3TrapDefaultHandler
4 */
5
6/*
7 * Copyright (C) 2007-2023 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/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#include "bs3kit-template-header.h"
42#if TMPL_BITS != 64
43# include <VBox/VMMDevTesting.h>
44# include <iprt/asm-amd64-x86.h>
45#endif
46
47
48/*********************************************************************************************************************************
49* Global Variables *
50*********************************************************************************************************************************/
51#define g_pBs3TrapSetJmpFrame BS3_DATA_NM(g_pBs3TrapSetJmpFrame)
52extern uint32_t g_pBs3TrapSetJmpFrame;
53
54#define g_Bs3TrapSetJmpCtx BS3_DATA_NM(g_Bs3TrapSetJmpCtx)
55extern BS3REGCTX g_Bs3TrapSetJmpCtx;
56
57
58#if TMPL_BITS != 64
59/**
60 * V86 syscall handler.
61 */
62static void bs3TrapDefaultHandlerV8086Syscall(PBS3TRAPFRAME pTrapFrame)
63{
64 /* Minimal syscall. */
65 uint16_t uSyscallNo = pTrapFrame->Ctx.rax.u16;
66 if (uSyscallNo == BS3_SYSCALL_PRINT_CHR)
67 Bs3PrintChr(pTrapFrame->Ctx.rcx.u8);
68 else if (uSyscallNo == BS3_SYSCALL_PRINT_STR)
69 Bs3PrintStrN(Bs3XptrFlatToCurrent(((uint32_t)pTrapFrame->Ctx.rcx.u16 << 4) + pTrapFrame->Ctx.rsi.u16),
70 pTrapFrame->Ctx.rdx.u16);
71 else if (uSyscallNo == BS3_SYSCALL_RESTORE_CTX)
72 Bs3RegCtxRestore(Bs3XptrFlatToCurrent(((uint32_t)pTrapFrame->Ctx.rcx.u16 << 4) + pTrapFrame->Ctx.rsi.u16),
73 pTrapFrame->Ctx.rdx.u16);
74 else if ( uSyscallNo == BS3_SYSCALL_TO_RING0
75 || uSyscallNo == BS3_SYSCALL_TO_RING1
76 || uSyscallNo == BS3_SYSCALL_TO_RING2
77 || uSyscallNo == BS3_SYSCALL_TO_RING3)
78 {
79 Bs3RegCtxConvertToRingX(&pTrapFrame->Ctx, pTrapFrame->Ctx.rax.u16 - BS3_SYSCALL_TO_RING0);
80 }
81 else if (uSyscallNo == BS3_SYSCALL_SET_DRX)
82 {
83 uint32_t uValue = pTrapFrame->Ctx.rsi.u32;
84 switch (pTrapFrame->Ctx.rdx.u8)
85 {
86 case 0: ASMSetDR0(uValue); break;
87 case 1: ASMSetDR1(uValue); break;
88 case 2: ASMSetDR2(uValue); break;
89 case 3: ASMSetDR3(uValue); break;
90 case 6: ASMSetDR6(uValue); break;
91 case 7: ASMSetDR7(uValue); break;
92 default: Bs3Panic();
93 }
94 }
95 else if (uSyscallNo == BS3_SYSCALL_GET_DRX)
96 {
97 uint32_t uValue;
98 switch (pTrapFrame->Ctx.rdx.u8)
99 {
100 case 0: uValue = ASMGetDR0(); break;
101 case 1: uValue = ASMGetDR1(); break;
102 case 2: uValue = ASMGetDR2(); break;
103 case 3: uValue = ASMGetDR3(); break;
104 case 6: uValue = ASMGetDR6(); break;
105 case 7: uValue = ASMGetDR7(); break;
106 default: uValue = 0; Bs3Panic();
107 }
108 pTrapFrame->Ctx.rax.u32 = uValue;
109 pTrapFrame->Ctx.rdx.u32 = uValue >> 16;
110 }
111 else if (uSyscallNo == BS3_SYSCALL_SET_CRX)
112 {
113 uint32_t uValue = pTrapFrame->Ctx.rsi.u32;
114 switch (pTrapFrame->Ctx.rdx.u8)
115 {
116 case 0: ASMSetCR0(uValue); pTrapFrame->Ctx.cr0.u32 = uValue; break;
117 case 2: ASMSetCR2(uValue); pTrapFrame->Ctx.cr2.u32 = uValue; break;
118 case 3: ASMSetCR3(uValue); pTrapFrame->Ctx.cr3.u32 = uValue; break;
119 case 4: ASMSetCR4(uValue); pTrapFrame->Ctx.cr4.u32 = uValue; break;
120 default: Bs3Panic();
121 }
122 }
123 else if (uSyscallNo == BS3_SYSCALL_GET_CRX)
124 {
125 uint32_t uValue;
126 switch (pTrapFrame->Ctx.rdx.u8)
127 {
128 case 0: uValue = ASMGetCR0(); break;
129 case 2: uValue = ASMGetCR2(); break;
130 case 3: uValue = ASMGetCR3(); break;
131 case 4: uValue = ASMGetCR4(); break;
132 default: uValue = 0; Bs3Panic();
133 }
134 pTrapFrame->Ctx.rax.u32 = uValue;
135 pTrapFrame->Ctx.rdx.u32 = uValue >> 16;
136 }
137 else if (uSyscallNo == BS3_SYSCALL_SET_TR)
138 {
139 Bs3RegSetTr(pTrapFrame->Ctx.rdx.u16);
140 pTrapFrame->Ctx.tr = pTrapFrame->Ctx.rdx.u16;
141 }
142 else if (uSyscallNo == BS3_SYSCALL_GET_TR)
143 pTrapFrame->Ctx.rax.u16 = ASMGetTR();
144 else if (uSyscallNo == BS3_SYSCALL_SET_LDTR)
145 {
146 Bs3RegSetLdtr(pTrapFrame->Ctx.rdx.u16);
147 pTrapFrame->Ctx.ldtr = pTrapFrame->Ctx.rdx.u16;
148 }
149 else if (uSyscallNo == BS3_SYSCALL_GET_LDTR)
150 pTrapFrame->Ctx.rax.u16 = ASMGetLDTR();
151 else if (uSyscallNo == BS3_SYSCALL_SET_XCR0)
152 ASMSetXcr0(RT_MAKE_U64(pTrapFrame->Ctx.rsi.u32, pTrapFrame->Ctx.rdx.u32));
153 else if (uSyscallNo == BS3_SYSCALL_GET_XCR0)
154 {
155 uint64_t const uValue = ASMGetXcr0();
156 pTrapFrame->Ctx.rax.u32 = (uint32_t)uValue;
157 pTrapFrame->Ctx.rdx.u32 = (uint32_t)(uValue >> 32);
158 }
159 else
160 Bs3Panic();
161}
162#endif
163
164#undef Bs3TrapDefaultHandler
165BS3_CMN_DEF(void, Bs3TrapDefaultHandler,(PBS3TRAPFRAME pTrapFrame))
166{
167#if TMPL_BITS != 64
168 /*
169 * v8086 VMM tasks.
170 */
171 //Bs3TestHostPrintf("Bs3____DefaultHandler: %02xh %04RX16:%08RX32 %08RX32 %04RX16:%08RX32 %d %d\n", pTrapFrame->bXcpt,
172 // pTrapFrame->Ctx.cs, pTrapFrame->Ctx.rip.u32, pTrapFrame->Ctx.rflags.u32, pTrapFrame->Ctx.ss,
173 // pTrapFrame->Ctx.rsp.u32, g_fBs3TrapNoV86Assist, 42);
174 if ((pTrapFrame->Ctx.rflags.u32 & X86_EFL_VM))
175 {
176 bool fHandled = true;
177 uint8_t cBitsOpcode = 16;
178 uint8_t bOpCode;
179 uint8_t const BS3_FAR *pbCodeStart;
180 uint8_t const BS3_FAR *pbCode;
181 uint16_t BS3_FAR *pusStack;
182
183 pusStack = (uint16_t BS3_FAR *)BS3_MAKE_PROT_R0PTR_FROM_REAL(pTrapFrame->Ctx.ss, pTrapFrame->Ctx.rsp.u16);
184 pbCode = (uint8_t const BS3_FAR *)BS3_MAKE_PROT_R0PTR_FROM_REAL(pTrapFrame->Ctx.cs, pTrapFrame->Ctx.rip.u16);
185 pbCodeStart = pbCode;
186
187 /*
188 * Deal with GPs in V8086 mode.
189 */
190 if ( pTrapFrame->bXcpt == X86_XCPT_GP
191 && !g_fBs3TrapNoV86Assist)
192 {
193 bOpCode = *pbCode++;
194 if (bOpCode == 0x66)
195 {
196 cBitsOpcode = 32;
197 bOpCode = *pbCode++;
198 }
199
200 /* INT xx: Real mode behaviour, but intercepting and implementing most of our syscall interface. */
201 if (bOpCode == 0xcd)
202 {
203 uint8_t bVector = *pbCode++;
204 if (bVector == BS3_TRAP_SYSCALL)
205 bs3TrapDefaultHandlerV8086Syscall(pTrapFrame);
206 else
207 {
208 /* Real mode behaviour. */
209 uint16_t BS3_FAR *pusIvte = (uint16_t BS3_FAR *)BS3_MAKE_PROT_R0PTR_FROM_REAL(0, 0);
210 pusIvte += (uint16_t)bVector *2;
211
212 pusStack[0] = pTrapFrame->Ctx.rflags.u16;
213 pusStack[1] = pTrapFrame->Ctx.cs;
214 pusStack[2] = pTrapFrame->Ctx.rip.u16 + (uint16_t)(pbCode - pbCodeStart);
215
216 pTrapFrame->Ctx.rip.u16 = pusIvte[0];
217 pTrapFrame->Ctx.cs = pusIvte[1];
218 pTrapFrame->Ctx.rflags.u16 &= ~X86_EFL_IF; /** @todo this isn't all, but it'll do for now, I hope. */
219 Bs3RegCtxRestore(&pTrapFrame->Ctx, 0/*fFlags*/); /* does not return. */
220 }
221 }
222 /* PUSHF: Real mode behaviour. */
223 else if (bOpCode == 0x9c)
224 {
225 if (cBitsOpcode == 32)
226 *pusStack++ = pTrapFrame->Ctx.rflags.au16[1] & ~(X86_EFL_VM | X86_EFL_RF);
227 *pusStack++ = pTrapFrame->Ctx.rflags.u16;
228 pTrapFrame->Ctx.rsp.u16 += cBitsOpcode / 8;
229 }
230 /* POPF: Real mode behaviour. */
231 else if (bOpCode == 0x9d)
232 {
233 if (cBitsOpcode == 32)
234 {
235 pTrapFrame->Ctx.rflags.u32 &= ~X86_EFL_POPF_BITS;
236 pTrapFrame->Ctx.rflags.u32 |= X86_EFL_POPF_BITS & *(uint32_t const *)pusStack;
237 }
238 else
239 {
240 pTrapFrame->Ctx.rflags.u32 &= ~(X86_EFL_POPF_BITS | UINT32_C(0xffff0000)) & ~X86_EFL_RF;
241 pTrapFrame->Ctx.rflags.u16 |= (uint16_t)X86_EFL_POPF_BITS & *pusStack;
242 }
243 pTrapFrame->Ctx.rsp.u16 -= cBitsOpcode / 8;
244 }
245 /* CLI: Real mode behaviour. */
246 else if (bOpCode == 0xfa)
247 pTrapFrame->Ctx.rflags.u16 &= ~X86_EFL_IF;
248 /* STI: Real mode behaviour. */
249 else if (bOpCode == 0xfb)
250 pTrapFrame->Ctx.rflags.u16 |= X86_EFL_IF;
251 /* OUT: byte I/O to VMMDev. */
252 else if ( bOpCode == 0xee
253 && ((unsigned)(pTrapFrame->Ctx.rdx.u16 - VMMDEV_TESTING_IOPORT_BASE) < (unsigned)VMMDEV_TESTING_IOPORT_COUNT))
254 ASMOutU8(pTrapFrame->Ctx.rdx.u16, pTrapFrame->Ctx.rax.u8);
255 /* OUT: [d]word I/O to VMMDev. */
256 else if ( bOpCode == 0xef
257 && ((unsigned)(pTrapFrame->Ctx.rdx.u16 - VMMDEV_TESTING_IOPORT_BASE) < (unsigned)VMMDEV_TESTING_IOPORT_COUNT))
258 {
259 if (cBitsOpcode != 32)
260 ASMOutU16(pTrapFrame->Ctx.rdx.u16, pTrapFrame->Ctx.rax.u16);
261 else
262 ASMOutU32(pTrapFrame->Ctx.rdx.u16, pTrapFrame->Ctx.rax.u32);
263 }
264 /* IN: byte I/O to VMMDev. */
265 else if ( bOpCode == 0xec
266 && ((unsigned)(pTrapFrame->Ctx.rdx.u16 - VMMDEV_TESTING_IOPORT_BASE) < (unsigned)VMMDEV_TESTING_IOPORT_COUNT))
267 pTrapFrame->Ctx.rax.u8 = ASMInU8(pTrapFrame->Ctx.rdx.u16);
268 /* IN: [d]word I/O to VMMDev. */
269 else if ( bOpCode == 0xed
270 && ((unsigned)(pTrapFrame->Ctx.rdx.u16 - VMMDEV_TESTING_IOPORT_BASE) < (unsigned)VMMDEV_TESTING_IOPORT_COUNT))
271 {
272 if (cBitsOpcode != 32)
273 pTrapFrame->Ctx.rax.u16 = ASMInU16(pTrapFrame->Ctx.rdx.u16);
274 else
275 pTrapFrame->Ctx.rax.u32 = ASMInU32(pTrapFrame->Ctx.rdx.u32);
276 }
277 /* Unexpected. */
278 else
279 fHandled = false;
280 }
281 /*
282 * Deal with lock prefixed int xxh syscall in v8086 mode.
283 */
284 else if ( pTrapFrame->bXcpt == X86_XCPT_UD
285 && pTrapFrame->Ctx.cs == BS3_SEL_TEXT16
286 && pTrapFrame->Ctx.rax.u16 <= BS3_SYSCALL_LAST
287 && pbCode[0] == 0xf0
288 && pbCode[1] == 0xcd
289 && pbCode[2] == BS3_TRAP_SYSCALL)
290 {
291 pbCode += 3;
292 bs3TrapDefaultHandlerV8086Syscall(pTrapFrame);
293 }
294 else
295 {
296 fHandled = false;
297 }
298 if (fHandled)
299 {
300 pTrapFrame->Ctx.rip.u16 += (uint16_t)(pbCode - pbCodeStart);
301# if 0
302 Bs3Printf("Calling Bs3RegCtxRestore\n");
303 Bs3RegCtxPrint(&pTrapFrame->Ctx);
304# endif
305 Bs3RegCtxRestore(&pTrapFrame->Ctx, 0 /*fFlags*/); /* does not return. */
306 return;
307 }
308 }
309#endif
310
311 /*
312 * Any pending setjmp?
313 */
314 if (g_pBs3TrapSetJmpFrame != 0)
315 {
316 PBS3TRAPFRAME pSetJmpFrame = (PBS3TRAPFRAME)Bs3XptrFlatToCurrent(g_pBs3TrapSetJmpFrame);
317 //Bs3Printf("Calling longjmp: pSetJmpFrame=%p (%#lx)\n", pSetJmpFrame, g_pBs3TrapSetJmpFrame);
318 g_pBs3TrapSetJmpFrame = 0;
319 Bs3MemCpy(pSetJmpFrame, pTrapFrame, sizeof(*pSetJmpFrame));
320 //Bs3RegCtxPrint(&g_Bs3TrapSetJmpCtx);
321 Bs3RegCtxRestore(&g_Bs3TrapSetJmpCtx, 0 /*fFlags*/);
322 }
323
324 /*
325 * Fatal.
326 *
327 * Special case for #DB so we can get at the DRx values before we print anything,
328 * as a aid for debugging VT-x/AMD-V code getting these out of sync.
329 */
330 if (pTrapFrame->bXcpt != X86_XCPT_DB)
331 {
332 Bs3TestPrintf("*** GURU ***\n");
333 Bs3TrapPrintFrame(pTrapFrame);
334 }
335 else
336 {
337 Bs3TestPrintf("*** GURU ***\n"
338#if ARCH_BITS == 64
339 "dr6=%08RX32 dr7=%08RX32 dr0=%08RX64\n"
340 "dr1=%08RX64 dr2=%08RX64 dr3=%08RX64\n"
341#else
342 "dr6=%08RX32 dr7=%08RX32 dr0=%08RX32 dr1=%08RX32 dr2=%08RX32 dr3=%08RX32\n"
343#endif
344 , (uint32_t)Bs3RegGetDr6(), (uint32_t)Bs3RegGetDr7(),
345 Bs3RegGetDr0(), Bs3RegGetDr1(), Bs3RegGetDr2(), Bs3RegGetDr3());
346 Bs3TrapPrintFrame(pTrapFrame);
347 }
348 Bs3Panic();
349}
350
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