VirtualBox

source: vbox/trunk/src/VBox/VMM/testcase/tstVMMR0CallHost-1.cpp@ 96860

Last change on this file since 96860 was 96407, checked in by vboxsync, 22 months ago

scm copyright and license note update

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 5.7 KB
Line 
1/* $Id: tstVMMR0CallHost-1.cpp 96407 2022-08-22 17:43:14Z vboxsync $ */
2/** @file
3 * Testcase for the VMMR0JMPBUF operations.
4 */
5
6/*
7 * Copyright (C) 2006-2022 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 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#include <iprt/errcore.h>
33#include <VBox/param.h>
34#include <iprt/alloca.h>
35#include <iprt/initterm.h>
36#include <iprt/rand.h>
37#include <iprt/string.h>
38#include <iprt/stream.h>
39#include <iprt/test.h>
40
41#define IN_VMM_R0
42#define IN_RING0 /* pretent we're in Ring-0 to get the prototypes. */
43#include <VBox/vmm/vmm.h>
44#include "VMMInternal.h"
45
46
47/*********************************************************************************************************************************
48* Global Variables *
49*********************************************************************************************************************************/
50/** The jump buffer. */
51static VMMR0JMPBUF g_Jmp;
52/** The mirror jump buffer. */
53static VMMR0JMPBUF g_JmpMirror;
54/** The number of jumps we've done. */
55static unsigned volatile g_cJmps;
56/** Number of bytes allocated last time we called foo(). */
57static size_t volatile g_cbFoo;
58/** Number of bytes used last time we called foo(). */
59static intptr_t volatile g_cbFooUsed;
60/** Set if we're in a long jump. */
61static bool g_fInLongJmp;
62
63
64int foo(int i, int iZero, int iMinusOne)
65{
66 NOREF(iZero);
67
68 /* allocate a buffer which we fill up to the end. */
69 size_t cb = (i % 1555) + 32;
70 g_cbFoo = cb;
71 char *pv = (char *)alloca(cb);
72 RTStrPrintf(pv, cb, "i=%d%*s\n", i, cb, "");
73#if defined(RT_ARCH_AMD64)
74 g_cbFooUsed = (uintptr_t)g_Jmp.rsp - (uintptr_t)pv;
75 RTTESTI_CHECK_MSG_RET(g_cbFooUsed < VMM_STACK_SIZE - 128, ("%p - %p -> %#x; cb=%#x i=%d\n", g_Jmp.rsp, pv, g_cbFooUsed, cb, i), -15);
76#elif defined(RT_ARCH_X86)
77 g_cbFooUsed = (uintptr_t)g_Jmp.esp - (uintptr_t)pv;
78 RTTESTI_CHECK_MSG_RET(g_cbFooUsed < (intptr_t)VMM_STACK_SIZE - 128, ("%p - %p -> %#x; cb=%#x i=%d\n", g_Jmp.esp, pv, g_cbFooUsed, cb, i), -15);
79#endif
80
81 /* Twice in a row, every 7th time. */
82 if ((i % 7) <= 1)
83 {
84 g_cJmps++;
85 g_fInLongJmp = true;
86 int rc = vmmR0CallRing3LongJmp(&g_Jmp, 42);
87 g_fInLongJmp = false;
88 if (!rc)
89 return i + 10000;
90 return -1;
91 }
92 NOREF(iMinusOne);
93 return i;
94}
95
96
97DECLCALLBACK(int) tst2(intptr_t i, intptr_t i2)
98{
99 RTTESTI_CHECK_MSG_RET(i >= 0 && i <= 8192, ("i=%d is out of range [0..8192]\n", i), 1);
100 RTTESTI_CHECK_MSG_RET(i2 == 0, ("i2=%d is out of range [0]\n", i2), 1);
101 int iExpect = (i % 7) <= 1 ? i + 10000 : i;
102 int rc = foo(i, 0, -1);
103 RTTESTI_CHECK_MSG_RET(rc == iExpect, ("i=%d rc=%d expected=%d\n", i, rc, iExpect), 1);
104 return 0;
105}
106
107
108DECLCALLBACK(DECL_NO_INLINE(RT_NOTHING, int)) stackRandom(PVMMR0JMPBUF pJmpBuf, PFNVMMR0SETJMP pfn, PVM pVM, PVMCPU pVCpu)
109{
110#ifdef RT_ARCH_AMD64
111 uint32_t cbRand = RTRandU32Ex(1, 96);
112#else
113 uint32_t cbRand = 1;
114#endif
115 uint8_t volatile *pabFuzz = (uint8_t volatile *)alloca(cbRand);
116 memset((void *)pabFuzz, 0xfa, cbRand);
117 int rc = vmmR0CallRing3SetJmp(pJmpBuf, pfn, pVM, pVCpu);
118 memset((void *)pabFuzz, 0xaf, cbRand);
119 return rc;
120}
121
122
123void tst(int iFrom, int iTo, int iInc)
124{
125 RT_BZERO(&g_Jmp, RT_UOFFSETOF(VMMR0JMPBUF, cbStackBuf));
126 g_Jmp.cbStackValid = _1M;
127 memset((void *)g_Jmp.pvStackBuf, '\0', g_Jmp.cbStackBuf);
128 g_cbFoo = 0;
129 g_cJmps = 0;
130 g_cbFooUsed = 0;
131 g_fInLongJmp = false;
132
133 for (int i = iFrom, iItr = 0; i != iTo; i += iInc, iItr++)
134 {
135 g_fInLongJmp = false;
136 int rc = stackRandom(&g_Jmp, (PFNVMMR0SETJMP)(uintptr_t)tst2, (PVM)(uintptr_t)i, 0);
137 RTTESTI_CHECK_MSG_RETV(rc == (g_fInLongJmp ? 42 : 0),
138 ("i=%d rc=%d setjmp; cbFoo=%#x cbFooUsed=%#x fInLongJmp=%d\n",
139 i, rc, g_cbFoo, g_cbFooUsed, g_fInLongJmp));
140
141 }
142 RTTESTI_CHECK_MSG_RETV(g_cJmps, ("No jumps!"));
143}
144
145
146int main()
147{
148 /*
149 * Init.
150 */
151 RTTEST hTest;
152 RTEXITCODE rcExit = RTTestInitAndCreate("tstVMMR0CallHost-1", &hTest);
153 if (rcExit != RTEXITCODE_SUCCESS)
154 return rcExit;
155 RTTestBanner(hTest);
156
157 g_Jmp.cbStackBuf = HOST_PAGE_SIZE;
158 g_Jmp.pvStackBuf = (uintptr_t)RTTestGuardedAllocTail(hTest, g_Jmp.cbStackBuf);
159 g_Jmp.pMirrorBuf = (uintptr_t)&g_JmpMirror;
160
161 /*
162 * Run two test with about 1000 long jumps each.
163 */
164 RTTestSub(hTest, "Increasing stack usage");
165 tst(0, 7000, 1);
166 RTTestSub(hTest, "Decreasing stack usage");
167 tst(7599, 0, -1);
168
169 return RTTestSummaryAndDestroy(hTest);
170}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use