hv: vlapic_timer: remove vlapic one-shot/periodic timer implement

These code is useless since it just pseudocode. Current it doesn't
support vlapic one-shot/periodic timer.

Signed-off-by: Li, Fei1 <fei1.li@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Li, Fei1 2018-05-03 10:08:59 +08:00 committed by Jack Ren
parent 5df2efad4a
commit b9971c206f
4 changed files with 6 additions and 377 deletions

View File

@ -165,14 +165,11 @@ static void init_vcpuid_entry(__unused struct vm *vm,
*
* EAX: (Virtual) TSC frequency in kHz.
* TSC frequency is calculated from PIT in ACRN
* EBX: (Virtual) Bus (local apic timer) frequency in kHz.
* Bus (local apic timer) frequency is hardcoded as
* (128 * 1024 * 1024) in ACRN
* ECX, EDX: RESERVED (reserved fields are set to zero).
* EBX, ECX, EDX: RESERVED (reserved fields are set to zero).
*/
case 0x40000010:
entry->eax = (uint32_t)(tsc_hz / 1000);
entry->ebx = (128 * 1024 * 1024) / 1000;
entry->ebx = 0;
entry->ecx = 0;
entry->edx = 0;
break;

View File

@ -1,118 +0,0 @@
/*-
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
* Copyright (c) 2018 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)time.h 8.5 (Berkeley) 5/4/95
* $FreeBSD$
*/
#ifndef _TIME_H_
#define _TIME_H_
struct callout {
void *c_arg; /* function argument */
void (*c_func)(void *); /* function to call */
short c_flags; /* User State */
};
#define CALLOUT_ACTIVE 0x0002 /* callout is currently active */
#define CALLOUT_PENDING 0x0004 /* callout is waiting for timeout */
#define callout_active(c) ((c)->c_flags & CALLOUT_ACTIVE)
#define callout_deactivate(c) ((c)->c_flags &= ~CALLOUT_ACTIVE)
#define callout_pending(c) ((c)->c_flags & CALLOUT_PENDING)
typedef int64_t time_t;
typedef int64_t sbintime_t;
struct bintime {
time_t sec;
uint64_t frac;
};
static inline void
bintime_add(struct bintime *_bt, const struct bintime *_bt2)
{
uint64_t _u;
_u = _bt->frac;
_bt->frac += _bt2->frac;
if (_u > _bt->frac)
_bt->sec++;
_bt->sec += _bt2->sec;
}
static inline void
bintime_sub(struct bintime *_bt, const struct bintime *_bt2)
{
uint64_t _u;
_u = _bt->frac;
_bt->frac -= _bt2->frac;
if (_u < _bt->frac)
_bt->sec--;
_bt->sec -= _bt2->sec;
}
static inline void
bintime_mul(struct bintime *_bt, uint32_t _x)
{
uint64_t _p1, _p2;
_p1 = (_bt->frac & 0xffffffffull) * _x;
_p2 = (_bt->frac >> 32) * _x + (_p1 >> 32);
_bt->sec *= _x;
_bt->sec += (_p2 >> 32);
_bt->frac = (_p2 << 32) | (_p1 & 0xffffffffull);
}
#define bintime_cmp(a, b, cmp) \
(((a)->sec == (b)->sec) ? \
((a)->frac cmp(b)->frac) : \
((a)->sec cmp(b)->sec))
#define SBT_1S ((sbintime_t)1 << 32)
#define SBT_1US (SBT_1S / 1000000)
#define BT2FREQ(bt) \
(((uint64_t)0x8000000000000000 + ((bt)->frac >> 2)) / \
((bt)->frac >> 1))
#define FREQ2BT(freq, bt) \
{ \
(bt)->sec = 0; \
(bt)->frac = ((uint64_t)0x8000000000000000 / (freq)) << 1; \
}
static inline sbintime_t
bttosbt(const struct bintime _bt)
{
return (((sbintime_t)_bt.sec << 32) + (_bt.frac >> 32));
}
#endif /* !_TIME_H_ */

View File

@ -40,7 +40,6 @@
#include "instr_emul_wrapper.h"
#include "instr_emul.h"
#include "time.h"
#include "vlapic_priv.h"
#define VLAPIC_VERBOS 0
@ -86,22 +85,6 @@ do { \
#define VLAPIC_CTR_ISR(vlapic, msg)
#endif
/*
* The 'vlapic->timer_mtx' is used to provide mutual exclusion between the
* vlapic_callout_handler() and vcpu accesses to:
* - timer_freq_bt, timer_period_bt, timer_fire_bt
* - timer LVT register
*/
#define VLAPIC_TIMER_LOCK(vlapic) spinlock_obtain(&((vlapic)->timer_mtx))
#define VLAPIC_TIMER_UNLOCK(vlapic) spinlock_release(&((vlapic)->timer_mtx))
/*
* APIC timer frequency:
* - arbitrary but chosen to be in the ballpark of contemporary hardware.
* - power-of-two to avoid loss of precision when converted to a bintime.
*/
#define VLAPIC_BUS_FREQ (128 * 1024 * 1024)
/* TIMER_LVT bit[18:17] == 0x10 TSD DEADLINE mode */
#define VLAPIC_TSCDEADLINE(lvt) (((lvt) & 0x60000) == 0x40000)
@ -265,124 +248,13 @@ vlapic_id_write_handler(struct vlapic *vlapic)
lapic->id = vlapic_get_id(vlapic);
}
static void
binuptime(struct bintime *bt)
static uint32_t vlapic_get_ccr(__unused struct vlapic *vlapic)
{
uint64_t now = TICKS_TO_US(rdtsc());
bt->sec = now / 1000000;
bt->frac = ((now - bt->sec * 1000000) *
(uint64_t)0x80000000 / 1000000) << 33;
}
int
callout_reset_sbt(struct callout *c, __unused sbintime_t sbt,
__unused sbintime_t prec, void (*ftn)(void *),
void *arg, __unused int flags)
{
c->c_flags |= CALLOUT_PENDING;
c->c_func = ftn;
c->c_arg = arg;
/* TODO: add expire timer*/
c->c_flags &= ~CALLOUT_PENDING;
c->c_flags |= CALLOUT_ACTIVE;
return 0;
}
int
callout_stop(struct callout *c)
static void vlapic_dcr_write_handler(__unused struct vlapic *vlapic)
{
callout_deactivate(c);
c->c_flags |= CALLOUT_PENDING;
return 0;
}
static int
vlapic_timer_divisor(uint32_t dcr)
{
switch (dcr & 0xB) {
case APIC_TDCR_1:
return 1;
case APIC_TDCR_2:
return 2;
case APIC_TDCR_4:
return 4;
case APIC_TDCR_8:
return 8;
case APIC_TDCR_16:
return 16;
case APIC_TDCR_32:
return 32;
case APIC_TDCR_64:
return 64;
case APIC_TDCR_128:
return 128;
default:
panic("vlapic_timer_divisor: invalid dcr");
}
}
static uint32_t
vlapic_get_ccr(struct vlapic *vlapic)
{
struct bintime bt_now, bt_rem;
struct lapic *lapic;
uint32_t ccr;
ccr = 0;
lapic = vlapic->apic_page;
VLAPIC_TIMER_LOCK(vlapic);
if (callout_active(&vlapic->callout)) {
/*
* If the timer is scheduled to expire in the future then
* compute the value of 'ccr' based on the remaining time.
*/
binuptime(&bt_now);
if (bintime_cmp(&vlapic->timer_fire_bt, &bt_now, >)) {
bt_rem = vlapic->timer_fire_bt;
bintime_sub(&bt_rem, &bt_now);
ccr += bt_rem.sec * BT2FREQ(&vlapic->timer_freq_bt);
ccr += bt_rem.frac / vlapic->timer_freq_bt.frac;
}
}
ASSERT(ccr <= lapic->icr_timer,
"vlapic_get_ccr: invalid ccr %#x, icr_timer is %#x",
ccr, lapic->icr_timer);
dev_dbg(ACRN_DBG_LAPIC, "vlapic ccr_timer = %#x, icr_timer = %#x",
ccr, lapic->icr_timer);
VLAPIC_TIMER_UNLOCK(vlapic);
return ccr;
}
static void
vlapic_dcr_write_handler(struct vlapic *vlapic)
{
struct lapic *lapic;
int divisor;
lapic = vlapic->apic_page;
VLAPIC_TIMER_LOCK(vlapic);
divisor = vlapic_timer_divisor(lapic->dcr_timer);
dev_dbg(ACRN_DBG_LAPIC, "vlapic dcr_timer=%#x, divisor=%d",
lapic->dcr_timer, divisor);
/*
* Update the timer frequency and the timer period.
*
* XXX changes to the frequency divider will not take effect until
* the timer is reloaded.
*/
FREQ2BT(VLAPIC_BUS_FREQ / divisor, &vlapic->timer_freq_bt);
vlapic->timer_period_bt = vlapic->timer_freq_bt;
bintime_mul(&vlapic->timer_period_bt, lapic->icr_timer);
VLAPIC_TIMER_UNLOCK(vlapic);
}
static void
@ -784,17 +656,6 @@ vlapic_set_error(struct vlapic *vlapic, uint32_t mask)
vlapic->esr_firing = 0;
}
static void
vlapic_fire_timer(struct vlapic *vlapic)
{
uint32_t lvt;
/* The timer LVT always uses the fixed delivery mode.*/
lvt = vlapic_get_lvt(vlapic, APIC_OFFSET_TIMER_LVT);
if (vlapic_fire_lvt(vlapic, lvt | APIC_LVT_DM_FIXED))
dev_dbg(ACRN_DBG_LAPIC, "vlapic timer fired");
}
static int
vlapic_trigger_lvt(struct vlapic *vlapic, int vector)
{
@ -850,97 +711,8 @@ vlapic_trigger_lvt(struct vlapic *vlapic, int vector)
return 0;
}
static void
vlapic_callout_handler(void *arg)
static void vlapic_icrtmr_write_handler(__unused struct vlapic *vlapic)
{
struct vlapic *vlapic;
struct bintime bt, btnow;
sbintime_t rem_sbt;
vlapic = arg;
VLAPIC_TIMER_LOCK(vlapic);
if (callout_pending(&vlapic->callout)) /* callout was reset */
goto done;
if (!callout_active(&vlapic->callout)) /* callout was stopped */
goto done;
callout_deactivate(&vlapic->callout);
vlapic_fire_timer(vlapic);
if (vlapic_periodic_timer(vlapic)) {
binuptime(&btnow);
ASSERT(bintime_cmp(&btnow, &vlapic->timer_fire_bt, >=),
"vlapic callout at %#lx.%#lx, expected at %#lx.#%lx",
btnow.sec, btnow.frac, vlapic->timer_fire_bt.sec,
vlapic->timer_fire_bt.frac);
/*
* Compute the delta between when the timer was supposed to
* fire and the present time.
*/
bt = btnow;
bintime_sub(&bt, &vlapic->timer_fire_bt);
rem_sbt = bttosbt(vlapic->timer_period_bt);
if (bintime_cmp(&bt, &vlapic->timer_period_bt, <)) {
/*
* Adjust the time until the next countdown downward
* to account for the lost time.
*/
rem_sbt -= bttosbt(bt);
} else {
/*
* If the delta is greater than the timer period then
* just reset our time base instead of trying to catch
* up.
*/
vlapic->timer_fire_bt = btnow;
dev_dbg(ACRN_DBG_LAPIC,
"vlapic timer lagged by %lu usecs, period is %lu usecs",
bttosbt(bt) / SBT_1US,
bttosbt(vlapic->timer_period_bt) / SBT_1US);
dev_dbg(ACRN_DBG_LAPIC, "resetting time base");
}
bintime_add(&vlapic->timer_fire_bt, &vlapic->timer_period_bt);
callout_reset_sbt(&vlapic->callout, rem_sbt, 0,
vlapic_callout_handler, vlapic, 0);
}
done:
VLAPIC_TIMER_UNLOCK(vlapic);
}
static void
vlapic_icrtmr_write_handler(struct vlapic *vlapic)
{
struct lapic *lapic;
sbintime_t sbt;
uint32_t icr_timer;
VLAPIC_TIMER_LOCK(vlapic);
lapic = vlapic->apic_page;
icr_timer = lapic->icr_timer;
vlapic->timer_period_bt = vlapic->timer_freq_bt;
bintime_mul(&vlapic->timer_period_bt, icr_timer);
if (icr_timer != 0) {
binuptime(&vlapic->timer_fire_bt);
bintime_add(&vlapic->timer_fire_bt, &vlapic->timer_period_bt);
sbt = bttosbt(vlapic->timer_period_bt);
callout_reset_sbt(&vlapic->callout, sbt, 0,
vlapic_callout_handler, vlapic, 0);
} else
callout_stop(&vlapic->callout);
VLAPIC_TIMER_UNLOCK(vlapic);
}
/*
@ -1312,13 +1084,10 @@ vlapic_svr_write_handler(struct vlapic *vlapic)
if ((changed & APIC_SVR_ENABLE) != 0) {
if ((new & APIC_SVR_ENABLE) == 0) {
/*
* The apic is now disabled so stop the apic timer
* TODO: The apic is now disabled so stop the apic timer
* and mask all the LVT entries.
*/
dev_dbg(ACRN_DBG_LAPIC, "vlapic is software-disabled");
VLAPIC_TIMER_LOCK(vlapic);
callout_stop(&vlapic->callout);
VLAPIC_TIMER_UNLOCK(vlapic);
vlapic_mask_lvts(vlapic);
/* the only one enabled LINT0-ExtINT vlapic disabled */
if (vlapic->vm->vpic_wire_mode == VPIC_WIRE_NULL) {
@ -1592,12 +1361,7 @@ vlapic_init(struct vlapic *vlapic)
/*
* If the vlapic is configured in x2apic mode then it will be
* accessed in the critical section via the MSR emulation code.
*
* Therefore the timer mutex must be a spinlock because blockable
* mutexes cannot be acquired in a critical section.
*/
spinlock_init(&vlapic->timer_mtx);
vlapic->msr_apicbase = DEFAULT_APIC_BASE | APICBASE_ENABLED;
if (vlapic->vcpu->vcpu_id == 0)
@ -1631,12 +1395,6 @@ void vlapic_restore(struct vlapic *vlapic, struct lapic_regs *regs)
lapic->dcr_timer = regs->tdcr;
}
void
vlapic_cleanup(__unused struct vlapic *vlapic)
{
callout_stop(&vlapic->callout);
}
static uint64_t
vlapic_get_apicbase(struct vlapic *vlapic)
{

View File

@ -118,14 +118,8 @@ struct vlapic {
uint32_t esr_pending;
int esr_firing;
struct callout callout; /* vlapic timer */
struct bintime timer_fire_bt; /* callout expiry time */
struct bintime timer_freq_bt; /* timer frequency */
struct bintime timer_period_bt; /* timer period */
struct timer timer;
spinlock_t timer_mtx;
/*
* The 'isrvec_stk' is a stack of vectors injected by the local apic.
* A vector is popped from the stack when the processor does an EOI.
@ -148,6 +142,4 @@ struct vlapic {
struct pir_desc pir;
};
void vlapic_cleanup(struct vlapic *vlapic);
#endif /* _VLAPIC_PRIV_H_ */