VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-basic-2-template.c@ 60215

Last change on this file since 60215 was 60215, checked in by vboxsync, 9 years ago

bs3-cpu-basic-2: cleanups

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 29.0 KB
Line 
1/* $Id: bs3-cpu-basic-2-template.c 60215 2016-03-27 23:39:19Z vboxsync $ */
2/** @file
3 * BS3Kit - bs3-cpu-basic-2, C code template.
4 */
5
6/*
7 * Copyright (C) 2007-2016 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.215389.xyz. 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#ifdef BS3_INSTANTIATING_MODE
29
30/*********************************************************************************************************************************
31* Header Files *
32*********************************************************************************************************************************/
33#include <iprt/asm.h>
34#include <iprt/asm-amd64-x86.h>
35
36
37/*********************************************************************************************************************************
38* Defined Constants And Macros *
39*********************************************************************************************************************************/
40# undef MyBs3Idt
41# undef MY_SYS_SEL_R0_CS
42# undef MY_SYS_SEL_R0_CS_CNF
43# undef MY_SYS_SEL_R0_DS
44# undef MY_SYS_SEL_R0_SS
45# if BS3_MODE_IS_16BIT_SYS(TMPL_MODE)
46# define MyBs3Idt BS3_DATA_NM(Bs3Idt16)
47# define MY_SYS_SEL_R0_CS BS3_SEL_R0_CS16
48# define MY_SYS_SEL_R0_CS_CNF BS3_SEL_R0_CS16_CNF
49# define MY_SYS_SEL_R0_DS BS3_SEL_R0_DS16
50# define MY_SYS_SEL_R0_SS BS3_SEL_R0_SS16
51# elif BS3_MODE_IS_32BIT_SYS(TMPL_MODE)
52# define MyBs3Idt BS3_DATA_NM(Bs3Idt32)
53# define MY_SYS_SEL_R0_CS BS3_SEL_R0_CS32
54# define MY_SYS_SEL_R0_CS_CNF BS3_SEL_R0_CS32_CNF
55# define MY_SYS_SEL_R0_DS BS3_SEL_R0_DS32
56# define MY_SYS_SEL_R0_SS BS3_SEL_R0_SS32
57# elif BS3_MODE_IS_64BIT_SYS(TMPL_MODE)
58# define MyBs3Idt BS3_DATA_NM(Bs3Idt64)
59# define MY_SYS_SEL_R0_CS BS3_SEL_R0_CS64
60# define MY_SYS_SEL_R0_CS_CNF BS3_SEL_R0_CS64_CNF
61# define MY_SYS_SEL_R0_DS BS3_SEL_R0_DS64
62# define MY_SYS_SEL_R0_SS BS3_SEL_R0_DS64
63# else
64# error "TMPL_MODE"
65# endif
66#undef CHECK_MEMBER
67#define CHECK_MEMBER(a_szName, a_szFmt, a_Actual, a_Expected) \
68 do \
69 { \
70 if ((a_Actual) == (a_Expected)) { /* likely */ } \
71 else Bs3TestFailedF("%u - %s: " a_szName "=" a_szFmt " expected " a_szFmt, uLine, pszMode, (a_Actual), (a_Expected)); \
72 } while (0)
73
74
75/*********************************************************************************************************************************
76* Internal Functions *
77*********************************************************************************************************************************/
78extern BS3_DECL(void) TMPL_NM(bs3CpuBasic2_Int80)(void);
79extern BS3_DECL(void) TMPL_NM(bs3CpuBasic2_Int81)(void);
80extern BS3_DECL(void) TMPL_NM(bs3CpuBasic2_Int82)(void);
81extern BS3_DECL(void) TMPL_NM(bs3CpuBasic2_Int83)(void);
82
83
84#if TMPL_MODE == BS3_MODE_PE16 || TMPL_MODE == BS3_MODE_PE16_32 || TMPL_MODE == BS3_MODE_LM64
85
86/**
87 * Compares trap stuff.
88 */
89#define bs3CpuBasic2_CompareTrapCtx1 BS3_CMN_NM(bs3CpuBasic2_CompareTrapCtx1)
90void bs3CpuBasic2_CompareTrapCtx1(PCBS3TRAPFRAME pTrapCtx, PCBS3REGCTX pStartCtx, uint16_t cbIpAdjust, uint8_t bXcpt,
91 const char *pszMode, unsigned uLine)
92{
93 uint16_t const cErrorsBefore = Bs3TestSubErrorCount();
94 CHECK_MEMBER("bXcpt", "%#04x", pTrapCtx->bXcpt, bXcpt);
95 CHECK_MEMBER("bErrCd", "%#06RX64", pTrapCtx->uErrCd, 0);
96 Bs3TestCheckRegCtxEx(&pTrapCtx->Ctx, pStartCtx, cbIpAdjust, 0 /*cbSpAdjust*/, 0 /*fExtraEfl*/, pszMode, uLine);
97 if (Bs3TestSubErrorCount() != cErrorsBefore)
98 {
99//Bs3TestPrintf("%s\n", __FUNCTION__);
100 Bs3TrapPrintFrame(pTrapCtx);
101ASMHalt();
102 }
103}
104
105
106/**
107 * Compares trap stuff.
108 */
109#define bs3CpuBasic2_CompareTrapCtx2 BS3_CMN_NM(bs3CpuBasic2_CompareTrapCtx2)
110void bs3CpuBasic2_CompareTrapCtx2(PCBS3TRAPFRAME pTrapCtx, PCBS3REGCTX pStartCtx, uint16_t cbIpAdjust, uint8_t bXcpt,
111 uint16_t uHandlerCs, const char *pszMode, unsigned uLine)
112{
113 uint16_t const cErrorsBefore = Bs3TestSubErrorCount();
114 CHECK_MEMBER("bXcpt", "%#04x", pTrapCtx->bXcpt, bXcpt);
115 CHECK_MEMBER("bErrCd", "%#06RX64", pTrapCtx->uErrCd, 0);
116 CHECK_MEMBER("uHandlerCs", "%#06x", pTrapCtx->uHandlerCs, uHandlerCs);
117 Bs3TestCheckRegCtxEx(&pTrapCtx->Ctx, pStartCtx, cbIpAdjust, 0 /*cbSpAdjust*/, 0 /*fExtraEfl*/, pszMode, uLine);
118 if (Bs3TestSubErrorCount() != cErrorsBefore)
119 {
120//Bs3TestPrintf("%s\n", __FUNCTION__);
121 Bs3TrapPrintFrame(pTrapCtx);
122ASMHalt();
123 }
124}
125
126/**
127 * Compares trap stuff.
128 */
129#define bs3CpuBasic2_CompareGpCtx BS3_CMN_NM(bs3CpuBasic2_CompareGpCtx)
130void bs3CpuBasic2_CompareGpCtx(PCBS3TRAPFRAME pTrapCtx, PCBS3REGCTX pStartCtx, uint16_t uErrCd, bool f16BitHandler,
131 const char *pszMode, unsigned uLine)
132{
133 uint16_t const cErrorsBefore = Bs3TestSubErrorCount();
134 CHECK_MEMBER("bXcpt", "%#04x", pTrapCtx->bXcpt, X86_XCPT_GP);
135 CHECK_MEMBER("bErrCd", "%#06RX64", pTrapCtx->uErrCd, (uint64_t)uErrCd);
136 Bs3TestCheckRegCtxEx(&pTrapCtx->Ctx, pStartCtx, 0 /*cbIpAdjust*/, 0 /*cbSpAdjust*/,
137 f16BitHandler ? 0 : X86_EFL_RF,
138 pszMode, uLine);
139 if (Bs3TestSubErrorCount() != cErrorsBefore)
140 {
141//Bs3TestPrintf("%s\n", __FUNCTION__);
142 Bs3TrapPrintFrame(pTrapCtx);
143ASMHalt();
144 }
145}
146
147/**
148 * Compares trap stuff.
149 */
150#define bs3CpuBasic2_CompareNpCtx BS3_CMN_NM(bs3CpuBasic2_CompareNpCtx)
151void bs3CpuBasic2_CompareNpCtx(PCBS3TRAPFRAME pTrapCtx, PCBS3REGCTX pStartCtx, uint16_t uErrCd, bool f16BitHandler,
152 const char *pszMode, unsigned uLine)
153{
154 uint16_t const cErrorsBefore = Bs3TestSubErrorCount();
155 CHECK_MEMBER("bXcpt", "%#04x", pTrapCtx->bXcpt, X86_XCPT_NP);
156 CHECK_MEMBER("bErrCd", "%#06RX64", pTrapCtx->uErrCd, (uint64_t)uErrCd);
157 Bs3TestCheckRegCtxEx(&pTrapCtx->Ctx, pStartCtx, 0 /*cbIpAdjust*/, 0 /*cbSpAdjust*/,
158 f16BitHandler ? 0 : X86_EFL_RF,
159 pszMode, uLine);
160 if (Bs3TestSubErrorCount() != cErrorsBefore)
161 {
162//Bs3TestPrintf("%s\n", __FUNCTION__);
163 Bs3TrapPrintFrame(pTrapCtx);
164ASMHalt();
165 }
166}
167
168#define bs3CpuBasic2_RaiseXcpt1Common BS3_CMN_NM(bs3CpuBasic2_RaiseXcpt1Common)
169static void bs3CpuBasic2_RaiseXcpt1Common(uint8_t const bMode, const char * const pszMode, bool const f16BitSys,
170 uint16_t const uSysR0Cs, uint16_t const uSysR0CsConf,
171 PX86DESC const paIdt, unsigned const cIdteShift)
172{
173 BS3TRAPFRAME TrapCtx;
174 BS3REGCTX Ctx80;
175 BS3REGCTX Ctx81;
176 BS3REGCTX Ctx82;
177 BS3REGCTX Ctx83;
178 BS3REGCTX CtxTmp;
179 PBS3REGCTX apCtx8x[4];
180 unsigned iCtx;
181 unsigned iRing;
182 unsigned i, j, k;
183 unsigned uLine;
184
185 //uLine = 0; NOREF(uLine); NOREF(pszMode); NOREF(f16BitSys);
186
187 /* make sure they're allocated */
188 Bs3MemZero(&Ctx80, sizeof(Ctx80));
189 Bs3MemZero(&Ctx81, sizeof(Ctx81));
190 Bs3MemZero(&Ctx82, sizeof(Ctx82));
191 Bs3MemZero(&Ctx83, sizeof(Ctx83));
192 Bs3MemZero(&CtxTmp, sizeof(CtxTmp));
193 Bs3MemZero(&TrapCtx, sizeof(TrapCtx));
194
195 /* Context array. */
196 apCtx8x[0] = &Ctx80;
197 apCtx8x[1] = &Ctx81;
198 apCtx8x[2] = &Ctx82;
199 apCtx8x[3] = &Ctx83;
200
201 /*
202 * IDT entry 80 thru 83 are assigned DPLs according to the number.
203 * (We'll be useing more, but this'll do for now.)
204 */
205 paIdt[0x80 << cIdteShift].Gate.u2Dpl = 0;
206 paIdt[0x81 << cIdteShift].Gate.u2Dpl = 1;
207 paIdt[0x82 << cIdteShift].Gate.u2Dpl = 2;
208 paIdt[0x83 << cIdteShift].Gate.u2Dpl = 3;
209
210 Bs3RegCtxSave(&Ctx80);
211 Ctx80.rsp.u -= 0x80;
212 Ctx80.rip.u = (uintptr_t)BS3_FP_OFF(&TMPL_NM(bs3CpuBasic2_Int80));
213# if TMPL_BITS == 32
214 BS3_DATA_NM(g_uBs3TrapEipHint) = Ctx80.rip.u32;
215# endif
216 Bs3MemCpy(&Ctx81, &Ctx80, sizeof(Ctx80));
217 Ctx81.rip.u = (uintptr_t)BS3_FP_OFF(&TMPL_NM(bs3CpuBasic2_Int81));
218 Bs3MemCpy(&Ctx82, &Ctx80, sizeof(Ctx80));
219 Ctx82.rip.u = (uintptr_t)BS3_FP_OFF(&TMPL_NM(bs3CpuBasic2_Int82));
220 Bs3MemCpy(&Ctx83, &Ctx80, sizeof(Ctx80));
221 Ctx83.rip.u = (uintptr_t)BS3_FP_OFF(&TMPL_NM(bs3CpuBasic2_Int83));
222
223 /*
224 * Check that all the above gates work from ring-0.
225 */
226 for (iCtx = 0; iCtx < RT_ELEMENTS(apCtx8x); iCtx++)
227 {
228# if TMPL_BITS == 32
229 BS3_DATA_NM(g_uBs3TrapEipHint) = apCtx8x[iCtx]->rip.u32;
230# endif
231 Bs3TrapSetJmpAndRestore(apCtx8x[iCtx], &TrapCtx);
232 bs3CpuBasic2_CompareTrapCtx1(&TrapCtx, apCtx8x[iCtx], 2 /*int 80h*/, 0x80+iCtx /*bXcpt*/, pszMode, iCtx);
233 }
234
235 /*
236 * Check that the gate DPL checks works.
237 */
238 uLine = 100;
239 for (iRing = 0; iRing <= 3; iRing++)
240 {
241 for (iCtx = 0; iCtx < RT_ELEMENTS(apCtx8x); iCtx++)
242 {
243 Bs3MemCpy(&CtxTmp, apCtx8x[iCtx], sizeof(CtxTmp));
244 Bs3RegCtxConvertToRingX(&CtxTmp, iRing);
245# if TMPL_BITS == 32
246 BS3_DATA_NM(g_uBs3TrapEipHint) = CtxTmp.rip.u32;
247# endif
248 Bs3TrapSetJmpAndRestore(&CtxTmp, &TrapCtx);
249 uLine++;
250 if (iCtx < iRing)
251 bs3CpuBasic2_CompareGpCtx(&TrapCtx, &CtxTmp, ((0x80 + iCtx) << X86_TRAP_ERR_SEL_SHIFT) | X86_TRAP_ERR_IDT,
252 f16BitSys, pszMode, uLine);
253 else
254 bs3CpuBasic2_CompareTrapCtx1(&TrapCtx, &CtxTmp, 2 /*int 8xh*/, 0x80 + iCtx /*bXcpt*/, pszMode, uLine);
255 }
256 }
257
258 /*
259 * Modify the gate CS value and run the handler at a different CPL.
260 * Throw RPL variations into the mix (completely ignored) together
261 * with gate presence.
262 * 1. CPL <= GATE.DPL
263 * 2. GATE.P
264 * 3. GATE.CS.DPL <= CPL (non-conforming segments)
265 */
266 uLine = 1000;
267 for (i = 0; i <= 3; i++)
268 {
269 for (iRing = 0; iRing <= 3; iRing++)
270 {
271 for (iCtx = 0; iCtx < RT_ELEMENTS(apCtx8x); iCtx++)
272 {
273# if TMPL_BITS == 32
274 BS3_DATA_NM(g_uBs3TrapEipHint) = apCtx8x[iCtx]->rip.u32;
275# endif
276 Bs3MemCpy(&CtxTmp, apCtx8x[iCtx], sizeof(CtxTmp));
277 Bs3RegCtxConvertToRingX(&CtxTmp, iRing);
278
279 for (j = 0; j <= 3; j++)
280 {
281 uint16_t const uCs = (uSysR0Cs | j) + (i << BS3_SEL_RING_SHIFT);
282 for (k = 0; k < 2; k++)
283 {
284 uLine++;
285 /*Bs3TestPrintf("uLine=%u iCtx=%u iRing=%u i=%u uCs=%04x\n", uLine, iCtx, iRing, i, uCs);*/
286 paIdt[(0x80 + iCtx) << cIdteShift].Gate.u16Sel = uCs;
287 paIdt[(0x80 + iCtx) << cIdteShift].Gate.u1Present = k;
288 Bs3TrapSetJmpAndRestore(&CtxTmp, &TrapCtx);
289 /*Bs3TrapPrintFrame(&TrapCtx);*/
290 if (iCtx < iRing)
291 bs3CpuBasic2_CompareGpCtx(&TrapCtx, &CtxTmp, ((0x80 + iCtx) << X86_TRAP_ERR_SEL_SHIFT) | X86_TRAP_ERR_IDT,
292 f16BitSys, pszMode, uLine);
293 else if (k == 0)
294 bs3CpuBasic2_CompareNpCtx(&TrapCtx, &CtxTmp, ((0x80 + iCtx) << X86_TRAP_ERR_SEL_SHIFT) | X86_TRAP_ERR_IDT,
295 f16BitSys, pszMode, uLine);
296 else if (i > iRing)
297 bs3CpuBasic2_CompareGpCtx(&TrapCtx, &CtxTmp, uCs & X86_SEL_MASK_OFF_RPL, f16BitSys, pszMode, uLine);
298 else
299 {
300 uint16_t uExpectedCs = uCs & X86_SEL_MASK_OFF_RPL;
301 if (i <= iCtx && i <= iRing)
302 uExpectedCs |= i;
303 bs3CpuBasic2_CompareTrapCtx2(&TrapCtx, &CtxTmp, 2 /*int 8xh*/, 0x80 + iCtx /*bXcpt*/,
304 uExpectedCs, pszMode, uLine);
305 }
306 }
307 }
308
309 paIdt[(0x80 + iCtx) << cIdteShift].Gate.u16Sel = uSysR0Cs;
310 paIdt[(0x80 + iCtx) << cIdteShift].Gate.u1Present = 1;
311 }
312 }
313 }
314 BS3_ASSERT(uLine < 2000);
315
316 /*
317 * Modify the gate CS value with a conforming segment.
318 */
319 uLine = 2000;
320 for (i = 0; i <= 3; i++) /* cs.dpl */
321 {
322 for (iRing = 0; iRing <= 3; iRing++)
323 {
324 for (iCtx = 0; iCtx < RT_ELEMENTS(apCtx8x); iCtx++)
325 {
326 Bs3MemCpy(&CtxTmp, apCtx8x[iCtx], sizeof(CtxTmp));
327 Bs3RegCtxConvertToRingX(&CtxTmp, iRing);
328# if TMPL_BITS == 32
329 BS3_DATA_NM(g_uBs3TrapEipHint) = CtxTmp.rip.u32;
330# endif
331
332 for (j = 0; j <= 3; j++) /* rpl */
333 {
334 uint16_t const uCs = (uSysR0CsConf | j) + (i << BS3_SEL_RING_SHIFT);
335 /*Bs3TestPrintf("uLine=%u iCtx=%u iRing=%u i=%u uCs=%04x\n", uLine, iCtx, iRing, i, uCs);*/
336 paIdt[(0x80 + iCtx) << cIdteShift].Gate.u16Sel = uCs;
337 Bs3TrapSetJmpAndRestore(&CtxTmp, &TrapCtx);
338 //Bs3TestPrintf("%u/%u/%u/%u: cs=%04x hcs=%04x xcpt=%02x\n", i, iRing, iCtx, j, uCs, TrapCtx.uHandlerCs, TrapCtx.bXcpt);
339 /*Bs3TrapPrintFrame(&TrapCtx);*/
340 uLine++;
341 if (iCtx < iRing)
342 bs3CpuBasic2_CompareGpCtx(&TrapCtx, &CtxTmp, ((0x80 + iCtx) << X86_TRAP_ERR_SEL_SHIFT) | X86_TRAP_ERR_IDT,
343 f16BitSys, pszMode, 1);//uLine);
344 else if (i > iRing)
345 bs3CpuBasic2_CompareGpCtx(&TrapCtx, &CtxTmp, uCs & X86_SEL_MASK_OFF_RPL, f16BitSys, pszMode, 2);//uLine);
346 else
347 bs3CpuBasic2_CompareTrapCtx1(&TrapCtx, &CtxTmp, 2 /*int 8xh*/, 0x80 + iCtx /*bXcpt*/, pszMode, 3);//uLine);
348 }
349 paIdt[(0x80 + iCtx) << cIdteShift].Gate.u16Sel = uSysR0Cs;
350 }
351 }
352 }
353 BS3_ASSERT(uLine < 3000);
354
355 /*
356 * The gates must be 64-bit in long mode..
357 */
358 if (cIdteShift != 0)
359 {
360 uLine = 3000;
361 for (i = 0; i <= 3; i++)
362 {
363 for (iRing = 0; iRing <= 3; iRing++)
364 {
365 for (iCtx = 0; iCtx < RT_ELEMENTS(apCtx8x); iCtx++)
366 {
367 Bs3MemCpy(&CtxTmp, apCtx8x[iCtx], sizeof(CtxTmp));
368 Bs3RegCtxConvertToRingX(&CtxTmp, iRing);
369
370 for (j = 0; j < 2; j++)
371 {
372 static const uint16_t s_auCSes[2] = { BS3_SEL_R0_CS16, BS3_SEL_R0_CS32 };
373 uint16_t uCs = (s_auCSes[j] | i) + (i << BS3_SEL_RING_SHIFT);
374 uLine++;
375 /*Bs3TestPrintf("uLine=%u iCtx=%u iRing=%u i=%u uCs=%04x\n", uLine, iCtx, iRing, i, uCs);*/
376 paIdt[(0x80 + iCtx) << cIdteShift].Gate.u16Sel = uCs;
377 Bs3TrapSetJmpAndRestore(&CtxTmp, &TrapCtx);
378 /*Bs3TrapPrintFrame(&TrapCtx);*/
379 if (iCtx < iRing)
380 bs3CpuBasic2_CompareGpCtx(&TrapCtx, &CtxTmp, ((0x80 + iCtx) << X86_TRAP_ERR_SEL_SHIFT) | X86_TRAP_ERR_IDT,
381 f16BitSys, pszMode, uLine);
382 else
383 bs3CpuBasic2_CompareGpCtx(&TrapCtx, &CtxTmp, uCs & X86_SEL_MASK_OFF_RPL, f16BitSys, pszMode, uLine);
384 }
385 paIdt[(0x80 + iCtx) << cIdteShift].Gate.u16Sel = uSysR0Cs;
386 }
387 }
388 }
389 BS3_ASSERT(uLine < 4000);
390 }
391
392 /*
393 * Check invalid gate types.
394 */
395 uLine = 32000;
396 for (iRing = 0; iRing <= 3; iRing++)
397 {
398 static const uint16_t s_auCSes[] = { BS3_SEL_R0_CS16, BS3_SEL_R0_CS32, BS3_SEL_R0_CS64,
399 BS3_SEL_TSS16, BS3_SEL_TSS32, BS3_SEL_TSS64, 0, BS3_SEL_SPARE_1f };
400 static uint16_t const s_auInvlTypes64[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13,
401 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
402 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f };
403 static uint16_t const s_auInvlTypes32[] = { 0, 1, 2, 3, 8, 9, 10, 11, 13,
404 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
405 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
406 /*286:*/ 12, 14, 15 };
407 uint16_t const * const pauInvTypes = cIdteShift != 0 ? s_auInvlTypes64 : s_auInvlTypes32;
408 uint16_t const cInvTypes = cIdteShift != 0 ? RT_ELEMENTS(s_auInvlTypes64)
409 : (BS3_DATA_NM(g_uBs3CpuDetected) & BS3CPU_TYPE_MASK) < BS3CPU_80386
410 ? RT_ELEMENTS(s_auInvlTypes32) : RT_ELEMENTS(s_auInvlTypes32) - 3;
411
412
413 for (iCtx = 0; iCtx < RT_ELEMENTS(apCtx8x); iCtx++)
414 {
415 unsigned iType;
416
417 Bs3MemCpy(&CtxTmp, apCtx8x[iCtx], sizeof(CtxTmp));
418 Bs3RegCtxConvertToRingX(&CtxTmp, iRing);
419# if TMPL_BITS == 32
420 BS3_DATA_NM(g_uBs3TrapEipHint) = CtxTmp.rip.u32;
421# endif
422 for (iType = 0; iType < cInvTypes; iType++)
423 {
424 uint8_t const bSavedType = paIdt[(0x80 + iCtx) << cIdteShift].Gate.u4Type;
425 paIdt[(0x80 + iCtx) << cIdteShift].Gate.u1DescType = pauInvTypes[iType] >> 4;
426 paIdt[(0x80 + iCtx) << cIdteShift].Gate.u4Type = pauInvTypes[iType] & 0xf;
427
428 for (i = 0; i < 4; i++)
429 {
430 for (j = 0; j < RT_ELEMENTS(s_auCSes); j++)
431 {
432 uint16_t uCs = (unsigned)(s_auCSes[j] - BS3_SEL_R0_FIRST) < (unsigned)(4 << BS3_SEL_RING_SHIFT)
433 ? (s_auCSes[j] | i) + (i << BS3_SEL_RING_SHIFT)
434 : s_auCSes[j] | i;
435 /*Bs3TestPrintf("uLine=%u iCtx=%u iRing=%u i=%u uCs=%04x type=%#x\n", uLine, iCtx, iRing, i, uCs, pauInvTypes[iType]);*/
436 paIdt[(0x80 + iCtx) << cIdteShift].Gate.u16Sel = uCs;
437 Bs3TrapSetJmpAndRestore(&CtxTmp, &TrapCtx);
438 uLine++;
439 bs3CpuBasic2_CompareGpCtx(&TrapCtx, &CtxTmp, ((0x80 + iCtx) << X86_TRAP_ERR_SEL_SHIFT) | X86_TRAP_ERR_IDT,
440 f16BitSys, pszMode, uLine);
441
442 /* Mark it not-present to check that invalid type takes precedence. */
443 paIdt[(0x80 + iCtx) << cIdteShift].Gate.u1Present = 0;
444 Bs3TrapSetJmpAndRestore(&CtxTmp, &TrapCtx);
445 uLine++;
446 bs3CpuBasic2_CompareGpCtx(&TrapCtx, &CtxTmp, ((0x80 + iCtx) << X86_TRAP_ERR_SEL_SHIFT) | X86_TRAP_ERR_IDT,
447 f16BitSys, pszMode, uLine);
448 paIdt[(0x80 + iCtx) << cIdteShift].Gate.u1Present = 1;
449 }
450 }
451
452 paIdt[(0x80 + iCtx) << cIdteShift].Gate.u16Sel = MY_SYS_SEL_R0_CS;
453 paIdt[(0x80 + iCtx) << cIdteShift].Gate.u4Type = bSavedType;
454 paIdt[(0x80 + iCtx) << cIdteShift].Gate.u1DescType = 0;
455 paIdt[(0x80 + iCtx) << cIdteShift].Gate.u1Present = 1;
456 }
457 }
458 }
459 BS3_ASSERT(uLine < 62000U && uLine > 32000U);
460}
461
462
463#endif /* once for each bitcount */
464
465
466#if TMPL_MODE == BS3_MODE_PE16 || TMPL_MODE == BS3_MODE_PE16_32
467
468/**
469 * Worker for bs3CpuBasic2_TssGateEsp that tests the INT 80 from outer rings.
470 */
471#define bs3CpuBasic2_TssGateEsp_AltStackOuterRing BS3_CMN_NM(bs3CpuBasic2_TssGateEsp_AltStackOuterRing)
472void bs3CpuBasic2_TssGateEsp_AltStackOuterRing(PCBS3REGCTX pCtx, uint8_t bRing, uint8_t *pbAltStack, size_t cbAltStack,
473 bool f16BitStack, bool f16BitTss, bool f16BitHandler,
474 const char *pszMode, unsigned uLine)
475{
476 uint8_t const cbIretFrame = f16BitHandler ? 5*2 : 5*4;
477 BS3REGCTX Ctx2;
478 BS3TRAPFRAME TrapCtx;
479 uint8_t *pbTmp;
480
481 Bs3MemCpy(&Ctx2, pCtx, sizeof(Ctx2));
482 Bs3RegCtxConvertToRingX(&Ctx2, bRing);
483
484 if (pbAltStack)
485 {
486 Ctx2.rsp.u = Bs3SelPtrToFlat(pbAltStack + 0x1980);
487 Bs3MemZero(pbAltStack, cbAltStack);
488 }
489
490 Bs3TrapSetJmpAndRestore(&Ctx2, &TrapCtx);
491
492 if (!f16BitStack && f16BitTss)
493 Ctx2.rsp.u &= UINT16_MAX;
494
495 bs3CpuBasic2_CompareTrapCtx1(&TrapCtx, &Ctx2, 2 /*int 80h*/, 0x80 /*bXcpt*/, pszMode, uLine);
496 CHECK_MEMBER("bCpl", "%u", TrapCtx.Ctx.bCpl, bRing);
497 CHECK_MEMBER("cbIretFrame", "%#x", TrapCtx.cbIretFrame, cbIretFrame);
498
499 if (pbAltStack)
500 {
501 uint64_t uExpectedRsp = (f16BitTss ? Bs3Tss16.sp0 : Bs3Tss32.esp0) - cbIretFrame;
502 if (f16BitStack)
503 {
504 uExpectedRsp &= UINT16_MAX;
505 uExpectedRsp |= Ctx2.rsp.u & ~(uint64_t)UINT16_MAX;
506 }
507 if ( TrapCtx.uHandlerRsp != uExpectedRsp
508 || TrapCtx.uHandlerSs != (f16BitTss ? Bs3Tss16.ss0 : Bs3Tss32.ss0))
509 Bs3TestFailedF("%u - %s: handler SS:ESP=%04x:%08RX64, expected %04x:%08RX16\n", uLine, pszMode,
510 TrapCtx.uHandlerSs, TrapCtx.uHandlerRsp, Bs3Tss16.ss0, uExpectedRsp);
511
512 pbTmp = (uint8_t *)ASMMemFirstNonZero(pbAltStack, cbAltStack);
513 if ((f16BitStack || TrapCtx.uHandlerRsp <= UINT16_MAX) && pbTmp != NULL)
514 Bs3TestFailedF("%u - %s: someone touched the alt stack (%p) with SS:ESP=%04x:%#RX32: %p=%02x\n", uLine, pszMode,
515 pbAltStack, Ctx2.ss, Ctx2.rsp.u32, pbTmp, *pbTmp);
516 else if (!f16BitStack && TrapCtx.uHandlerRsp > UINT16_MAX && pbTmp == NULL)
517 Bs3TestFailedF("%u - %s: the alt stack (%p) was not used SS:ESP=%04x:%#RX32\n", uLine, pszMode,
518 pbAltStack, Ctx2.ss, Ctx2.rsp.u32);
519 }
520}
521
522#define bs3CpuBasic2_TssGateEspCommon BS3_CMN_NM(bs3CpuBasic2_TssGateEspCommon)
523void bs3CpuBasic2_TssGateEspCommon(uint8_t const bMode, const char * const pszMode, bool const f16BitSys,
524 PX86DESC const paIdt, unsigned const cIdteShift)
525{
526 BS3TRAPFRAME TrapCtx;
527 BS3REGCTX Ctx;
528 BS3REGCTX Ctx2;
529# if TMPL_BITS == 16
530 uint8_t *pbTmp;
531# endif
532 unsigned uLine;
533
534 /* make sure they're allocated */
535 Bs3MemZero(&Ctx, sizeof(Ctx));
536 Bs3MemZero(&Ctx2, sizeof(Ctx2));
537 Bs3MemZero(&TrapCtx, sizeof(TrapCtx));
538
539 Bs3RegCtxSave(&Ctx);
540 Ctx.rsp.u -= 0x80;
541 Ctx.rip.u = (uintptr_t)BS3_FP_OFF(&TMPL_NM(bs3CpuBasic2_Int80));
542# if TMPL_BITS == 32
543 BS3_DATA_NM(g_uBs3TrapEipHint) = Ctx.rip.u32;
544# endif
545
546 /*
547 * We'll be using IDT entry 80 and 81 here. The first one will be
548 * accessible from all DPLs, the latter not. So, start with setting
549 * the DPLs.
550 */
551 paIdt[0x80 << cIdteShift].Gate.u2Dpl = 3;
552 paIdt[0x81 << cIdteShift].Gate.u2Dpl = 0;
553
554 /*
555 * Check that the basic stuff works first.
556 */
557 Bs3TrapSetJmpAndRestore(&Ctx, &TrapCtx);
558 bs3CpuBasic2_CompareTrapCtx1(&TrapCtx, &Ctx, 2 /*int 80h*/, 0x80 /*bXcpt*/, pszMode, __LINE__);
559
560 bs3CpuBasic2_TssGateEsp_AltStackOuterRing(&Ctx, 1, NULL, 0, f16BitSys, f16BitSys, f16BitSys, pszMode, __LINE__);
561 bs3CpuBasic2_TssGateEsp_AltStackOuterRing(&Ctx, 2, NULL, 0, f16BitSys, f16BitSys, f16BitSys, pszMode, __LINE__);
562 bs3CpuBasic2_TssGateEsp_AltStackOuterRing(&Ctx, 3, NULL, 0, f16BitSys, f16BitSys, f16BitSys, pszMode, __LINE__);
563
564 /*
565 * Check that the upper part of ESP is preserved when doing .
566 */
567 if ((BS3_DATA_NM(g_uBs3CpuDetected) & BS3CPU_TYPE_MASK) >= BS3CPU_80386)
568 {
569 size_t const cbAltStack = _8K;
570 uint8_t *pbAltStack = Bs3MemAllocZ(BS3MEMKIND_TILED, cbAltStack);
571 if (pbAltStack)
572 {
573 /* same ring */
574 uLine = __LINE__;
575 Bs3MemCpy(&Ctx2, &Ctx, sizeof(Ctx2));
576 Ctx2.rsp.u = Bs3SelPtrToFlat(pbAltStack + 0x1980);
577 if (Bs3TrapSetJmp(&TrapCtx))
578 Bs3RegCtxRestore(&Ctx2, 0); /* (does not return) */
579 bs3CpuBasic2_CompareTrapCtx1(&TrapCtx, &Ctx2, 2 /*int 80h*/, 0x80 /*bXcpt*/, pszMode, uLine);
580# if TMPL_BITS == 16
581 if ((pbTmp = (uint8_t *)ASMMemFirstNonZero(pbAltStack, cbAltStack)) != NULL)
582 Bs3TestFailedF("%u - %s: someone touched the alt stack (%p) with SS:ESP=%04x:%#RX32: %p=%02x\n",
583 uLine, pszMode, pbAltStack, Ctx2.ss, Ctx2.rsp.u32, pbTmp, *pbTmp);
584# else
585 if (ASMMemIsZero(pbAltStack, cbAltStack))
586 Bs3TestFailedF("%u - %s: alt stack wasn't used despite SS:ESP=%04x:%#RX32\n",
587 uLine, pszMode, Ctx2.ss, Ctx2.rsp.u32);
588# endif
589
590 /* Different rings (load SS0:SP0 from TSS). */
591 bs3CpuBasic2_TssGateEsp_AltStackOuterRing(&Ctx, 1, pbAltStack, cbAltStack,
592 f16BitSys, f16BitSys, f16BitSys, pszMode, __LINE__);
593 bs3CpuBasic2_TssGateEsp_AltStackOuterRing(&Ctx, 2, pbAltStack, cbAltStack,
594 f16BitSys, f16BitSys, f16BitSys, pszMode, __LINE__);
595 bs3CpuBasic2_TssGateEsp_AltStackOuterRing(&Ctx, 3, pbAltStack, cbAltStack,
596 f16BitSys, f16BitSys, f16BitSys, pszMode, __LINE__);
597
598 /* Different rings but switch the SS bitness in the TSS. */
599 if (f16BitSys)
600 {
601 Bs3Tss16.ss0 = BS3_SEL_R0_SS32;
602 bs3CpuBasic2_TssGateEsp_AltStackOuterRing(&Ctx, 1, pbAltStack, cbAltStack,
603 false, f16BitSys, f16BitSys, pszMode, __LINE__);
604 Bs3Tss16.ss0 = BS3_SEL_R0_SS16;
605 }
606 else
607 {
608 Bs3Tss32.ss0 = BS3_SEL_R0_SS16;
609 bs3CpuBasic2_TssGateEsp_AltStackOuterRing(&Ctx, 1, pbAltStack, cbAltStack,
610 true, f16BitSys, f16BitSys, pszMode, __LINE__);
611 Bs3Tss32.ss0 = BS3_SEL_R0_SS32;
612 }
613
614 Bs3MemFree(pbAltStack, cbAltStack);
615 }
616 else
617 Bs3TestPrintf("%s: Skipping ESP check, alloc failed\n", pszMode);
618 }
619 else
620 Bs3TestPrintf("%s: Skipping ESP check, CPU too old\n", pszMode);
621}
622
623#endif
624
625
626BS3_DECL(uint8_t) TMPL_NM(bs3CpuBasic2_TssGateEsp)(uint8_t bMode)
627{
628 uint8_t bRet = 0;
629
630#if TMPL_MODE == BS3_MODE_PE16 \
631 || TMPL_MODE == BS3_MODE_PE16_32 \
632 || TMPL_MODE == BS3_MODE_PP16 \
633 || TMPL_MODE == BS3_MODE_PP16_32 \
634 || TMPL_MODE == BS3_MODE_PAE16 \
635 || TMPL_MODE == BS3_MODE_PAE16_32 \
636 || TMPL_MODE == BS3_MODE_PE32
637 bs3CpuBasic2_TssGateEspCommon(bMode,
638 BS3_DATA_NM(TMPL_NM(g_szBs3ModeName)),
639 BS3_MODE_IS_16BIT_SYS(TMPL_MODE),
640 (PX86DESC)MyBs3Idt,
641 BS3_MODE_IS_64BIT_SYS(TMPL_MODE) ? 1 : 0);
642#else
643 bRet = BS3TESTDOMODE_SKIPPED;
644#endif
645
646 /*
647 * Re-initialize the IDT.
648 */
649 TMPL_NM(Bs3TrapInit)();
650 return bRet;
651}
652
653
654BS3_DECL(uint8_t) TMPL_NM(bs3CpuBasic2_RaiseXcpt1)(uint8_t bMode)
655{
656 uint8_t bRet = 0;
657
658 /*
659 * Pass to common worker which is only compiled once per mode.
660 */
661#if !BS3_MODE_IS_RM_OR_V86(TMPL_MODE)
662 bs3CpuBasic2_RaiseXcpt1Common(bMode,
663 BS3_DATA_NM(TMPL_NM(g_szBs3ModeName)),
664 BS3_MODE_IS_16BIT_SYS(TMPL_MODE),
665 MY_SYS_SEL_R0_CS,
666 MY_SYS_SEL_R0_CS_CNF,
667 (PX86DESC)MyBs3Idt,
668 BS3_MODE_IS_64BIT_SYS(TMPL_MODE) ? 1 : 0);
669#else
670 bRet = BS3TESTDOMODE_SKIPPED;
671#endif
672
673 /*
674 * Re-initialize the IDT.
675 */
676 TMPL_NM(Bs3TrapInit)();
677 return bRet;
678}
679
680
681
682
683BS3_DECL(uint8_t) TMPL_NM(bs3CpuBasic2_iret)(uint8_t bMode)
684{
685 NOREF(bMode);
686 return BS3TESTDOMODE_SKIPPED;
687}
688
689
690#endif /* BS3_INSTANTIATING_MODE */
691
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette