Changeset 72549 in vbox
- Timestamp:
- Jun 13, 2018 5:58:19 PM (7 years ago)
- Location:
- trunk/src/VBox/ValidationKit/utils/cpu
- Files:
-
- 1 added
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/ValidationKit/utils/cpu/Makefile.kmk
r70377 r72549 58 58 cidet-app_VBOX_IMPORT_CHECKER.win.x86 = $(NO_SUCH_VARIABLE) # doesn't work on NT4 yet. 59 59 60 #PROGRAMS += rdtsc61 #rdtsc_TEMPLATE = VBoxValidationKitR362 #rdtsc_SOURCES = rdtsc.cpp rdtsc-asm.asm60 PROGRAMS += rdtsc 61 rdtsc_TEMPLATE = VBoxValidationKitR3 62 rdtsc_SOURCES = rdtsc.cpp rdtsc-asm.asm 63 63 64 64 -
trunk/src/VBox/ValidationKit/utils/cpu/rdtsc.cpp
r69111 r72549 26 26 27 27 28 /********************************************************************************************************************************* 29 * Header Files * 30 *********************************************************************************************************************************/ 31 #include <iprt/types.h> 32 #include <stdlib.h> 28 33 #include <stdio.h> 29 30 int main() 34 #include <time.h> 35 36 37 /********************************************************************************************************************************* 38 * Structures and Typedefs * 39 *********************************************************************************************************************************/ 40 typedef struct RDTSCRESULT 31 41 { 32 int i; 33 int cMatches = 0; 34 for (i = 0; i < 10000000; i++) 42 RTCCUINTREG uLow, uHigh; 43 } RDTSCRESULT; 44 45 46 /********************************************************************************************************************************* 47 * Global Variables * 48 *********************************************************************************************************************************/ 49 extern "C" RDTSCRESULT g_aRdTscResults[]; /* rdtsc-asm.asm */ 50 51 52 /********************************************************************************************************************************* 53 * Internal Functions * 54 *********************************************************************************************************************************/ 55 /** 56 * Does 3 (32-bit) or 6 (64-bit) fast TSC reads and stores the result 57 * in g_aRdTscResults, starting with the 2nd entry. 58 * 59 * Starting the result storing at g_aRdTscResults[1] make it easy to do the 60 * comparisons in a loop. 61 * 62 * @returns Number of results read into g_aRdTscResults[1] and onwards. 63 */ 64 DECLASM(uint32_t) DoTscReads(void); 65 66 67 68 69 int main(int argc, char **argv) 70 { 71 72 /* 73 * Tunables. 74 */ 75 uint64_t offJumpThreshold = _4G * 2; 76 unsigned cMaxLoops = 10000000; 77 unsigned cStatusEvery = 2000000; 78 unsigned cMinSeconds = 0; 79 80 for (int i = 1; i < argc; i++) 35 81 { 36 int cMatchedNow = 0;37 __asm82 const char *psz = argv[i]; 83 if (*psz == '-') 38 84 { 39 rdtsc 40 mov ebx, eax 41 mov ecx, edx 42 rdtsc 43 mov esi, eax 44 mov edi, edx 45 rdtsc 46 47 cmp eax, ebx 48 jnz l_ok1 49 cmp edx, ecx 50 jnz l_ok1 51 inc [cMatchedNow] 52 l_ok1: 53 54 cmp eax, esi 55 jnz l_ok2 56 cmp edx, edi 57 jnz l_ok2 58 inc [cMatchedNow] 59 jmp l_ok3 60 l_ok2: 61 62 cmp ebx, esi 63 jnz l_ok3 64 cmp ecx, edi 65 jnz l_ok3 66 inc [cMatchedNow] 67 l_ok3: 85 psz++; 86 char chOpt; 87 while ((chOpt = *psz++) != '\0') 88 { 89 /* Option value. */ 90 const char *pszValue = NULL; 91 unsigned long uValue = 0; 92 switch (chOpt) 93 { 94 case 'l': 95 case 's': 96 case 'm': 97 if (*psz == '\0') 98 { 99 if (i + 1 >= argc) 100 { 101 printf("syntax error: The %c option requires a value\n", chOpt); 102 return RTEXITCODE_SYNTAX; 103 } 104 pszValue = argv[++i]; 105 } 106 else 107 pszValue = psz + (*psz == ':' || *psz == '='); 108 switch (chOpt) 109 { 110 case 'l': 111 case 's': 112 case 'm': 113 { 114 char *pszNext = NULL; 115 uValue = strtoul(pszValue, &pszNext, 0); 116 if (pszNext && *pszNext != '\0') 117 if (*pszNext == 'M'&& pszNext[1] == '\0') 118 uValue *= _1M; 119 else if (*pszNext == 'K' && pszNext[1] == '\0') 120 uValue *= _1K; 121 else if (*pszNext == 'G' && pszNext[1] == '\0') 122 uValue *= _1G; 123 else 124 { 125 printf("syntax error: Bad value format for option %c: %s\n", chOpt, pszValue); 126 return RTEXITCODE_SYNTAX; 127 } 128 break; 129 } 130 } 131 break; 132 } 133 134 /* handle the option. */ 135 switch (chOpt) 136 { 137 case 'l': 138 cMaxLoops = uValue; 139 break; 140 141 case 'm': 142 cMinSeconds = uValue; 143 break; 144 145 case 's': 146 cStatusEvery = uValue; 147 break; 148 149 case 'h': 150 case '?': 151 printf("usage: rdtsc [-l <loops>] [-s <loops-between-status>]\n" 152 " [-m <minimum-seconds-to-run>]\n"); 153 return RTEXITCODE_SUCCESS; 154 155 default: 156 printf("syntax error: Unknown option %c (argument %d)\n", chOpt, i); 157 return RTEXITCODE_SYNTAX; 158 } 159 } 68 160 } 69 if (cMatchedNow)161 else 70 162 { 71 printf(" %08d: %d\n", i, cMatchedNow);72 cMatches += cMatchedNow;163 printf("synatx error: argument %d (%s): not an option\n", i, psz); 164 return RTEXITCODE_SYNTAX; 73 165 } 74 166 } 75 printf("done: %d matches\n", cMatches); 76 return !!cMatches; 167 168 /* 169 * Do the job. 170 */ 171 time_t uSecStart; 172 time(&uSecStart); 173 unsigned cOuterLoops = 0; 174 unsigned cLoopsToNextStatus = cStatusEvery; 175 unsigned cRdTscInstructions = 0; 176 unsigned cBackwards = 0; 177 unsigned cSame = 0; 178 unsigned cBadValues = 0; 179 unsigned cJumps = 0; 180 uint64_t offMaxJump = 0; 181 uint64_t offMinIncr = UINT64_MAX; 182 uint64_t offMaxIncr = 0; 183 184 g_aRdTscResults[0] = g_aRdTscResults[DoTscReads() - 1]; 185 186 for (;;) 187 { 188 for (unsigned iLoop = 0; iLoop < cMaxLoops; iLoop++) 189 { 190 uint32_t const cResults = DoTscReads(); 191 cRdTscInstructions += cResults; 192 193 for (uint32_t i = 0; i < cResults; i++) 194 { 195 uint64_t uPrev = RT_MAKE_U64((uint32_t)g_aRdTscResults[i ].uLow, (uint32_t)g_aRdTscResults[i ].uHigh); 196 uint64_t uCur = RT_MAKE_U64((uint32_t)g_aRdTscResults[i + 1].uLow, (uint32_t)g_aRdTscResults[i + 1].uHigh); 197 if (RT_LIKELY(uCur != uPrev)) 198 { 199 int64_t offDelta = uCur - uPrev; 200 if (RT_LIKELY(offDelta >= 0)) 201 { 202 if (RT_LIKELY((uint64_t)offDelta < offJumpThreshold)) 203 { 204 if ((uint64_t)offDelta < offMinIncr) 205 offMinIncr = offDelta; 206 if ((uint64_t)offDelta > offMaxIncr && i != 0) 207 offMaxIncr = offDelta; 208 } 209 else 210 { 211 cJumps++; 212 if ((uint64_t)offDelta > offMaxJump) 213 offMaxJump = offDelta; 214 printf("%u/%u: Jump: %#010x`%08x -> %#010x`%08x\n", cOuterLoops, iLoop, 215 (unsigned)g_aRdTscResults[i].uHigh, (unsigned)g_aRdTscResults[i].uLow, 216 (unsigned)g_aRdTscResults[i + 1].uHigh, (unsigned)g_aRdTscResults[i + 1].uLow); 217 } 218 } 219 else 220 { 221 cBackwards++; 222 printf("%u/%u: Back: %#010x`%08x -> %#010x`%08x\n", cOuterLoops, iLoop, 223 (unsigned)g_aRdTscResults[i].uHigh, (unsigned)g_aRdTscResults[i].uLow, 224 (unsigned)g_aRdTscResults[i + 1].uHigh, (unsigned)g_aRdTscResults[i + 1].uLow); 225 } 226 } 227 else 228 { 229 cSame++; 230 printf("%u/%u: Same: %#010x`%08x -> %#010x`%08x\n", cOuterLoops, iLoop, 231 (unsigned)g_aRdTscResults[i].uHigh, (unsigned)g_aRdTscResults[i].uLow, 232 (unsigned)g_aRdTscResults[i + 1].uHigh, (unsigned)g_aRdTscResults[i + 1].uLow); 233 } 234 #if ARCH_BITS == 64 235 if ((g_aRdTscResults[i + 1].uLow >> 32) || (g_aRdTscResults[i + 1].uHigh >> 32)) 236 cBadValues++; 237 #endif 238 } 239 240 /* Copy the last value for the next iteration. */ 241 g_aRdTscResults[0] = g_aRdTscResults[cResults]; 242 243 /* Display status. */ 244 if (RT_LIKELY(--cLoopsToNextStatus > 0)) 245 { /* likely */ } 246 else 247 { 248 cLoopsToNextStatus = cStatusEvery; 249 printf("%u/%u: %#010x`%08x\n", cOuterLoops, iLoop, 250 (unsigned)g_aRdTscResults[cResults].uHigh, (unsigned)g_aRdTscResults[cResults].uLow); 251 } 252 } 253 254 /* 255 * Check minimum number of seconds. 256 */ 257 cOuterLoops++; 258 if (!cMinSeconds) 259 break; 260 time_t uSecNow; 261 if ( time(&uSecNow) == -1 262 || cMinSeconds == -1 263 || uSecNow - uSecStart >= cMinSeconds) 264 break; 265 } 266 267 /* 268 * Summary. 269 */ 270 if (cBackwards == 0 && cSame == 0 && cJumps == 0 && cBadValues == 0) 271 { 272 printf("rdtsc: Success (%u RDTSC over %u*%u loops, deltas: %#x`%08x..%#x`%08x)\n", 273 cRdTscInstructions, cOuterLoops, cMaxLoops, 274 (unsigned)(offMinIncr >> 32), (unsigned)offMinIncr, (unsigned)(offMaxIncr >> 32), (unsigned)offMaxIncr); 275 return RTEXITCODE_SUCCESS; 276 } 277 printf("RDTSC instructions: %u\n", cRdTscInstructions); 278 printf("Loops: %u * %u => %u\n", cMaxLoops, cOuterLoops, cOuterLoops * cMaxLoops); 279 printf("Backwards: %u\n", cBackwards); 280 printf("Jumps: %u\n", cJumps); 281 printf("Max jumps: %#010x`%08x\n", (unsigned)(offMaxJump >> 32), (unsigned)offMaxJump); 282 printf("Same value: %u\n", cSame); 283 printf("Bad values: %u\n", cBadValues); 284 printf("Min increment: %#010x`%08x\n", (unsigned)(offMinIncr >> 32), (unsigned)offMinIncr); 285 printf("Max increment: %#010x`%08x\n", (unsigned)(offMaxIncr >> 32), (unsigned)offMaxIncr); 286 return RTEXITCODE_FAILURE; 77 287 } 288
Note:
See TracChangeset
for help on using the changeset viewer.