VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/Support/testcase/tstSupTscDelta.cpp

Last change on this file was 106061, checked in by vboxsync, 8 weeks ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.1 KB
Line 
1/* $Id: tstSupTscDelta.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * SUP Testcase - Global Info Page TSC Delta Measurement Utility.
4 */
5
6/*
7 * Copyright (C) 2015-2024 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 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#include <VBox/sup.h>
42#include <iprt/errcore.h>
43#include <iprt/assert.h>
44#include <iprt/stream.h>
45#include <iprt/string.h>
46#include <iprt/getopt.h>
47#include <iprt/test.h>
48#include <iprt/thread.h>
49
50
51
52int main(int argc, char **argv)
53{
54 RTTEST hTest;
55 RTEXITCODE rcExit = RTTestInitExAndCreate(argc, &argv, 0 /*fRtInit*/, "tstSupTscDelta", &hTest);
56 if (rcExit != RTEXITCODE_SUCCESS)
57 return rcExit;
58
59 /*
60 * Parse args
61 */
62 static const RTGETOPTDEF g_aOptions[] =
63 {
64 { "--iterations", 'i', RTGETOPT_REQ_INT32 },
65 { "--delay", 'd', RTGETOPT_REQ_INT32 },
66 };
67
68 uint32_t cIterations = 0; /* Currently 0 so that it doesn't upset testing. */
69 uint32_t cMsSleepBetweenIterations = 10;
70
71 int ch;
72 RTGETOPTUNION ValueUnion;
73 RTGETOPTSTATE GetState;
74 RTGetOptInit(&GetState, argc, argv, g_aOptions, RT_ELEMENTS(g_aOptions), 1, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
75 while ((ch = RTGetOpt(&GetState, &ValueUnion)))
76 {
77 switch (ch)
78 {
79 case 'd':
80 cMsSleepBetweenIterations = ValueUnion.u32;
81 break;
82 case 'i':
83 cIterations = ValueUnion.u32;
84 break;
85
86 default:
87 return RTGetOptPrintError(ch, &ValueUnion);
88 }
89 }
90 if (!cIterations)
91 return RTTestSkipAndDestroy(hTest, "Nothing to do. The --iterations argument is 0 or not given.");
92
93 /*
94 * Init
95 */
96 PSUPDRVSESSION pSession = NIL_RTR0PTR;
97 int rc = SUPR3Init(&pSession);
98 if (RT_SUCCESS(rc))
99 {
100 PSUPGLOBALINFOPAGE pGip = g_pSUPGlobalInfoPage;
101 if (pGip)
102 {
103 if (pGip->enmUseTscDelta < SUPGIPUSETSCDELTA_PRACTICALLY_ZERO)
104 return RTTestSkipAndDestroy(hTest, "No deltas to play with: enmUseTscDelta=%d\n", pGip->enmUseTscDelta);
105
106 /*
107 * Init stats.
108 */
109 struct
110 {
111 int64_t iLowest;
112 int64_t iHighest;
113 int64_t iTotal;
114 uint64_t uAbsMin;
115 uint64_t uAbsMax;
116 uint64_t uAbsTotal;
117 } aCpuStats[RTCPUSET_MAX_CPUS];
118 RT_ZERO(aCpuStats);
119 for (uint32_t i = 0; i < pGip->cCpus; i++)
120 {
121 aCpuStats[i].iLowest = INT64_MAX;
122 aCpuStats[i].iHighest = INT64_MIN;
123 aCpuStats[i].uAbsMin = UINT64_MAX;
124 }
125
126 /*
127 * Do the work.
128 */
129 for (uint32_t iIteration = 0; ; iIteration++)
130 {
131 /*
132 * Display the current deltas and gather statistics.
133 */
134 RTPrintf("tstSupTscDelta: Iteration #%u results:", iIteration);
135 for (uint32_t iCpu = 0; iCpu < pGip->cCpus; iCpu++)
136 {
137 int64_t iTscDelta = pGip->aCPUs[iCpu].i64TSCDelta;
138
139 /* print */
140 if ((iCpu % 4) == 0)
141 RTPrintf("\ntstSupTscDelta:");
142 if (pGip->aCPUs[iCpu].enmState != SUPGIPCPUSTATE_ONLINE)
143 RTPrintf(" %02x: offline ", iCpu);
144 else if (iTscDelta != INT64_MAX)
145 RTPrintf(" %02x: %-12lld", iCpu, iTscDelta);
146 else
147 RTPrintf(" %02x: INT64_MAX ", iCpu);
148
149 /* stats */
150 if ( iTscDelta != INT64_MAX
151 && pGip->aCPUs[iCpu].enmState == SUPGIPCPUSTATE_ONLINE)
152 {
153 if (aCpuStats[iCpu].iLowest > iTscDelta)
154 aCpuStats[iCpu].iLowest = iTscDelta;
155 if (aCpuStats[iCpu].iHighest < iTscDelta)
156 aCpuStats[iCpu].iHighest = iTscDelta;
157 aCpuStats[iCpu].iTotal += iTscDelta;
158
159 uint64_t uAbsTscDelta = iTscDelta >= 0 ? (uint64_t)iTscDelta : (uint64_t)-iTscDelta;
160 if (aCpuStats[iCpu].uAbsMin > uAbsTscDelta)
161 aCpuStats[iCpu].uAbsMin = uAbsTscDelta;
162 if (aCpuStats[iCpu].uAbsMax < uAbsTscDelta)
163 aCpuStats[iCpu].uAbsMax = uAbsTscDelta;
164 aCpuStats[iCpu].uAbsTotal += uAbsTscDelta;
165 }
166 }
167 if (((pGip->cCpus - 1) % 4) != 0)
168 RTPrintf("\n");
169
170 /*
171 * Done?
172 */
173 if (iIteration + 1 >= cIterations)
174 break;
175
176 /*
177 * Force a new measurement.
178 */
179 RTThreadSleep(cMsSleepBetweenIterations);
180 for (uint32_t iCpu = 0; iCpu < pGip->cCpus; iCpu++)
181 if (pGip->aCPUs[iCpu].enmState == SUPGIPCPUSTATE_ONLINE)
182 {
183 rc = SUPR3TscDeltaMeasure(pGip->aCPUs[iCpu].idCpu, false /*fAsync*/, true /*fForce*/, 64, 16 /*ms*/);
184 if (RT_FAILURE(rc))
185 RTTestFailed(hTest, "SUPR3TscDeltaMeasure failed on %#x: %Rrc", pGip->aCPUs[iCpu].idCpu, rc);
186 }
187 }
188
189 /*
190 * Display statistics that we've gathered.
191 */
192 RTPrintf("tstSupTscDelta: Results:\n");
193 int64_t iLowest = INT64_MAX;
194 int64_t iHighest = INT64_MIN;
195 int64_t iTotal = 0;
196 uint32_t cTotal = 0;
197 for (uint32_t iCpu = 0; iCpu < pGip->cCpus; iCpu++)
198 {
199 if (pGip->aCPUs[iCpu].enmState != SUPGIPCPUSTATE_ONLINE)
200 RTPrintf("tstSupTscDelta: %02x: offline\n", iCpu);
201 else
202 {
203 RTPrintf("tstSupTscDelta: %02x: lowest=%-12lld highest=%-12lld average=%-12lld spread=%-12lld\n",
204 iCpu,
205 aCpuStats[iCpu].iLowest,
206 aCpuStats[iCpu].iHighest,
207 aCpuStats[iCpu].iTotal / cIterations,
208 aCpuStats[iCpu].iHighest - aCpuStats[iCpu].iLowest);
209 RTPrintf( "tstSupTscDelta: absmin=%-12llu absmax=%-12llu absavg=%-12llu idCpu=%#4x idApic=%#4x\n",
210 aCpuStats[iCpu].uAbsMin,
211 aCpuStats[iCpu].uAbsMax,
212 aCpuStats[iCpu].uAbsTotal / cIterations,
213 pGip->aCPUs[iCpu].idCpu,
214 pGip->aCPUs[iCpu].idApic);
215 if (iLowest > aCpuStats[iCpu].iLowest)
216 iLowest = aCpuStats[iCpu].iLowest;
217 if (iHighest < aCpuStats[iCpu].iHighest)
218 iHighest = aCpuStats[iCpu].iHighest;
219 iTotal += aCpuStats[iCpu].iHighest;
220 cTotal += cIterations;
221 }
222 }
223 RTPrintf("tstSupTscDelta: all: lowest=%-12lld highest=%-12lld average=%-12lld spread=%-12lld\n",
224 iLowest, iHighest, iTotal / cTotal, iHighest - iLowest);
225 }
226 else
227 RTTestFailed(hTest, "g_pSUPGlobalInfoPage is NULL");
228
229 SUPR3Term(false /*fForced*/);
230 }
231 else
232 RTTestFailed(hTest, "SUPR3Init failed: %Rrc", rc);
233 return RTTestSummaryAndDestroy(hTest);
234}
235
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