mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-19 20:22:46 +00:00
HV: timer: keep TSC frequency in KHz
This patch represents TSC freqeuency in KHz using a 32-bit unsigned integer. The conversion macros between ticks and us/ms are changed to inline functions to enforce the types of the input parameters. Note that us_to_ticks accepts only uint32_t (~4K us at most) and never overflows. Results of some unit tests on the conversion functions: calibrate_tsc, tsc_khz=1881600 64us -> ticks: 120422 64us -> ticks -> us: 63 511us -> ticks: 961497 511us -> ticks -> us: 510 1280000 ticks -> us: 680 1280000 ticks -> us -> ticks: 1279488 Signed-off-by: Junjie Mao <junjie.mao@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
parent
ffc0b27db4
commit
e75cca64c8
@ -497,12 +497,12 @@ static void bsp_boot_post(void)
|
|||||||
pr_acrnlog("HV version %d.%d-rc%d-%s-%s %s build by %s, start time %lluus",
|
pr_acrnlog("HV version %d.%d-rc%d-%s-%s %s build by %s, start time %lluus",
|
||||||
HV_MAJOR_VERSION, HV_MINOR_VERSION, HV_RC_VERSION,
|
HV_MAJOR_VERSION, HV_MINOR_VERSION, HV_RC_VERSION,
|
||||||
HV_BUILD_TIME, HV_BUILD_VERSION, HV_BUILD_TYPE,
|
HV_BUILD_TIME, HV_BUILD_VERSION, HV_BUILD_TYPE,
|
||||||
HV_BUILD_USER, TICKS_TO_US(start_tsc));
|
HV_BUILD_USER, ticks_to_us(start_tsc));
|
||||||
else
|
else
|
||||||
pr_acrnlog("HV version %d.%d-%s-%s %s build by %s, start time %lluus",
|
pr_acrnlog("HV version %d.%d-%s-%s %s build by %s, start time %lluus",
|
||||||
HV_MAJOR_VERSION, HV_MINOR_VERSION,
|
HV_MAJOR_VERSION, HV_MINOR_VERSION,
|
||||||
HV_BUILD_TIME, HV_BUILD_VERSION, HV_BUILD_TYPE,
|
HV_BUILD_TIME, HV_BUILD_VERSION, HV_BUILD_TYPE,
|
||||||
HV_BUILD_USER, TICKS_TO_US(start_tsc));
|
HV_BUILD_USER, ticks_to_us(start_tsc));
|
||||||
|
|
||||||
pr_acrnlog("API version %d.%d",
|
pr_acrnlog("API version %d.%d",
|
||||||
HV_API_MAJOR_VERSION, HV_API_MINOR_VERSION);
|
HV_API_MAJOR_VERSION, HV_API_MINOR_VERSION);
|
||||||
|
@ -139,7 +139,7 @@ static void init_vcpuid_entry(__unused struct vm *vm,
|
|||||||
* EBX, ECX, EDX: RESERVED (reserved fields are set to zero).
|
* EBX, ECX, EDX: RESERVED (reserved fields are set to zero).
|
||||||
*/
|
*/
|
||||||
case 0x40000010:
|
case 0x40000010:
|
||||||
entry->eax = (uint32_t)(tsc_hz / 1000);
|
entry->eax = tsc_khz;
|
||||||
entry->ebx = 0;
|
entry->ebx = 0;
|
||||||
entry->ecx = 0;
|
entry->ecx = 0;
|
||||||
entry->edx = 0;
|
entry->edx = 0;
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
#define CAL_MS 10
|
#define CAL_MS 10
|
||||||
#define MIN_TIMER_PERIOD_US 500
|
#define MIN_TIMER_PERIOD_US 500
|
||||||
|
|
||||||
uint64_t tsc_hz = 1000000000;
|
uint32_t tsc_khz = 0U;
|
||||||
|
|
||||||
static void run_timer(struct timer *timer)
|
static void run_timer(struct timer *timer)
|
||||||
{
|
{
|
||||||
@ -79,7 +79,7 @@ int add_timer(struct timer *timer)
|
|||||||
/* limit minimal periodic timer cycle period */
|
/* limit minimal periodic timer cycle period */
|
||||||
if (timer->mode == TICK_MODE_PERIODIC)
|
if (timer->mode == TICK_MODE_PERIODIC)
|
||||||
timer->period_in_cycle = max(timer->period_in_cycle,
|
timer->period_in_cycle = max(timer->period_in_cycle,
|
||||||
US_TO_TICKS(MIN_TIMER_PERIOD_US));
|
us_to_ticks(MIN_TIMER_PERIOD_US));
|
||||||
|
|
||||||
pcpu_id = get_cpu_id();
|
pcpu_id = get_cpu_id();
|
||||||
cpu_timer = &per_cpu(cpu_timers, pcpu_id);
|
cpu_timer = &per_cpu(cpu_timers, pcpu_id);
|
||||||
@ -285,8 +285,10 @@ static uint64_t native_calibrate_tsc(void)
|
|||||||
|
|
||||||
void calibrate_tsc(void)
|
void calibrate_tsc(void)
|
||||||
{
|
{
|
||||||
|
uint64_t tsc_hz;
|
||||||
tsc_hz = native_calibrate_tsc();
|
tsc_hz = native_calibrate_tsc();
|
||||||
if (tsc_hz == 0U)
|
if (tsc_hz == 0U)
|
||||||
tsc_hz = pit_calibrate_tsc(CAL_MS);
|
tsc_hz = pit_calibrate_tsc(CAL_MS);
|
||||||
printf("%s, tsc_hz=%lu\n", __func__, tsc_hz);
|
tsc_khz = (uint32_t)(tsc_hz / 1000UL);
|
||||||
|
printf("%s, tsc_khz=%lu\n", __func__, tsc_khz);
|
||||||
}
|
}
|
||||||
|
@ -148,7 +148,7 @@ void get_vmexit_profile(char *str, int str_max)
|
|||||||
int len, size = str_max;
|
int len, size = str_max;
|
||||||
|
|
||||||
len = snprintf(str, size, "\r\nNow(us) = %16lld\r\n",
|
len = snprintf(str, size, "\r\nNow(us) = %16lld\r\n",
|
||||||
TICKS_TO_US(rdtsc()));
|
ticks_to_us(rdtsc()));
|
||||||
size -= len;
|
size -= len;
|
||||||
str += len;
|
str += len;
|
||||||
|
|
||||||
@ -169,7 +169,7 @@ void get_vmexit_profile(char *str, int str_max)
|
|||||||
for (cpu = 0; cpu < phys_cpu_num; cpu++) {
|
for (cpu = 0; cpu < phys_cpu_num; cpu++) {
|
||||||
len = snprintf(str, size, "\t%10lld\t%10lld",
|
len = snprintf(str, size, "\t%10lld\t%10lld",
|
||||||
per_cpu(vmexit_cnt, cpu)[i],
|
per_cpu(vmexit_cnt, cpu)[i],
|
||||||
TICKS_TO_US(per_cpu(vmexit_time, cpu)[i]));
|
ticks_to_us(per_cpu(vmexit_time, cpu)[i]));
|
||||||
size -= len;
|
size -= len;
|
||||||
str += len;
|
str += len;
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ void do_logmsg(uint32_t severity, const char *fmt, ...)
|
|||||||
timestamp = rdtsc();
|
timestamp = rdtsc();
|
||||||
|
|
||||||
/* Scale time-stamp appropriately */
|
/* Scale time-stamp appropriately */
|
||||||
timestamp = TICKS_TO_US(timestamp);
|
timestamp = ticks_to_us(timestamp);
|
||||||
|
|
||||||
/* Get CPU ID */
|
/* Get CPU ID */
|
||||||
cpu_id = get_cpu_id();
|
cpu_id = get_cpu_id();
|
||||||
|
@ -44,12 +44,28 @@ int atoi(const char *str);
|
|||||||
long strtol_deci(const char *nptr);
|
long strtol_deci(const char *nptr);
|
||||||
uint64_t strtoul_hex(const char *nptr);
|
uint64_t strtoul_hex(const char *nptr);
|
||||||
|
|
||||||
extern uint64_t tsc_hz;
|
/**
|
||||||
#define US_TO_TICKS(x) ((x) * tsc_hz / 1000000UL)
|
* Frequency of TSC in KHz (where 1KHz = 1000Hz). Only valid after
|
||||||
#define CYCLES_PER_MS US_TO_TICKS(1000UL)
|
* calibrate_tsc() returns.
|
||||||
|
*/
|
||||||
|
extern uint32_t tsc_khz;
|
||||||
|
|
||||||
#define TICKS_TO_US(x) ((((x) * (1000000UL >> 8)) / tsc_hz) << 8)
|
static inline uint64_t us_to_ticks(uint32_t us)
|
||||||
#define TICKS_TO_MS(x) (((x) * 1000UL) / tsc_hz)
|
{
|
||||||
|
return ((uint64_t)us * (uint64_t)tsc_khz / 1000UL);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CYCLES_PER_MS us_to_ticks(1000U)
|
||||||
|
|
||||||
|
static inline uint64_t ticks_to_us(uint64_t ticks)
|
||||||
|
{
|
||||||
|
return (ticks * 1000UL) / (uint64_t)tsc_khz;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint64_t ticks_to_ms(uint64_t ticks)
|
||||||
|
{
|
||||||
|
return ticks / (uint64_t)tsc_khz;
|
||||||
|
}
|
||||||
|
|
||||||
static inline uint64_t rdtsc(void)
|
static inline uint64_t rdtsc(void)
|
||||||
{
|
{
|
||||||
|
@ -11,7 +11,7 @@ void udelay(uint32_t us)
|
|||||||
uint64_t dest_tsc, delta_tsc;
|
uint64_t dest_tsc, delta_tsc;
|
||||||
|
|
||||||
/* Calculate number of ticks to wait */
|
/* Calculate number of ticks to wait */
|
||||||
delta_tsc = US_TO_TICKS(us);
|
delta_tsc = us_to_ticks(us);
|
||||||
dest_tsc = rdtsc() + delta_tsc;
|
dest_tsc = rdtsc() + delta_tsc;
|
||||||
|
|
||||||
/* Loop until time expired */
|
/* Loop until time expired */
|
||||||
|
Loading…
Reference in New Issue
Block a user