hv/mod_timer: split tsc handling code from timer.

Generalize and split basic cpu cycle/tick routines from x86/timer:
- Instead of rdstc(), use cpu_ticks() in generic code.
- Instead of get_tsc_khz(), use cpu_tickrate() in generic code.
- Include "common/ticks.h" instead of "x86/timer.h" in generic code.
- CYCLES_PER_MS is renamed to TICKS_PER_MS.

The x86 specific API rdstc() and get_tsc_khz(), as well as TSC_PER_MS
are still available in arch/x86/tsc.h but only for x86 specific usage.

Tracked-On: #5920
Signed-off-by: Rong Liu <rong2.liu@intel.com>
Signed-off-by: Yi Liang <yi.liang@intel.com>
This commit is contained in:
Liang Yi 2021-04-08 17:36:12 +08:00 committed by wenlingz
parent c2df3f7940
commit 5a2b89b0a4
23 changed files with 301 additions and 209 deletions

View File

@ -808,6 +808,7 @@ INPUT = custom-doxygen/mainpage.md \
../hypervisor/include/arch/x86/asm/guest/assign.h \
../hypervisor/include/arch/x86/asm/guest/vcpu.h \
../hypervisor/include/arch/x86/asm/guest/virtual_cr.h \
../hypervisor/include/arch/x86/asm/tsc.h \
../hypervisor/include/arch/x86/asm/timer.h \
../hypervisor/include/arch/x86/asm/ioapic.h \
../hypervisor/include/arch/x86/asm/lapic.h \
@ -817,6 +818,7 @@ INPUT = custom-doxygen/mainpage.md \
../hypervisor/include/dm/io_req.h \
../hypervisor/include/common/hypercall.h \
../hypervisor/include/common/irq.h \
../hypervisor/include/common/ticks.h \
../hypervisor/include/common/ptdev.h \
../hypervisor/include/public/acrn_common.h \
../hypervisor/include/public/acrn_hv_defs.h \

View File

@ -219,6 +219,7 @@ HW_C_SRCS += arch/x86/gdt.c
HW_C_SRCS += arch/x86/nmi.c
HW_C_SRCS += arch/x86/exception.c
HW_C_SRCS += arch/x86/irq.c
HW_C_SRCS += arch/x86/tsc.c
HW_C_SRCS += arch/x86/timer.c
HW_C_SRCS += arch/x86/vmx.c
HW_C_SRCS += arch/x86/cpu_state_tbl.c
@ -228,6 +229,7 @@ HW_C_SRCS += arch/x86/trampoline.c
HW_S_SRCS += arch/x86/sched.S
HW_C_SRCS += arch/x86/rdt.c
HW_C_SRCS += arch/x86/sgx.c
HW_C_SRCS += common/ticks.c
HW_C_SRCS += common/irq.c
HW_C_SRCS += common/softirq.c
HW_C_SRCS += common/schedule.c

View File

@ -32,6 +32,7 @@
#include <ivshmem.h>
#include <asm/rtcm.h>
#include <reloc.h>
#include <ticks.h>
#define CPU_UP_TIMEOUT 100U /* millisecond */
#define CPU_DOWN_TIMEOUT 100U /* millisecond */
@ -49,7 +50,7 @@ static void init_keylocker(void);
static void set_current_pcpu_id(uint16_t pcpu_id);
static void print_hv_banner(void);
static uint16_t get_pcpu_id_from_lapic_id(uint32_t lapic_id);
static uint64_t start_tsc __attribute__((__section__(".bss_noinit")));
static uint64_t start_tick __attribute__((__section__(".bss_noinit")));
/**
* @pre phys_cpu_num <= MAX_PCPU_NUM
@ -124,7 +125,7 @@ void init_pcpu_pre(bool is_bsp)
if (is_bsp) {
pcpu_id = BSP_CPU_ID;
start_tsc = rdtsc();
start_tick = cpu_ticks();
/* Get CPU capabilities thru CPUID, including the physical address bit
* limit which is required for initializing paging.
@ -220,7 +221,7 @@ void init_pcpu_post(uint16_t pcpu_id)
HV_FULL_VERSION,
HV_BUILD_TIME, HV_BUILD_VERSION, HV_BUILD_TYPE,
HV_DAILY_TAG, HV_BUILD_SCENARIO, HV_BUILD_BOARD,
HV_BUILD_USER, HV_CONFIG_TOOL, ticks_to_us(start_tsc));
HV_BUILD_USER, HV_CONFIG_TOOL, ticks_to_us(start_tick));
pr_acrnlog("API version %u.%u", HV_API_MAJOR_VERSION, HV_API_MINOR_VERSION);

View File

@ -12,6 +12,7 @@
#include <logmsg.h>
#include <asm/vmx.h>
#include <asm/guest/hyperv.h>
#include <asm/tsc.h>
#define DBG_LEVEL_HYPERV 6U

View File

@ -17,6 +17,7 @@
#include <asm/security.h>
#include <logmsg.h>
#include <asm/seed.h>
#include <asm/tsc.h>
#define TRUSTY_VERSION 1U
#define TRUSTY_VERSION_2 2U
@ -282,7 +283,7 @@ static bool setup_trusty_info(struct acrn_vcpu *vcpu, uint32_t mem_size, uint64_
/* Prepare trusty startup param */
startup_param.size_of_this_struct = sizeof(struct trusty_startup_param);
startup_param.mem_size = mem_size;
startup_param.tsc_per_ms = CYCLES_PER_MS;
startup_param.tsc_per_ms = TSC_PER_MS;
startup_param.trusty_mem_base = TRUSTY_EPT_REBASE_GPA;
/* According to trusty boot protocol, it will use RDI as the

View File

@ -13,6 +13,7 @@
#include <asm/cpufeatures.h>
#include <asm/vmx.h>
#include <asm/sgx.h>
#include <asm/tsc.h>
#include <logmsg.h>
static inline const struct vcpuid_entry *local_find_vcpuid_entry(const struct acrn_vcpu *vcpu,

View File

@ -46,6 +46,7 @@
#include <trace.h>
#include <logmsg.h>
#include <asm/irq.h>
#include <ticks.h>
#include "vlapic_priv.h"
#define VLAPIC_VERBOS 0
@ -281,7 +282,7 @@ static void vlapic_reset_timer(struct acrn_vlapic *vlapic)
static bool
set_expiration(struct acrn_vlapic *vlapic)
{
uint64_t now = rdtsc();
uint64_t now = cpu_ticks();
uint64_t delta;
struct vlapic_timer *vtimer;
struct hv_timer *timer;
@ -332,7 +333,7 @@ static void vlapic_update_lvtt(struct acrn_vlapic *vlapic,
static uint32_t vlapic_get_ccr(const struct acrn_vlapic *vlapic)
{
uint64_t now = rdtsc();
uint64_t now = cpu_ticks();
uint32_t remain_count = 0U;
const struct vlapic_timer *vtimer;

View File

@ -19,6 +19,7 @@
#include <asm/guest/nested.h>
#include <asm/cpufeatures.h>
#include <asm/rdt.h>
#include <asm/tsc.h>
#include <trace.h>
#include <logmsg.h>

View File

@ -14,21 +14,11 @@
#include <softirq.h>
#include <trace.h>
#include <asm/irq.h>
#include <ticks.h>
#define MAX_TIMER_ACTIONS 32U
#define CAL_MS 10U
#define MIN_TIMER_PERIOD_US 500U
static uint32_t tsc_khz;
uint64_t rdtsc(void)
{
uint32_t lo, hi;
asm volatile("rdtsc" : "=a" (lo), "=d" (hi));
return ((uint64_t)hi << 32U) | lo;
}
static void run_timer(const struct hv_timer *timer)
{
/* deadline = 0 means stop timer, we should skip */
@ -211,129 +201,6 @@ void timer_init(void)
}
}
static uint64_t pit_calibrate_tsc(uint32_t cal_ms_arg)
{
#define PIT_TICK_RATE 1193182U
#define PIT_TARGET 0x3FFFU
#define PIT_MAX_COUNT 0xFFFFU
uint32_t cal_ms = cal_ms_arg;
uint32_t initial_pit;
uint16_t current_pit;
uint32_t max_cal_ms;
uint64_t current_tsc;
uint8_t initial_pit_high, initial_pit_low;
max_cal_ms = ((PIT_MAX_COUNT - PIT_TARGET) * 1000U) / PIT_TICK_RATE;
cal_ms = min(cal_ms, max_cal_ms);
/* Assume the 8254 delivers 18.2 ticks per second when 16 bits fully
* wrap. This is about 1.193MHz or a clock period of 0.8384uSec
*/
initial_pit = (cal_ms * PIT_TICK_RATE) / 1000U;
initial_pit += PIT_TARGET;
initial_pit_high = (uint8_t)(initial_pit >> 8U);
initial_pit_low = (uint8_t)initial_pit;
/* Port 0x43 ==> Control word write; Data 0x30 ==> Select Counter 0,
* Read/Write least significant byte first, mode 0, 16 bits.
*/
pio_write8(0x30U, 0x43U);
pio_write8(initial_pit_low, 0x40U); /* Write LSB */
pio_write8(initial_pit_high, 0x40U); /* Write MSB */
current_tsc = rdtsc();
do {
/* Port 0x43 ==> Control word write; 0x00 ==> Select
* Counter 0, Counter Latch Command, Mode 0; 16 bits
*/
pio_write8(0x00U, 0x43U);
current_pit = (uint16_t)pio_read8(0x40U); /* Read LSB */
current_pit |= (uint16_t)pio_read8(0x40U) << 8U; /* Read MSB */
/* Let the counter count down to PIT_TARGET */
} while (current_pit > PIT_TARGET);
current_tsc = rdtsc() - current_tsc;
return (current_tsc / cal_ms) * 1000U;
}
/*
* Determine TSC frequency via CPUID 0x15 and 0x16.
*/
static uint64_t native_calibrate_tsc(void)
{
uint64_t tsc_hz = 0UL;
const struct cpuinfo_x86 *cpu_info = get_pcpu_info();
if (cpu_info->cpuid_level >= 0x15U) {
uint32_t eax_denominator, ebx_numerator, ecx_hz, reserved;
cpuid_subleaf(0x15U, 0x0U, &eax_denominator, &ebx_numerator,
&ecx_hz, &reserved);
if ((eax_denominator != 0U) && (ebx_numerator != 0U)) {
tsc_hz = ((uint64_t) ecx_hz *
ebx_numerator) / eax_denominator;
}
}
if ((tsc_hz == 0UL) && (cpu_info->cpuid_level >= 0x16U)) {
uint32_t eax_base_mhz, ebx_max_mhz, ecx_bus_mhz, edx;
cpuid_subleaf(0x16U, 0x0U, &eax_base_mhz, &ebx_max_mhz, &ecx_bus_mhz, &edx);
tsc_hz = (uint64_t) eax_base_mhz * 1000000U;
}
return tsc_hz;
}
void calibrate_tsc(void)
{
uint64_t tsc_hz;
tsc_hz = native_calibrate_tsc();
if (tsc_hz == 0U) {
tsc_hz = pit_calibrate_tsc(CAL_MS);
}
tsc_khz = (uint32_t)(tsc_hz / 1000UL);
printf("%s, tsc_khz=%lu\n", __func__, tsc_khz);
}
uint32_t get_tsc_khz(void)
{
return tsc_khz;
}
/**
* Frequency of TSC in KHz (where 1KHz = 1000Hz). Only valid after
* calibrate_tsc() returns.
*/
uint64_t us_to_ticks(uint32_t us)
{
return (((uint64_t)us * (uint64_t)tsc_khz) / 1000UL);
}
uint64_t ticks_to_us(uint64_t ticks)
{
uint64_t us = 0UL;
if (tsc_khz != 0U) {
us = (ticks * 1000UL) / (uint64_t)tsc_khz;
}
return us;
}
uint64_t ticks_to_ms(uint64_t ticks)
{
return ticks / (uint64_t)tsc_khz;
}
void udelay(uint32_t us)
{
uint64_t dest_tsc, delta_tsc;

124
hypervisor/arch/x86/tsc.c Normal file
View File

@ -0,0 +1,124 @@
/*
* Copyright (C) 2021 Intel Corporation.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <types.h>
#include <util.h>
#include <asm/cpuid.h>
#include <asm/cpu_caps.h>
#include <asm/io.h>
#include <asm/tsc.h>
#define CAL_MS 10U
static uint32_t tsc_khz;
static uint64_t pit_calibrate_tsc(uint32_t cal_ms_arg)
{
#define PIT_TICK_RATE 1193182U
#define PIT_TARGET 0x3FFFU
#define PIT_MAX_COUNT 0xFFFFU
uint32_t cal_ms = cal_ms_arg;
uint32_t initial_pit;
uint16_t current_pit;
uint32_t max_cal_ms;
uint64_t current_tsc;
uint8_t initial_pit_high, initial_pit_low;
max_cal_ms = ((PIT_MAX_COUNT - PIT_TARGET) * 1000U) / PIT_TICK_RATE;
cal_ms = min(cal_ms, max_cal_ms);
/* Assume the 8254 delivers 18.2 ticks per second when 16 bits fully
* wrap. This is about 1.193MHz or a clock period of 0.8384uSec
*/
initial_pit = (cal_ms * PIT_TICK_RATE) / 1000U;
initial_pit += PIT_TARGET;
initial_pit_high = (uint8_t)(initial_pit >> 8U);
initial_pit_low = (uint8_t)initial_pit;
/* Port 0x43 ==> Control word write; Data 0x30 ==> Select Counter 0,
* Read/Write least significant byte first, mode 0, 16 bits.
*/
pio_write8(0x30U, 0x43U);
pio_write8(initial_pit_low, 0x40U); /* Write LSB */
pio_write8(initial_pit_high, 0x40U); /* Write MSB */
current_tsc = rdtsc();
do {
/* Port 0x43 ==> Control word write; 0x00 ==> Select
* Counter 0, Counter Latch Command, Mode 0; 16 bits
*/
pio_write8(0x00U, 0x43U);
current_pit = (uint16_t)pio_read8(0x40U); /* Read LSB */
current_pit |= (uint16_t)pio_read8(0x40U) << 8U; /* Read MSB */
/* Let the counter count down to PIT_TARGET */
} while (current_pit > PIT_TARGET);
current_tsc = rdtsc() - current_tsc;
return (current_tsc / cal_ms) * 1000U;
}
/*
* Determine TSC frequency via CPUID 0x15 and 0x16.
*/
static uint64_t native_calibrate_tsc(void)
{
uint64_t tsc_hz = 0UL;
const struct cpuinfo_x86 *cpu_info = get_pcpu_info();
if (cpu_info->cpuid_level >= 0x15U) {
uint32_t eax_denominator, ebx_numerator, ecx_hz, reserved;
cpuid_subleaf(0x15U, 0x0U, &eax_denominator, &ebx_numerator,
&ecx_hz, &reserved);
if ((eax_denominator != 0U) && (ebx_numerator != 0U)) {
tsc_hz = ((uint64_t) ecx_hz *
ebx_numerator) / eax_denominator;
}
}
if ((tsc_hz == 0UL) && (cpu_info->cpuid_level >= 0x16U)) {
uint32_t eax_base_mhz, ebx_max_mhz, ecx_bus_mhz, edx;
cpuid_subleaf(0x16U, 0x0U, &eax_base_mhz, &ebx_max_mhz, &ecx_bus_mhz, &edx);
tsc_hz = (uint64_t) eax_base_mhz * 1000000U;
}
return tsc_hz;
}
void calibrate_tsc(void)
{
uint64_t tsc_hz;
tsc_hz = native_calibrate_tsc();
if (tsc_hz == 0U) {
tsc_hz = pit_calibrate_tsc(CAL_MS);
}
tsc_khz = (uint32_t)(tsc_hz / 1000UL);
}
uint32_t get_tsc_khz(void)
{
return tsc_khz;
}
/* external API */
uint64_t cpu_ticks(void)
{
return rdtsc();
}
uint32_t cpu_tickrate(void)
{
return tsc_khz;
}

View File

@ -17,7 +17,7 @@
#include <asm/mmu.h>
#include <asm/lapic.h>
#include <asm/vtd.h>
#include <asm/timer.h>
#include <ticks.h>
#include <logmsg.h>
#include <asm/board.h>
#include <asm/vm_config.h>
@ -248,11 +248,11 @@ static inline void dmar_wait_completion(const struct dmar_drhd_rt *dmar_unit, ui
uint32_t mask, uint32_t pre_condition, uint32_t *status)
{
/* variable start isn't used when built as release version */
__unused uint64_t start = rdtsc();
__unused uint64_t start = cpu_ticks();
do {
*status = iommu_read32(dmar_unit, offset);
ASSERT(((rdtsc() - start) < CYCLES_PER_MS),
ASSERT(((cpu_ticks() - start) < TICKS_PER_MS),
"DMAR OP Timeout!");
asm_pause();
} while( (*status & mask) == pre_condition);
@ -564,9 +564,9 @@ static void dmar_issue_qi_request(struct dmar_drhd_rt *dmar_unit, struct dmar_en
qi_status = DMAR_INV_STATUS_INCOMPLETE;
iommu_write32(dmar_unit, DMAR_IQT_REG, dmar_unit->qi_tail);
start = rdtsc();
start = cpu_ticks();
while (qi_status != DMAR_INV_STATUS_COMPLETED) {
if ((rdtsc() - start) > CYCLES_PER_MS) {
if ((cpu_ticks() - start) > TICKS_PER_MS) {
pr_err("DMAR OP Timeout! @ %s", __func__);
break;
}

View File

@ -24,6 +24,7 @@
#include <vmcs9900.h>
#include <asm/rtcm.h>
#include <asm/irq.h>
#include <ticks.h>
#define DBG_LEVEL_HYCALL 6U
@ -1134,7 +1135,7 @@ int32_t hcall_vm_intr_monitor(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm,
case INTR_CMD_DELAY_INT:
/* buffer[0] is the delay time (in MS), if 0 to cancel delay */
target_vm->intr_inject_delay_delta =
intr_hdr->buffer[0] * CYCLES_PER_MS;
intr_hdr->buffer[0] * TICKS_PER_MS;
break;
default:

View File

@ -12,6 +12,7 @@
#include <irq.h>
#include <logmsg.h>
#include <asm/vtd.h>
#include <ticks.h>
#define PTIRQ_ENTRY_HASHBITS 9U
#define PTIRQ_ENTRY_HASHSIZE (1U << PTIRQ_ENTRY_HASHBITS)
@ -176,7 +177,8 @@ static void ptirq_interrupt_handler(__unused uint32_t irq, void *data)
if (timer_is_started(&entry->intr_delay_timer)) {
to_enqueue = false;
} else {
entry->intr_delay_timer.fire_tsc = rdtsc() + entry->vm->intr_inject_delay_delta;
entry->intr_delay_timer.fire_tsc =
cpu_ticks() + entry->vm->intr_inject_delay_delta;
}
} else {
entry->intr_delay_timer.fire_tsc = 0UL;

View File

@ -7,6 +7,7 @@
#include <list.h>
#include <asm/per_cpu.h>
#include <schedule.h>
#include <ticks.h>
#define BVT_MCU_MS 1U
/* context switch allowance */
@ -148,7 +149,7 @@ static void sched_tick_handler(void *param)
static int sched_bvt_init(struct sched_control *ctl)
{
struct sched_bvt_control *bvt_ctl = &per_cpu(sched_bvt_ctl, ctl->pcpu_id);
uint64_t tick_period = BVT_MCU_MS * CYCLES_PER_MS;
uint64_t tick_period = BVT_MCU_MS * TICKS_PER_MS;
int ret = 0;
ASSERT(ctl->pcpu_id == get_pcpu_id(), "Init scheduler on wrong CPU!");
@ -158,7 +159,7 @@ static int sched_bvt_init(struct sched_control *ctl)
/* The tick_timer is periodically */
initialize_timer(&bvt_ctl->tick_timer, sched_tick_handler, ctl,
rdtsc() + tick_period, TICK_MODE_PERIODIC, tick_period);
cpu_ticks() + tick_period, TICK_MODE_PERIODIC, tick_period);
if (add_timer(&bvt_ctl->tick_timer) < 0) {
pr_err("Failed to add schedule tick timer!");
@ -180,7 +181,7 @@ static void sched_bvt_init_data(struct thread_object *obj)
data = (struct sched_bvt_data *)obj->data;
INIT_LIST_HEAD(&data->list);
data->mcu = BVT_MCU_MS * CYCLES_PER_MS;
data->mcu = BVT_MCU_MS * TICKS_PER_MS;
/* TODO: virtual time advance ratio should be proportional to weight. */
data->vt_ratio = 1U;
data->residual = 0U;
@ -200,7 +201,7 @@ static uint64_t p2v(uint64_t phy_time, uint64_t ratio)
static void update_vt(struct thread_object *obj)
{
struct sched_bvt_data *data;
uint64_t now_tsc = rdtsc();
uint64_t now_tsc = cpu_ticks();
uint64_t v_delta, delta_mcu = 0U;
data = (struct sched_bvt_data *)obj->data;
@ -229,7 +230,7 @@ static struct thread_object *sched_bvt_pick_next(struct sched_control *ctl)
struct list_head *first, *sec;
struct thread_object *next = NULL;
struct thread_object *current = ctl->curr_obj;
uint64_t now_tsc = rdtsc();
uint64_t now_tsc = cpu_ticks();
uint64_t delta_mcu = 0U;
if (!is_idle_thread(current)) {

View File

@ -7,6 +7,7 @@
#include <list.h>
#include <asm/per_cpu.h>
#include <schedule.h>
#include <ticks.h>
#define CONFIG_SLICE_MS 10UL
struct sched_iorr_data {
@ -77,7 +78,7 @@ static void sched_tick_handler(void *param)
struct sched_iorr_data *data;
struct thread_object *current;
uint16_t pcpu_id = get_pcpu_id();
uint64_t now = rdtsc();
uint64_t now = cpu_ticks();
uint64_t rflags;
obtain_schedule_lock(pcpu_id, &rflags);
@ -106,7 +107,7 @@ static void sched_tick_handler(void *param)
int sched_iorr_init(struct sched_control *ctl)
{
struct sched_iorr_control *iorr_ctl = &per_cpu(sched_iorr_ctl, ctl->pcpu_id);
uint64_t tick_period = CYCLES_PER_MS;
uint64_t tick_period = TICKS_PER_MS;
int ret = 0;
ASSERT(get_pcpu_id() == ctl->pcpu_id, "Init scheduler on wrong CPU!");
@ -116,7 +117,7 @@ int sched_iorr_init(struct sched_control *ctl)
/* The tick_timer is periodically */
initialize_timer(&iorr_ctl->tick_timer, sched_tick_handler, ctl,
rdtsc() + tick_period, TICK_MODE_PERIODIC, tick_period);
cpu_ticks() + tick_period, TICK_MODE_PERIODIC, tick_period);
if (add_timer(&iorr_ctl->tick_timer) < 0) {
pr_err("Failed to add schedule tick timer!");
@ -137,7 +138,7 @@ void sched_iorr_init_data(struct thread_object *obj)
data = (struct sched_iorr_data *)obj->data;
INIT_LIST_HEAD(&data->list);
data->left_cycles = data->slice_cycles = CONFIG_SLICE_MS * CYCLES_PER_MS;
data->left_cycles = data->slice_cycles = CONFIG_SLICE_MS * TICKS_PER_MS;
}
static struct thread_object *sched_iorr_pick_next(struct sched_control *ctl)
@ -146,7 +147,7 @@ static struct thread_object *sched_iorr_pick_next(struct sched_control *ctl)
struct thread_object *next = NULL;
struct thread_object *current = NULL;
struct sched_iorr_data *data;
uint64_t now = rdtsc();
uint64_t now = cpu_ticks();
current = ctl->curr_obj;
data = (struct sched_iorr_data *)current->data;

31
hypervisor/common/ticks.c Normal file
View File

@ -0,0 +1,31 @@
/*
* Copyright (C) 2021 Intel Corporation.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <common/ticks.h>
/* cpu_ticks() and cpu_tickrate() are provided in arch specific modules */
uint64_t us_to_ticks(uint32_t us)
{
return (((uint64_t)us * (uint64_t)cpu_tickrate()) / 1000UL);
}
uint64_t ticks_to_us(uint64_t ticks)
{
uint64_t us = 0UL;
uint64_t khz = cpu_tickrate();
if (khz != 0U) {
us = (ticks * 1000UL) / (uint64_t)khz;
}
return us;
}
uint64_t ticks_to_ms(uint64_t ticks)
{
return ticks / (uint64_t)cpu_tickrate();
}

View File

@ -9,6 +9,7 @@
#include <uart16550.h>
#include <shell.h>
#include <asm/timer.h>
#include <ticks.h>
#include <vuart.h>
#include <logmsg.h>
#include <acrn_hv_defs.h>
@ -161,8 +162,8 @@ void console_setup_timer(void)
{
uint64_t period_in_cycle, fire_tsc;
period_in_cycle = CYCLES_PER_MS * CONSOLE_KICK_TIMER_TIMEOUT;
fire_tsc = rdtsc() + period_in_cycle;
period_in_cycle = TICKS_PER_MS * CONSOLE_KICK_TIMER_TIMEOUT;
fire_tsc = cpu_ticks() + period_in_cycle;
initialize_timer(&console_timer,
console_timer_callback, NULL,
fire_tsc, TICK_MODE_PERIODIC, period_in_cycle);

View File

@ -11,6 +11,7 @@
#include <asm/per_cpu.h>
#include <npk_log.h>
#include <logmsg.h>
#include <ticks.h>
/* buf size should be identical to the size in hvlog option, which is
* transfered to SOS:
@ -53,7 +54,7 @@ void do_logmsg(uint32_t severity, const char *fmt, ...)
}
/* Get time-stamp value */
timestamp = rdtsc();
timestamp = cpu_ticks();
/* Scale time-stamp appropriately */
timestamp = ticks_to_us(timestamp);

View File

@ -15,6 +15,7 @@
#include <asm/guest/vm.h>
#include <sprintf.h>
#include <logmsg.h>
#include <ticks.h>
#define DBG_LEVEL_PROFILING 5U
#define DBG_LEVEL_ERR_PROFILING 3U
@ -339,7 +340,7 @@ static int32_t profiling_generate_data(int32_t collector, uint32_t type)
clac();
/* populate the data header */
pkt_header.tsc = rdtsc();
pkt_header.tsc = cpu_ticks();
pkt_header.collector_id = collector;
pkt_header.cpu_id = get_pcpu_id();
pkt_header.data_type = 1U << type;
@ -411,7 +412,7 @@ static int32_t profiling_generate_data(int32_t collector, uint32_t type)
clac();
/* populate the data header */
pkt_header.tsc = rdtsc();
pkt_header.tsc = cpu_ticks();
pkt_header.collector_id = collector;
pkt_header.cpu_id = get_pcpu_id();
pkt_header.data_type = (uint16_t)type;
@ -1307,7 +1308,7 @@ void profiling_vmenter_handler(__unused struct acrn_vcpu *vcpu)
((socwatch_collection_switch &
(1UL << (uint64_t)SOCWATCH_VM_SWITCH_TRACING)) > 0UL))) {
get_cpu_var(profiling_info.vm_info).vmenter_tsc = rdtsc();
get_cpu_var(profiling_info.vm_info).vmenter_tsc = cpu_ticks();
}
}
@ -1323,7 +1324,7 @@ void profiling_pre_vmexit_handler(struct acrn_vcpu *vcpu)
if ((get_cpu_var(profiling_info.s_state).pmu_state == PMU_RUNNING) ||
(get_cpu_var(profiling_info.soc_state) == SW_RUNNING)) {
get_cpu_var(profiling_info.vm_info).vmexit_tsc = rdtsc();
get_cpu_var(profiling_info.vm_info).vmexit_tsc = cpu_ticks();
get_cpu_var(profiling_info.vm_info).vmexit_reason
= exit_reason;
if (exit_reason == VMX_EXIT_REASON_EXTERNAL_INTERRUPT) {

View File

@ -6,6 +6,7 @@
#include <types.h>
#include <asm/per_cpu.h>
#include <ticks.h>
#include <trace.h>
#define TRACE_CUSTOM 0xFCU
@ -51,7 +52,7 @@ static inline void trace_put(uint16_t cpu_id, uint32_t evid, uint32_t n_data, st
{
struct shared_buf *sbuf = per_cpu(sbuf, cpu_id)[ACRN_TRACE];
entry->tsc = rdtsc();
entry->tsc = cpu_ticks();
entry->id = evid;
entry->n_data = (uint8_t)n_data;
entry->cpu = (uint8_t)cpu_id;

View File

@ -8,6 +8,7 @@
#define TIMER_H
#include <list.h>
#include <asm/tsc.h>
/**
* @brief Timer
@ -47,38 +48,8 @@ struct hv_timer {
/* External Interfaces */
#define CYCLES_PER_MS us_to_ticks(1000U)
void udelay(uint32_t us);
/**
* @brief convert us to ticks.
*
* @return ticks
*/
uint64_t us_to_ticks(uint32_t us);
/**
* @brief convert ticks to us.
*
* @return microsecond
*/
uint64_t ticks_to_us(uint64_t ticks);
/**
* @brief convert ticks to ms.
*
* @return millisecond
*/
uint64_t ticks_to_ms(uint64_t ticks);
/**
* @brief read tsc.
*
* @return tsc value
*/
uint64_t rdtsc(void);
/**
* @brief Initialize a timer structure.
*
@ -162,20 +133,6 @@ void del_timer(struct hv_timer *timer);
*/
void timer_init(void);
/**
* @brief Calibrate tsc.
*
* @return None
*/
void calibrate_tsc(void);
/**
* @brief Get tsc.
*
* @return tsc(KHz)
*/
uint32_t get_tsc_khz(void);
/**
* @}
*/

View File

@ -0,0 +1,41 @@
/*
* Copyright (C) 2021 Intel Corporation.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef ARCH_X86_TSC_H
#define ARCH_X86_TSC_H
#include <types.h>
#define TSC_PER_MS ((uint64_t)get_tsc_khz())
/**
* @brief Read Time Stamp Counter (TSC).
*
* @return TSC value
*/
static inline uint64_t rdtsc(void)
{
uint32_t lo, hi;
asm volatile("rdtsc" : "=a" (lo), "=d" (hi));
return ((uint64_t)hi << 32U) | lo;
}
/**
* @brief Get Time Stamp Counter (TSC) frequency in KHz.
*
* @return TSC frequency in KHz
*/
uint32_t get_tsc_khz(void);
/**
* @brief Calibrate Time Stamp Counter (TSC) frequency.
*
* @return None
*/
void calibrate_tsc(void);
#endif /* ARCH_X86_TSC_H */

View File

@ -0,0 +1,53 @@
/*
* Copyright (C) 2021 Intel Corporation.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef COMMON_TICKS_H
#define COMMON_TICKS_H
#include <types.h>
#define TICKS_PER_MS us_to_ticks(1000U)
/**
* @brief Read current CPU tick count.
*
* @return CPU ticks
*/
uint64_t cpu_ticks(void);
/**
* @brief Get CPU tick frequency in KHz.
*
* @return CPU frequency (KHz)
*/
uint32_t cpu_tickrate(void);
/**
* @brief Convert micro seconds to CPU ticks.
*
* @param[in] us micro seconds to convert
* @return CPU ticks
*/
uint64_t us_to_ticks(uint32_t us);
/**
* @brief Convert CPU cycles to micro seconds.
*
* @param[in] ticks CPU ticks to convert
* @return microsecond
*/
uint64_t ticks_to_us(uint64_t ticks);
/**
* @brief Convert CPU cycles to milli seconds.
*
* @param[in] ticks CPU ticks to convert
* @return millisecond
*/
uint64_t ticks_to_ms(uint64_t ticks);
#endif /* COMMON_TICKS_H */