blob: 593da70d452a5a8d45e1b695e9d2bedcaa0610c9 [file] [log] [blame]
/*
* Copyright 2017, Data61
* Commonwealth Scientific and Industrial Research Organisation (CSIRO)
* ABN 41 687 119 230.
*
* This software may be distributed and modified according to the terms of
* the BSD 2-Clause license. Note that NO WARRANTY is provided.
* See "LICENSE_BSD2.txt" for details.
*
* @TAG(DATA61_BSD)
*/
#include <platsupport/arch/tsc.h>
#include <utils/time.h>
#include <stdio.h>
#define WAIT_SECONDS 2ull
#define WAIT_NS (NS_IN_S * WAIT_SECONDS) /* 2 seconds in nano seconds to wait for */
uint64_t tsc_freq_hint = 0;
uint64_t tsc_calculate_frequency_hpet(const hpet_t *hpet)
{
if (tsc_freq_hint) {
return tsc_freq_hint;
}
uint64_t tsc_start = rdtsc_pure();
uint64_t hpet_start = hpet_get_time(hpet);
/* spin until WAIT_NS has passed */
while (hpet_get_time(hpet) - hpet_start < WAIT_NS);
uint64_t tsc_end = rdtsc_pure();
return (tsc_end - tsc_start) / WAIT_SECONDS;
}
uint64_t tsc_calculate_frequency_pit(pit_t *pit)
{
if (tsc_freq_hint) {
return tsc_freq_hint;
}
/* the PIT should be able to set a timeout for 50 ms */
uint64_t wait_ns = 50 * NS_IN_MS;
int UNUSED error = pit_set_timeout(pit, wait_ns, true);
assert(error == 0);
uint64_t start_time = rdtsc_pure();
uint64_t last_absolute = 0;
uint64_t total_observed = 0;
uint64_t time_offset = pit_get_time(pit);
uint64_t last_time = time_offset;
while (total_observed + last_absolute < WAIT_NS) {
uint64_t current_time = pit_get_time(pit);
if (current_time > last_time) {
total_observed += wait_ns;
}
last_absolute = wait_ns - current_time + time_offset;
last_time = current_time;
}
uint64_t end_time = rdtsc_pure();
/* well that was a fucking trial. Now hopefully we got something sane */
return (end_time - start_time) / WAIT_SECONDS;
}