mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-26 15:31:35 +00:00
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:
parent
c2df3f7940
commit
5a2b89b0a4
@ -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 \
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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
124
hypervisor/arch/x86/tsc.c
Normal 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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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)) {
|
||||
|
@ -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
31
hypervisor/common/ticks.c
Normal 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();
|
||||
}
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
41
hypervisor/include/arch/x86/asm/tsc.h
Normal file
41
hypervisor/include/arch/x86/asm/tsc.h
Normal 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 */
|
53
hypervisor/include/common/ticks.h
Normal file
53
hypervisor/include/common/ticks.h
Normal 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 */
|
||||
|
Loading…
Reference in New Issue
Block a user