VirtualBox

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

Last change on this file since 92780 was 92408, checked in by vboxsync, 3 years ago

VMM: Reworked most of the call-ring-3 stuff into setjmp-longjmp-on-assert and removed the stack switching/copying/resume code. bugref:10093 bugref:10124

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