hv/mod_timer: refine timer interface

1. do not allow external modules to touch internal field of a timer.
2. make timer mode internal, period_in_ticks will decide the mode.

API wise:
1. the "mode" parameter was taken out of initialize_timer().
2. a new function update_timer() was added to update the timeout and
   period fields.
3. the timer_expired() function was extended with an output parameter
   to return the remaining cycles before expiration.

Also, the "fire_tsc" field name of hv_timer was renamed to "timeout".
With the new API, however, this change should not concern user code.

Tracked-On: #5920

Signed-off-by: Jason Chen CJ <jason.cj.chen@intel.com>
This commit is contained in:
Liang Yi
2021-04-19 16:55:07 +08:00
committed by wenlingz
parent 3547c9cd23
commit 6805510d77
7 changed files with 108 additions and 76 deletions

View File

@@ -260,9 +260,7 @@ static void vlapic_init_timer(struct acrn_vlapic *vlapic)
vtimer = &vlapic->vtimer;
(void)memset(vtimer, 0U, sizeof(struct vlapic_timer));
initialize_timer(&vtimer->timer,
vlapic_timer_expired, vlapic2vcpu(vlapic),
0UL, 0, 0UL);
initialize_timer(&vtimer->timer, vlapic_timer_expired, vlapic2vcpu(vlapic), 0UL, 0UL);
}
/**
@@ -274,16 +272,12 @@ static void vlapic_reset_timer(struct acrn_vlapic *vlapic)
timer = &vlapic->vtimer.timer;
del_timer(timer);
timer->mode = TICK_MODE_ONESHOT;
timer->fire_tsc = 0UL;
timer->period_in_cycle = 0UL;
update_timer(timer, 0UL, 0UL);
}
static bool
set_expiration(struct acrn_vlapic *vlapic)
{
uint64_t now = cpu_ticks();
uint64_t delta;
struct vlapic_timer *vtimer;
struct hv_timer *timer;
uint32_t tmicr, divisor_shift;
@@ -296,13 +290,11 @@ set_expiration(struct acrn_vlapic *vlapic)
if ((tmicr == 0U) || (divisor_shift > 8U)) {
ret = false;
} else {
delta = (uint64_t)tmicr << divisor_shift;
uint64_t delta = (uint64_t)tmicr << divisor_shift;
timer = &vtimer->timer;
if (vlapic_lvtt_period(vlapic)) {
timer->period_in_cycle = delta;
}
timer->fire_tsc = now + delta;
update_timer(timer, cpu_ticks() + delta,
vlapic_lvtt_period(vlapic) ? delta : 0UL);
ret = true;
}
return ret;
@@ -322,10 +314,7 @@ static void vlapic_update_lvtt(struct acrn_vlapic *vlapic,
* the timer mode disarms the local APIC timer.
*/
del_timer(timer);
timer->mode = (timer_mode == APIC_LVTT_TM_PERIODIC) ?
TICK_MODE_PERIODIC: TICK_MODE_ONESHOT;
timer->fire_tsc = 0UL;
timer->period_in_cycle = 0UL;
update_timer(timer, 0UL, 0UL);
vtimer->mode = timer_mode;
}
@@ -333,19 +322,13 @@ static void vlapic_update_lvtt(struct acrn_vlapic *vlapic,
static uint32_t vlapic_get_ccr(const struct acrn_vlapic *vlapic)
{
uint64_t now = cpu_ticks();
uint32_t remain_count = 0U;
const struct vlapic_timer *vtimer;
vtimer = &vlapic->vtimer;
const struct vlapic_timer *vtimer = &vlapic->vtimer;
if ((vtimer->tmicr != 0U) && (!vlapic_lvtt_tsc_deadline(vlapic))) {
uint64_t fire_tsc = vtimer->timer.fire_tsc;
if (now < fire_tsc) {
uint32_t divisor_shift = vtimer->divisor_shift;
uint64_t shifted_delta =
(fire_tsc - now) >> divisor_shift;
uint64_t remains;
if (!timer_expired(&vtimer->timer, cpu_ticks(), &remains)) {
uint64_t shifted_delta = remains >> vtimer->divisor_shift;
remain_count = (uint32_t)shifted_delta;
}
}
@@ -405,7 +388,7 @@ uint64_t vlapic_get_tsc_deadline_msr(const struct acrn_vlapic *vlapic)
} else if (!vlapic_lvtt_tsc_deadline(vlapic)) {
ret = 0UL;
} else {
ret = (vlapic->vtimer.timer.fire_tsc == 0UL) ? 0UL :
ret = timer_expired(&vlapic->vtimer.timer, cpu_ticks(), NULL) ? 0UL :
vcpu_get_guest_msr(vcpu, MSR_IA32_TSC_DEADLINE);
}
@@ -444,14 +427,14 @@ void vlapic_set_tsc_deadline_msr(struct acrn_vlapic *vlapic, uint64_t val_arg)
if (val != 0UL) {
/* transfer guest tsc to host tsc */
val -= exec_vmread64(VMX_TSC_OFFSET_FULL);
timer->fire_tsc = val;
update_timer(timer, val, 0UL);
/* vlapic_init_timer has been called,
* and timer->fire_tsc is not 0,here
* add_timer should not return error
*/
(void)add_timer(timer);
} else {
timer->fire_tsc = 0UL;
update_timer(timer, 0UL, 0UL);
}
} else {
/* No action required */
@@ -2039,10 +2022,6 @@ static void vlapic_timer_expired(void *data)
if (!vlapic_lvtt_masked(vlapic)) {
vlapic_set_intr(vcpu, lapic->lvt[APIC_LVT_TIMER].v & APIC_LVTT_VECTOR, LAPIC_TRIG_EDGE);
}
if (!vlapic_lvtt_period(vlapic)) {
vlapic->vtimer.timer.fire_tsc = 0UL;
}
}
/*