Sorry, i sent that before i had finished.
I am trying to find an equivalent of the following code for FreeBSD
size_t outsz = sizeof bi->cpu.tsc_freq;
int ret = sysctlbyname("machdep.tsc_freq", &bi->cpu.tsc_freq, &outsz, NULL,
0);
if (ret == -1)
err(1, "sysctl(machdep.tsc_freq)");
int invariant_tsc = 0;
outsz = sizeof invariant_tsc;
ret = sysctlbyname("kern.timecounter.invariant_tsc", &invariant_tsc, &outsz,
NULL, 0);
if (ret == -1)
err(1, "sysctl(kern.timecounter.invariant_tsc");
if (invariant_tsc != 1)
errx(1, "Host TSC is not invariant, cannot continue");
line 122-134 of
https://github.com/adamsteen/solo5/blob/master/ukvm/ukvm_hv_freebsd_x86_64.c
Currently the port fails with "vmx_handle_exit: unhandled exit
2147483681 (unknown)" (0x80000021 in hex), I am setting up the
registers to incorrect values, but need to read more to understand
what OpenBSD vmm and ukvm are expecting from each other.
Cheers
Adam
> Hi Mike
>
> In short i don't want to calculate the TSC frequency, i would like to
> get it from the kernel if possible? (also checking if it was
> invariant.) I knew my code was inaccurate, but didn't know another
> way.
>
> I did check the output of dmesg: "cpu0: TSC frequency 2492310500 Hz',
> but couldn't find a away to get this programmatically, eg via sysctl
>
> Long story, i am in the process of porting Solo5 to OpenBSD (see
> https://github.com/adamsteen/solo5) and need the tsc frequency to
> support the ukvm tsc clock.
>
> Is there currently a way to get the TSC frequency programmatically?
> and is CPUID the best way to check if the tsc is invariant?
> (CPUID.80000007H:EDX[8], Intel's Designer's vol3b, section 16.11.1
> Invariant TSC)
>
> On Mon, Jul 31, 2017 at 1:57 AM, Mike Belopuhov <[email protected]> wrote:
>> On Wed, Jul 26, 2017 at 19:24 +0800, Adam Steen wrote:
>>> Hi
>>>
>>> Is there an easy/accurate way to calculate the tsc timecounter frequency?
>>> like Time Stamp Counters <http://blog.tinola.com/?e=54> on Linux. (on a
>>> Sandy Bridge cpu)
>>>
>>> Another reference Converting Sandy Bridge TSC to wall clock time
>>> <https://software.intel.com/en-us/forums/intel-isa-extensions/topic/284137>.
>>>
>>> The code below works but i don't really know how accurate it is, at best
>>> 10,000 Hz.
>>>
>>> Cheers
>>> Adam
>>>
>>
>> Hi,
>>
>> First of all it's not clear why do you want to calculate TSC
>> frequency in the userland program? The kernel does it and
>> prints the result to the system message buffer (viewed with
>> the dmesg command).
>>
>> The second thing worth pointing out is that gettimeofday is a
>> syscall that queries the timestamp from the timecounter code
>> (updated every 10ms) with a current delta read directly from
>> the hardware so that you get an accurate reading, but then
>> it's adjusted according to the system time adjustment rules
>> imposed by things like NTP and settimeofday, so essentially
>> it's not monotonic (unless you can ensure there is no actor
>> present that is adjusting the time while you're performing
>> your measurement). There's also a way for userland to query
>> a precise monotonically increasing timestamp: clock_gettime
>> with CLOCK_MONOTONIC as the clock_id. In this case the
>> returned timestamp is relative to the moment the system was
>> brought up but this doesn't matter if all you need is
>> difference.
>>
>> The third thing to know is where does this hardware reading
>> comes from and what's its precision. Running "sysctl -n
>> kern.timecounter.hardware" will tell you what is currently
>> selected as the source and then you can locate that device
>> your dmesg (with exception of i8254 -- that 1.19Mhz PIT).
>> For instance on my laptop it's ACPI HPET that is proving a
>> running counter with the frequency of 14 MHz. This is what's
>> going to limit the precision of your measurement.
>>
>> To get a better reading you may try to take a series of say
>> 10 measurements and calculate the average.
>>
>> The difference between RDTSC and RDTSCP is that the latter
>> tells you on which CPU the instruction was executed. This
>> poses a valid question: is TSC frequency the same on a multi-
>> socket system. And I don't have an answer for that one.
>> AFAIU, this boils down to the motherboard design and if the
>> manufacturer has selected to use different quartz crystals
>> for different sockets, then as we know for a fact that no two
>> quartz crystals are created the same and thus frequency
>> sourced from them and multiplied by clock generator PLLs to
>> produce bus and then core clock signals will be slightly
>> different between sockets. I believe there's a way to
>> compensate for that but OpenBSD doesn't do this currently.
>>
>> However, your code doesn't check on which CPU the RDTSC has
>> been executed so you can just use RDTSC and hope that TSC
>> frequencies are the same and all counters on all cores have
>> been started at the same time by the firmware (which is
>> another question whether or not this is actually true).
>>
>> The CPUID call that you can see used there is there to
>> provide serialization. I believe there's no need to do it in
>> this case. In fact we haven't observed adverse effects w/o
>> an additional serialization instruction on Skylake where TSC
>> is used as the default timecounter (e.g. instead of an HPET).
>>
>> The other issue with your program is that you don't account
>> for how long does it take to perform a syscall operation. You
>> could time it before running the loop and then subtract the
>> reading.
>>
>> And finally, a userland program will not run a 1 second loop
>> uninterrupted since the scheduler will always attempt to
>> select a different process every 10ms. Which means that
>> a potential context switch and a 10ms timeslice of another
>> process might make its way into your measurement.
>>
>> This all begs the same question I asked in the beginning: why
>> do you want to calculate the TSC frequency in the userland
>> program?
>>
>>