VirtualBox

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

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

bs3-cpu-basic-2: Extending the first test to 32-bit system.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.2 KB
Line 
1/* $Id: bs3-cpu-basic-2-template.c 60132 2016-03-22 09:32:04Z 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
35
36/*********************************************************************************************************************************
37* Internal Functions *
38*********************************************************************************************************************************/
39extern BS3_DECL(void) TMPL_NM(bs3CpuBasic2_TssGateEsp_IntXx)(void);
40
41
42# if TMPL_MODE == BS3_MODE_PE16 \
43 || TMPL_MODE == BS3_MODE_PE16_32
44
45/**
46 * Compares trap stuff.
47 */
48static void bs3CpuBasic2_CompareTrapCtx1(PCBS3TRAPFRAME pTrapCtx, PCBS3REGCTX pStartCtx, uint16_t cbIpAdjust, uint8_t bXcpt,
49 const char *pszMode, unsigned uLine)
50{
51 uint16_t cErrorsBefore = Bs3TestSubErrorCount();
52
53#define CHECK_MEMBER(a_szName, a_szFmt, a_Actual, a_Expected) \
54 do \
55 { \
56 if ((a_Actual) == (a_Expected)) { /* likely */ } \
57 else Bs3TestFailedF("%u - %s: " a_szName "=" a_szFmt " expected " a_szFmt, uLine, pszMode, (a_Actual), (a_Expected)); \
58 } while (0)
59
60 CHECK_MEMBER("bXcpt", "%#04x", pTrapCtx->bXcpt, bXcpt);
61 Bs3TestCheckRegCtxEx(&pTrapCtx->Ctx, pStartCtx, cbIpAdjust, 0 /*cbSpAdjust*/, pszMode, uLine);
62 if (Bs3TestSubErrorCount() != cErrorsBefore)
63 Bs3TrapPrintFrame(pTrapCtx);
64}
65
66
67/**
68 * Worker for bs3CpuBasic2_TssGateEsp that tests the INT 80 from outer rings.
69 */
70static void bs3CpuBasic2_TssGateEsp_AltStackOuterRing(PCBS3REGCTX pCtx, uint8_t bRing, uint8_t *pbAltStack, size_t cbAltStack,
71 bool f16BitStack, bool f16BitTss, const char *pszMode, unsigned uLine)
72{
73 BS3REGCTX Ctx2;
74 BS3TRAPFRAME TrapCtx;
75 uint8_t *pbTmp;
76
77 Bs3MemCpy(&Ctx2, pCtx, sizeof(Ctx2));
78 Bs3RegCtxConvertToRingX(&Ctx2, bRing);
79
80 if (pbAltStack)
81 {
82 Ctx2.rsp.u = Bs3SelPtrToFlat(pbAltStack + 0x1980);
83 Bs3MemZero(pbAltStack, cbAltStack);
84 }
85
86 Bs3TrapSetJmpAndRestore(&Ctx2, &TrapCtx);
87
88 if (!f16BitStack && f16BitTss)
89 Ctx2.rsp.u &= UINT16_MAX;
90
91 bs3CpuBasic2_CompareTrapCtx1(&TrapCtx, &Ctx2, 2 /*int 80h*/, 0x80 /*bXcpt*/, pszMode, uLine);
92 CHECK_MEMBER("bCpl", "%u", TrapCtx.Ctx.bCpl, bRing);
93
94 if (pbAltStack)
95 {
96 uint64_t uExpectedRsp = f16BitTss ? Bs3Tss16.sp0 : Bs3Tss32.esp0;
97 if (f16BitStack)
98 {
99 uExpectedRsp &= UINT16_MAX;
100 uExpectedRsp |= Ctx2.rsp.u & ~(uint64_t)UINT16_MAX;
101 }
102 if ( TrapCtx.uHandlerRsp != uExpectedRsp
103 || TrapCtx.uHandlerSs != (f16BitTss ? Bs3Tss16.ss0 : Bs3Tss32.ss0))
104 Bs3TestFailedF("%u - %s: handler SS:ESP=%04x:%08RX64, expected %04x:%08RX16\n", uLine, pszMode,
105 TrapCtx.uHandlerSs, TrapCtx.uHandlerRsp, Bs3Tss16.ss0, uExpectedRsp);
106
107 pbTmp = (uint8_t *)ASMMemFirstNonZero(pbAltStack, cbAltStack);
108 if ((f16BitStack || TrapCtx.uHandlerRsp <= UINT16_MAX) && pbTmp != NULL)
109 Bs3TestFailedF("%u - %s: someone touched the alt stack (%p) with SS:ESP=%04x:%#RX32: %p=%02x\n", uLine, pszMode,
110 pbAltStack, Ctx2.ss, Ctx2.rsp.u32, pbTmp, *pbTmp);
111 else if (!f16BitStack && TrapCtx.uHandlerRsp > UINT16_MAX && pbTmp == NULL)
112 Bs3TestFailedF("%u - %s: the alt stack (%p) was not used SS:ESP=%04x:%#RX32\n", uLine, pszMode,
113 pbAltStack, Ctx2.ss, Ctx2.rsp.u32);
114 }
115}
116
117#endif
118
119
120BS3_DECL(uint8_t) TMPL_NM(bs3CpuBasic2_TssGateEsp)(uint8_t bMode)
121{
122 uint8_t bRet = 0;
123 BS3TRAPFRAME TrapCtx;
124 BS3REGCTX Ctx, Ctx2;
125 uint8_t *pbTmp;
126 unsigned uLine;
127 const char *pszMode = BS3_DATA_NM(TMPL_NM(g_szBs3ModeName));
128
129 pbTmp = NULL; NOREF(pbTmp); uLine = 0; NOREF(uLine); NOREF(pszMode);
130
131 /* make sure they're allocated */
132 Bs3MemZero(&Ctx, sizeof(Ctx));
133 Bs3MemZero(&Ctx2, sizeof(Ctx2));
134 Bs3MemZero(&TrapCtx, sizeof(TrapCtx));
135
136#if TMPL_MODE == BS3_MODE_PE16 \
137 || TMPL_MODE == BS3_MODE_PE16_32 \
138 || TMPL_MODE == BS3_MODE_PP16 \
139 || TMPL_MODE == BS3_MODE_PP16_32 \
140 || TMPL_MODE == BS3_MODE_PAE16 \
141 || TMPL_MODE == BS3_MODE_PAE16_32 \
142 || TMPL_MODE == BS3_MODE_PE32
143
144 Bs3RegCtxSave(&Ctx);
145 Ctx.rsp.u -= 0x80;
146 Ctx.rip.u = (uintptr_t)BS3_FP_OFF(&TMPL_NM(bs3CpuBasic2_TssGateEsp_IntXx));
147# if TMPL_BITS == 32
148 BS3_DATA_NM(g_uBs3TrapEipHint) = Ctx.rip.u32;
149# endif
150
151 /*
152 * We'll be using IDT entry 80 and 81 here. The first one will be
153 * accessible from all DPLs, the latter not. So, start with setting
154 * the DPLs.
155 */
156# if BS3_MODE_IS_16BIT_SYS(TMPL_MODE)
157 BS3_DATA_NM(Bs3Idt16)[0x80].Gate.u2Dpl = 3;
158 BS3_DATA_NM(Bs3Idt16)[0x81].Gate.u2Dpl = 0;
159# else
160 BS3_DATA_NM(Bs3Idt32)[0x80].Gate.u2Dpl = 3;
161 BS3_DATA_NM(Bs3Idt32)[0x81].Gate.u2Dpl = 0;
162# endif
163
164 /*
165 * Check that the basic stuff works first.
166 */
167 Bs3TrapSetJmpAndRestore(&Ctx, &TrapCtx);
168 bs3CpuBasic2_CompareTrapCtx1(&TrapCtx, &Ctx, 2 /*int 80h*/, 0x80 /*bXcpt*/, pszMode, __LINE__);
169
170 bs3CpuBasic2_TssGateEsp_AltStackOuterRing(&Ctx, 1, NULL, 0, BS3_MODE_IS_16BIT_SYS(TMPL_MODE),
171 BS3_MODE_IS_16BIT_SYS(TMPL_MODE), pszMode, __LINE__);
172 bs3CpuBasic2_TssGateEsp_AltStackOuterRing(&Ctx, 2, NULL, 0, BS3_MODE_IS_16BIT_SYS(TMPL_MODE),
173 BS3_MODE_IS_16BIT_SYS(TMPL_MODE), pszMode, __LINE__);
174 bs3CpuBasic2_TssGateEsp_AltStackOuterRing(&Ctx, 3, NULL, 0, BS3_MODE_IS_16BIT_SYS(TMPL_MODE),
175 BS3_MODE_IS_16BIT_SYS(TMPL_MODE), pszMode, __LINE__);
176
177 /*
178 * Check that the upper part of ESP is preserved when doing .
179 */
180 if ((BS3_DATA_NM(g_uBs3CpuDetected) & BS3CPU_TYPE_MASK) >= BS3CPU_80386)
181 {
182 size_t const cbAltStack = _8K;
183 uint8_t *pbAltStack = Bs3MemAllocZ(BS3MEMKIND_TILED, cbAltStack);
184 if (pbAltStack)
185 {
186 /* same ring */
187 uLine = __LINE__;
188 Bs3MemCpy(&Ctx2, &Ctx, sizeof(Ctx2));
189 Ctx2.rsp.u = Bs3SelPtrToFlat(pbAltStack + 0x1980);
190 if (Bs3TrapSetJmp(&TrapCtx))
191 Bs3RegCtxRestore(&Ctx2, 0); /* (does not return) */
192 bs3CpuBasic2_CompareTrapCtx1(&TrapCtx, &Ctx2, 2 /*int 80h*/, 0x80 /*bXcpt*/, pszMode, uLine);
193# if TMPL_BITS == 16
194 if ((pbTmp = (uint8_t *)ASMMemFirstNonZero(pbAltStack, cbAltStack)) != NULL)
195 Bs3TestFailedF("%u - %s: someone touched the alt stack (%p) with SS:ESP=%04x:%#RX32: %p=%02x\n",
196 uLine, pszMode, pbAltStack, Ctx2.ss, Ctx2.rsp.u32, pbTmp, *pbTmp);
197# else
198 if (ASMMemIsZero(pbAltStack, cbAltStack))
199 Bs3TestFailedF("%u - %s: alt stack wasn't used despite SS:ESP=%04x:%#RX32\n",
200 uLine, pszMode, Ctx2.ss, Ctx2.rsp.u32);
201# endif
202
203 /* Different rings (load SS0:SP0 from TSS). */
204 bs3CpuBasic2_TssGateEsp_AltStackOuterRing(&Ctx, 1, pbAltStack, cbAltStack, BS3_MODE_IS_16BIT_SYS(TMPL_MODE),
205 BS3_MODE_IS_16BIT_SYS(TMPL_MODE), pszMode, __LINE__);
206 bs3CpuBasic2_TssGateEsp_AltStackOuterRing(&Ctx, 2, pbAltStack, cbAltStack, BS3_MODE_IS_16BIT_SYS(TMPL_MODE),
207 BS3_MODE_IS_16BIT_SYS(TMPL_MODE), pszMode, __LINE__);
208 bs3CpuBasic2_TssGateEsp_AltStackOuterRing(&Ctx, 3, pbAltStack, cbAltStack, BS3_MODE_IS_16BIT_SYS(TMPL_MODE),
209 BS3_MODE_IS_16BIT_SYS(TMPL_MODE), pszMode, __LINE__);
210
211 /* Different rings but switch the SS bitness in the TSS. */
212# if TMPL_BITS == 16
213 Bs3Tss16.ss0 = BS3_SEL_R0_SS32;
214 bs3CpuBasic2_TssGateEsp_AltStackOuterRing(&Ctx, 1, pbAltStack, cbAltStack, false, true, pszMode, __LINE__);
215 Bs3Tss16.ss0 = BS3_SEL_R0_SS16;
216# else
217 Bs3Tss32.ss0 = BS3_SEL_R0_SS16;
218 bs3CpuBasic2_TssGateEsp_AltStackOuterRing(&Ctx, 1, pbAltStack, cbAltStack, true, false, pszMode, __LINE__);
219 Bs3Tss32.ss0 = BS3_SEL_R0_SS32;
220# endif
221
222 Bs3MemFree(pbAltStack, cbAltStack);
223 }
224 else
225 Bs3TestPrintf("%s: Skipping ESP check, alloc failed\n", pszMode);
226 }
227 else
228 Bs3TestPrintf("%s: Skipping ESP check, CPU too old\n", pszMode);
229
230#else
231 bRet = BS3TESTDOMODE_SKIPPED;
232#endif
233
234 /*
235 * Re-initialize the IDT.
236 */
237#if BS3_MODE_IS_16BIT_SYS(TMPL_MODE)
238 Bs3Trap16Init();
239#elif BS3_MODE_IS_32BIT_SYS(TMPL_MODE)
240 Bs3Trap32Init();
241#elif BS3_MODE_IS_32BIT_SYS(TMPL_MODE)
242 Bs3Trap64Init();
243#endif
244
245 return bRet;
246}
247
248
249BS3_DECL(uint8_t) TMPL_NM(bs3CpuBasic2_iret)(uint8_t bMode)
250{
251 NOREF(bMode);
252 return BS3TESTDOMODE_SKIPPED;
253}
254
255
256#endif /* BS3_INSTANTIATING_MODE */
257
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