VirtualBox

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

Last change on this file since 86728 was 82968, checked in by vboxsync, 5 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.6 KB
Line 
1/* $Id: bs3-cmn-TrapDefaultHandler.c 82968 2020-02-04 10:35:17Z vboxsync $ */
2/** @file
3 * BS3Kit - Bs3TrapDefaultHandler
4 */
5
6/*
7 * Copyright (C) 2007-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include "bs3kit-template-header.h"
32#if TMPL_BITS != 64
33# include <VBox/VMMDevTesting.h>
34# include <iprt/asm-amd64-x86.h>
35#endif
36
37
38/*********************************************************************************************************************************
39* Global Variables *
40*********************************************************************************************************************************/
41#define g_pBs3TrapSetJmpFrame BS3_DATA_NM(g_pBs3TrapSetJmpFrame)
42extern uint32_t g_pBs3TrapSetJmpFrame;
43
44#define g_Bs3TrapSetJmpCtx BS3_DATA_NM(g_Bs3TrapSetJmpCtx)
45extern BS3REGCTX g_Bs3TrapSetJmpCtx;
46
47
48#if TMPL_BITS != 64
49/**
50 * V86 syscall handler.
51 */
52static void bs3TrapDefaultHandlerV8086Syscall(PBS3TRAPFRAME pTrapFrame)
53{
54 /* Minimal syscall. */
55 uint16_t uSyscallNo = pTrapFrame->Ctx.rax.u16;
56 if (uSyscallNo == BS3_SYSCALL_PRINT_CHR)
57 Bs3PrintChr(pTrapFrame->Ctx.rcx.u8);
58 else if (uSyscallNo == BS3_SYSCALL_PRINT_STR)
59 Bs3PrintStrN(Bs3XptrFlatToCurrent(((uint32_t)pTrapFrame->Ctx.rcx.u16 << 4) + pTrapFrame->Ctx.rsi.u16),
60 pTrapFrame->Ctx.rdx.u16);
61 else if (uSyscallNo == BS3_SYSCALL_RESTORE_CTX)
62 Bs3RegCtxRestore(Bs3XptrFlatToCurrent(((uint32_t)pTrapFrame->Ctx.rcx.u16 << 4) + pTrapFrame->Ctx.rsi.u16),
63 pTrapFrame->Ctx.rdx.u16);
64 else if ( uSyscallNo == BS3_SYSCALL_TO_RING0
65 || uSyscallNo == BS3_SYSCALL_TO_RING1
66 || uSyscallNo == BS3_SYSCALL_TO_RING2
67 || uSyscallNo == BS3_SYSCALL_TO_RING3)
68 {
69 Bs3RegCtxConvertToRingX(&pTrapFrame->Ctx, pTrapFrame->Ctx.rax.u16 - BS3_SYSCALL_TO_RING0);
70 }
71 else if (uSyscallNo == BS3_SYSCALL_SET_DRX)
72 {
73 uint32_t uValue = pTrapFrame->Ctx.rsi.u32;
74 switch (pTrapFrame->Ctx.rdx.u8)
75 {
76 case 0: ASMSetDR0(uValue); break;
77 case 1: ASMSetDR1(uValue); break;
78 case 2: ASMSetDR2(uValue); break;
79 case 3: ASMSetDR3(uValue); break;
80 case 6: ASMSetDR6(uValue); break;
81 case 7: ASMSetDR7(uValue); break;
82 default: Bs3Panic();
83 }
84 }
85 else if (uSyscallNo == BS3_SYSCALL_GET_DRX)
86 {
87 uint32_t uValue;
88 switch (pTrapFrame->Ctx.rdx.u8)
89 {
90 case 0: uValue = ASMGetDR0(); break;
91 case 1: uValue = ASMGetDR1(); break;
92 case 2: uValue = ASMGetDR2(); break;
93 case 3: uValue = ASMGetDR3(); break;
94 case 6: uValue = ASMGetDR6(); break;
95 case 7: uValue = ASMGetDR7(); break;
96 default: uValue = 0; Bs3Panic();
97 }
98 pTrapFrame->Ctx.rax.u32 = uValue;
99 pTrapFrame->Ctx.rdx.u32 = uValue >> 16;
100 }
101 else if (uSyscallNo == BS3_SYSCALL_SET_CRX)
102 {
103 uint32_t uValue = pTrapFrame->Ctx.rsi.u32;
104 switch (pTrapFrame->Ctx.rdx.u8)
105 {
106 case 0: ASMSetCR0(uValue); pTrapFrame->Ctx.cr0.u32 = uValue; break;
107 case 2: ASMSetCR2(uValue); pTrapFrame->Ctx.cr2.u32 = uValue; break;
108 case 3: ASMSetCR3(uValue); pTrapFrame->Ctx.cr3.u32 = uValue; break;
109 case 4: ASMSetCR4(uValue); pTrapFrame->Ctx.cr4.u32 = uValue; break;
110 default: Bs3Panic();
111 }
112 }
113 else if (uSyscallNo == BS3_SYSCALL_GET_CRX)
114 {
115 uint32_t uValue;
116 switch (pTrapFrame->Ctx.rdx.u8)
117 {
118 case 0: uValue = ASMGetDR0(); break;
119 case 2: uValue = ASMGetCR2(); break;
120 case 3: uValue = ASMGetCR3(); break;
121 case 4: uValue = ASMGetCR4(); break;
122 default: uValue = 0; Bs3Panic();
123 }
124 pTrapFrame->Ctx.rax.u32 = uValue;
125 pTrapFrame->Ctx.rdx.u32 = uValue >> 16;
126 }
127 else if (uSyscallNo == BS3_SYSCALL_SET_TR)
128 {
129 Bs3RegSetTr(pTrapFrame->Ctx.rdx.u16);
130 pTrapFrame->Ctx.tr = pTrapFrame->Ctx.rdx.u16;
131 }
132 else if (uSyscallNo == BS3_SYSCALL_GET_TR)
133 pTrapFrame->Ctx.rax.u16 = ASMGetTR();
134 else if (uSyscallNo == BS3_SYSCALL_SET_LDTR)
135 {
136 Bs3RegSetLdtr(pTrapFrame->Ctx.rdx.u16);
137 pTrapFrame->Ctx.ldtr = pTrapFrame->Ctx.rdx.u16;
138 }
139 else if (uSyscallNo == BS3_SYSCALL_GET_LDTR)
140 pTrapFrame->Ctx.rax.u16 = ASMGetLDTR();
141 else
142 Bs3Panic();
143}
144#endif
145
146#undef Bs3TrapDefaultHandler
147BS3_CMN_DEF(void, Bs3TrapDefaultHandler,(PBS3TRAPFRAME pTrapFrame))
148{
149#if TMPL_BITS != 64
150 /*
151 * v8086 VMM tasks.
152 */
153 //Bs3TestHostPrintf("Bs3____DefaultHandler: %02xh %04RX16:%08RX32 %08RX32 %04RX16:%08RX32 %d %d\n", pTrapFrame->bXcpt,
154 // pTrapFrame->Ctx.cs, pTrapFrame->Ctx.rip.u32, pTrapFrame->Ctx.rflags.u32, pTrapFrame->Ctx.ss,
155 // pTrapFrame->Ctx.rsp.u32, g_fBs3TrapNoV86Assist, 42);
156 if ((pTrapFrame->Ctx.rflags.u32 & X86_EFL_VM))
157 {
158 bool fHandled = true;
159 uint8_t cBitsOpcode = 16;
160 uint8_t bOpCode;
161 uint8_t const BS3_FAR *pbCodeStart;
162 uint8_t const BS3_FAR *pbCode;
163 uint16_t BS3_FAR *pusStack;
164
165 pusStack = (uint16_t BS3_FAR *)BS3_MAKE_PROT_R0PTR_FROM_REAL(pTrapFrame->Ctx.ss, pTrapFrame->Ctx.rsp.u16);
166 pbCode = (uint8_t const BS3_FAR *)BS3_MAKE_PROT_R0PTR_FROM_REAL(pTrapFrame->Ctx.cs, pTrapFrame->Ctx.rip.u16);
167 pbCodeStart = pbCode;
168
169 /*
170 * Deal with GPs in V8086 mode.
171 */
172 if ( pTrapFrame->bXcpt == X86_XCPT_GP
173 && !g_fBs3TrapNoV86Assist)
174 {
175 bOpCode = *pbCode++;
176 if (bOpCode == 0x66)
177 {
178 cBitsOpcode = 32;
179 bOpCode = *pbCode++;
180 }
181
182 /* INT xx: Real mode behaviour, but intercepting and implementing most of our syscall interface. */
183 if (bOpCode == 0xcd)
184 {
185 uint8_t bVector = *pbCode++;
186 if (bVector == BS3_TRAP_SYSCALL)
187 bs3TrapDefaultHandlerV8086Syscall(pTrapFrame);
188 else
189 {
190 /* Real mode behaviour. */
191 uint16_t BS3_FAR *pusIvte = (uint16_t BS3_FAR *)BS3_MAKE_PROT_R0PTR_FROM_REAL(0, 0);
192 pusIvte += (uint16_t)bVector *2;
193
194 pusStack[0] = pTrapFrame->Ctx.rflags.u16;
195 pusStack[1] = pTrapFrame->Ctx.cs;
196 pusStack[2] = pTrapFrame->Ctx.rip.u16 + (uint16_t)(pbCode - pbCodeStart);
197
198 pTrapFrame->Ctx.rip.u16 = pusIvte[0];
199 pTrapFrame->Ctx.cs = pusIvte[1];
200 pTrapFrame->Ctx.rflags.u16 &= ~X86_EFL_IF; /** @todo this isn't all, but it'll do for now, I hope. */
201 Bs3RegCtxRestore(&pTrapFrame->Ctx, 0/*fFlags*/); /* does not return. */
202 }
203 }
204 /* PUSHF: Real mode behaviour. */
205 else if (bOpCode == 0x9c)
206 {
207 if (cBitsOpcode == 32)
208 *pusStack++ = pTrapFrame->Ctx.rflags.au16[1] & ~(X86_EFL_VM | X86_EFL_RF);
209 *pusStack++ = pTrapFrame->Ctx.rflags.u16;
210 pTrapFrame->Ctx.rsp.u16 += cBitsOpcode / 8;
211 }
212 /* POPF: Real mode behaviour. */
213 else if (bOpCode == 0x9d)
214 {
215 if (cBitsOpcode == 32)
216 {
217 pTrapFrame->Ctx.rflags.u32 &= ~X86_EFL_POPF_BITS;
218 pTrapFrame->Ctx.rflags.u32 |= X86_EFL_POPF_BITS & *(uint32_t const *)pusStack;
219 }
220 else
221 {
222 pTrapFrame->Ctx.rflags.u32 &= ~(X86_EFL_POPF_BITS | UINT32_C(0xffff0000)) & ~X86_EFL_RF;
223 pTrapFrame->Ctx.rflags.u16 |= (uint16_t)X86_EFL_POPF_BITS & *pusStack;
224 }
225 pTrapFrame->Ctx.rsp.u16 -= cBitsOpcode / 8;
226 }
227 /* CLI: Real mode behaviour. */
228 else if (bOpCode == 0xfa)
229 pTrapFrame->Ctx.rflags.u16 &= ~X86_EFL_IF;
230 /* STI: Real mode behaviour. */
231 else if (bOpCode == 0xfb)
232 pTrapFrame->Ctx.rflags.u16 |= X86_EFL_IF;
233 /* OUT: byte I/O to VMMDev. */
234 else if ( bOpCode == 0xee
235 && ((unsigned)(pTrapFrame->Ctx.rdx.u16 - VMMDEV_TESTING_IOPORT_BASE) < (unsigned)VMMDEV_TESTING_IOPORT_COUNT))
236 ASMOutU8(pTrapFrame->Ctx.rdx.u16, pTrapFrame->Ctx.rax.u8);
237 /* OUT: [d]word I/O to VMMDev. */
238 else if ( bOpCode == 0xef
239 && ((unsigned)(pTrapFrame->Ctx.rdx.u16 - VMMDEV_TESTING_IOPORT_BASE) < (unsigned)VMMDEV_TESTING_IOPORT_COUNT))
240 {
241 if (cBitsOpcode != 32)
242 ASMOutU16(pTrapFrame->Ctx.rdx.u16, pTrapFrame->Ctx.rax.u16);
243 else
244 ASMOutU32(pTrapFrame->Ctx.rdx.u16, pTrapFrame->Ctx.rax.u32);
245 }
246 /* IN: byte I/O to VMMDev. */
247 else if ( bOpCode == 0xec
248 && ((unsigned)(pTrapFrame->Ctx.rdx.u16 - VMMDEV_TESTING_IOPORT_BASE) < (unsigned)VMMDEV_TESTING_IOPORT_COUNT))
249 pTrapFrame->Ctx.rax.u8 = ASMInU8(pTrapFrame->Ctx.rdx.u16);
250 /* IN: [d]word I/O to VMMDev. */
251 else if ( bOpCode == 0xed
252 && ((unsigned)(pTrapFrame->Ctx.rdx.u16 - VMMDEV_TESTING_IOPORT_BASE) < (unsigned)VMMDEV_TESTING_IOPORT_COUNT))
253 {
254 if (cBitsOpcode != 32)
255 pTrapFrame->Ctx.rax.u16 = ASMInU16(pTrapFrame->Ctx.rdx.u16);
256 else
257 pTrapFrame->Ctx.rax.u32 = ASMInU32(pTrapFrame->Ctx.rdx.u32);
258 }
259 /* Unexpected. */
260 else
261 fHandled = false;
262 }
263 /*
264 * Deal with lock prefixed int xxh syscall in v8086 mode.
265 */
266 else if ( pTrapFrame->bXcpt == X86_XCPT_UD
267 && pTrapFrame->Ctx.cs == BS3_SEL_TEXT16
268 && pTrapFrame->Ctx.rax.u16 <= BS3_SYSCALL_LAST
269 && pbCode[0] == 0xf0
270 && pbCode[1] == 0xcd
271 && pbCode[2] == BS3_TRAP_SYSCALL)
272 {
273 pbCode += 3;
274 bs3TrapDefaultHandlerV8086Syscall(pTrapFrame);
275 }
276 else
277 {
278 fHandled = false;
279 }
280 if (fHandled)
281 {
282 pTrapFrame->Ctx.rip.u16 += (uint16_t)(pbCode - pbCodeStart);
283# if 0
284 Bs3Printf("Calling Bs3RegCtxRestore\n");
285 Bs3RegCtxPrint(&pTrapFrame->Ctx);
286# endif
287 Bs3RegCtxRestore(&pTrapFrame->Ctx, 0 /*fFlags*/); /* does not return. */
288 return;
289 }
290 }
291#endif
292
293 /*
294 * Any pending setjmp?
295 */
296 if (g_pBs3TrapSetJmpFrame != 0)
297 {
298 PBS3TRAPFRAME pSetJmpFrame = (PBS3TRAPFRAME)Bs3XptrFlatToCurrent(g_pBs3TrapSetJmpFrame);
299 //Bs3Printf("Calling longjmp: pSetJmpFrame=%p (%#lx)\n", pSetJmpFrame, g_pBs3TrapSetJmpFrame);
300 g_pBs3TrapSetJmpFrame = 0;
301 Bs3MemCpy(pSetJmpFrame, pTrapFrame, sizeof(*pSetJmpFrame));
302 //Bs3RegCtxPrint(&g_Bs3TrapSetJmpCtx);
303 Bs3RegCtxRestore(&g_Bs3TrapSetJmpCtx, 0 /*fFlags*/);
304 }
305
306 /*
307 * Fatal.
308 */
309 Bs3TestPrintf("*** GURU ***\n");
310 Bs3TrapPrintFrame(pTrapFrame);
311 Bs3Panic();
312}
313
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