VMware Cloud Community
TomaszSzreder
Contributor
Contributor

Timekeeping problem: can't read pseudoperformance counters with rdpmc

Hi,

I have recently become concerned about obtaining accurate (non-drifting) and precise (fine-grained) timestamps within a Windows guest VM running on ESXi 4.0. I felt like I need to read real time from host machine instead of apparent time, and it seems that accessing Pseudoperformance Counters described in the official Timekeeping in VMware VMs whitepaper should do the trick. I followed the instructions provided in the whitepaper, but I can’t get the rdpmc instruction to work.

I added the line “monitor_control.pseudo_perfctr = TRUE” to the .vmx config file, and then tried to assemble the following code using masm32, but I keep on getting the error “rdpmc-test.asm(35) : error A2085: instruction or register not accepted in current CPU mode” (this is the line with rdpmc invocation). I am using VMware ESXi 4.0, and the same problem occurs on Windows XP 32-bit as well as Windows 7 32-bit guest machines. What am I doing wrong?

(rdpmc-test.asm)

    include \masm32\include\masm32rt.inc

    .data?

      value dd ?

    .data

      item dd 0

    .code

start:

    call main

    inkey

    exit

main proc

    print "rdpmc-test",13,10

    pusha

    mov ecx,10001H

    rdpmc    

    ;print str$(eax),13,10

   popa

    ret

main endp

end start

(makeit.bat)

@echo off

    if exist "rdpmc-test.obj" del "rdpmc-test.obj"
    if exist "rdpmc-test.exe" del "rdpmc-test.exe"

    \masm32\bin\ml /c /coff "rdpmc-test.asm"
    if errorlevel 1 goto errasm

    \masm32\bin\PoLink /SUBSYSTEM:CONSOLE "rdpmc-test.obj"
    if errorlevel 1 goto errlink
    dir "rdpmc-test.*"
    goto TheEnd

  :errlink
    echo _
    echo Link error
    goto TheEnd

  :errasm
    echo _
    echo Assembly Error
    goto TheEnd
   
  :TheEnd

pause

(Error output)

Microsoft (R) Macro Assembler Version 6.14.8444
Copyright (C) Microsoft Corp 1981-1997.  All rights reserved.

Assembling: rdpmc-test.asm
rdpmc-test.asm(35) : error A2085: instruction or register not accepted in current CPU mode
_
Assembly Error

Press any key to continue . . .

Thanks

Tomasz Szreder

0 Kudos
1 Reply
TomaszSzreder
Contributor
Contributor

The problem reading VMware Pseudo-Performance Counters is gone: in order to obtain an accurate timestamp provided by one of the counters, you can use the following code:

unsigned int performanceCounterValueHighPart;
unsigned int performanceCounterValueLowPart;
__asm { /* Try to poll VMware Pseudo-Performance Counter #0x10001 ("real time in ns") */
mov performanceCounterValueHighPart, 0
mov performanceCounterValueLowPart, 0
CPUID            // Used for serialization
mov ecx, 0x10001 /* "Elapsed real time in ns":
* special pseudo-performance counter provided by VMware.
* Can only be used if the virtual machine
* has in .vmx configuration the following option:
* "monitor_control.pseudo_perfctr" = "TRUE"
* This allows to read timer count from the underlying host physical machine,
* effectively getting rid of the timekeeping problem.
* Read more at:
* http://www.vmware.com/files/pdf/Timekeeping-In-VirtualMachines.pdf
*/
RDPMC
mov performanceCounterValueHighPart, edx
mov performanceCounterValueLowPart, eax
}

The trick is to use either inline assembly (RDPMC) or compiler intrinsics (__readpmc()) and compile with Visual Studio rather than plain MASM32.

Hope this helps somebody.

Regards

Tomasz Szreder

0 Kudos