VirtualBox

Changeset 72549 in vbox


Ignore:
Timestamp:
Jun 13, 2018 5:58:19 PM (7 years ago)
Author:
vboxsync
Message:

ValidationKit/rdtsc: Rewrote the rdtsc testcase to (hopefully) work with more than just 32-bit MSC. Need this to test TSC during pausing of NEM/win (bugref:9044).

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  
    5858cidet-app_VBOX_IMPORT_CHECKER.win.x86 = $(NO_SUCH_VARIABLE) # doesn't work on NT4 yet.
    5959
    60 #PROGRAMS += rdtsc
    61 #rdtsc_TEMPLATE = VBoxValidationKitR3
    62 #rdtsc_SOURCES  = rdtsc.cpp rdtsc-asm.asm
     60PROGRAMS += rdtsc
     61rdtsc_TEMPLATE = VBoxValidationKitR3
     62rdtsc_SOURCES  = rdtsc.cpp rdtsc-asm.asm
    6363
    6464
  • trunk/src/VBox/ValidationKit/utils/cpu/rdtsc.cpp

    r69111 r72549  
    2626
    2727
     28/*********************************************************************************************************************************
     29*   Header Files                                                                                                                 *
     30*********************************************************************************************************************************/
     31#include <iprt/types.h>
     32#include <stdlib.h>
    2833#include <stdio.h>
    29 
    30 int main()
     34#include <time.h>
     35
     36
     37/*********************************************************************************************************************************
     38*   Structures and Typedefs                                                                                                      *
     39*********************************************************************************************************************************/
     40typedef struct RDTSCRESULT
    3141{
    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*********************************************************************************************************************************/
     49extern "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 */
     64DECLASM(uint32_t) DoTscReads(void);
     65
     66
     67
     68
     69int 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++)
    3581    {
    36         int cMatchedNow = 0;
    37         __asm
     82        const char *psz = argv[i];
     83        if (*psz == '-')
    3884        {
    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            }
    68160        }
    69         if (cMatchedNow)
     161        else
    70162        {
    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;
    73165        }
    74166    }
    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;
    77287}
     288
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette