doc: hv: add comments to timer APIs for documentation

This patch adds more comment to describe functions that are
interfaces to the other modules in the hypervisor. The comments
are in doxygen-style for document generation.

Tracked-On: #1595
Signed-off-by: Li, Fei1 <fei1.li@intel.com>
This commit is contained in:
Li, Fei1 2018-11-15 19:07:22 +08:00 committed by wenlingz
parent 2dbb0cbafc
commit 5fd6021dee
3 changed files with 108 additions and 48 deletions

View File

@ -808,6 +808,7 @@ INPUT = custom-doxygen/mainpage.md \
../hypervisor/include/public/acrn_common.h \ ../hypervisor/include/public/acrn_common.h \
../hypervisor/include/public/acrn_hv_defs.h \ ../hypervisor/include/public/acrn_hv_defs.h \
../hypervisor/include/arch/x86/guest/vcpu.h \ ../hypervisor/include/arch/x86/guest/vcpu.h \
../hypervisor/include/arch/x86/timer.h \
../hypervisor/arch/x86/trusty.c \ ../hypervisor/arch/x86/trusty.c \
../devicemodel/include/virtio.h \ ../devicemodel/include/virtio.h \
../hypervisor/include/arch/x86/ioapic.h \ ../hypervisor/include/arch/x86/ioapic.h \

View File

@ -24,37 +24,27 @@ tsc-deadline timer mode by writing the local APIC LVT register.
Data Structures and APIs Data Structures and APIs
************************ ************************
.. note:: API link to hv_timer and per_cpu_timer structs in include/arch/x86/timer.h Interfaces Design
And to the function APIs there too. =================
Before adding a timer, we must initialize the timer with .. doxygenfunction:: initialize_timer
*initialize_timer*. The processor generates a timer interrupt when the :project: Project ACRN
value of timer-stamp counter is greater than or equal to the *fire_tsc*
field. If you want to add a periodic timer, you should also pass the
period (unit in tsc cycles), otherwise, period_in_cycle will be ignored.
When the timer interrupt is generated, it will call the callback
function *func* with parameter *priv_data*.
The *initialize_timer* function only initialize the timer data .. doxygenfunction:: timer_expired
structure; it will not program the ``IA32_TSC_DEADLINE_MSR`` to generate :project: Project ACRN
the timer interrupt. If you want to generate a timer interrupt, you must
call *add_timer* to add the timer to the *per_cpu_timer* timer_list. In
return, we will chose the nearest expired timer on the timer_list and
program ``IA32_TSC_DEADLINE_MSR`` by writing its value to fire_ts. Then
when the fire_tsc expires, it raises the interrupt whose callback raises
a softirq. We will handle the software interrupt before the VM reenters
the guest. (Currently, the hypervisor only uses the timer for the
console).
The timer softirq handler will check each expired timer on its .. doxygenfunction:: add_timer
timer_list. Before calling the expired timer callback handler, it will :project: Project ACRN
remove the timer from its logical cpu timer_list. After calling the
timer callback handler, it will re-add the timer to the timer_list if
it's a periodic timer. If you want to modify a timer before it expires,
you should call del_timer to remove the timer from the timer_list, then
call add_timer again after updating the timer fields.
.. note:: .. doxygenfunction:: del_timer
:project: Project ACRN
.. doxygenfunction:: timer_init
:project: Project ACRN
.. doxygenfunction:: check_tsc
:project: Project ACRN
.. doxygenfunction:: calibrate_tsc
:project: Project ACRN
Only call initialize_timer only once for each timer.
Don't call add_timer or del_timer in the timer callback function.

View File

@ -7,36 +7,62 @@
#ifndef TIMER_H #ifndef TIMER_H
#define TIMER_H #define TIMER_H
/**
* @brief Timer
*
* @defgroup timer ACRN Timer
* @{
*/
typedef void (*timer_handle_t)(void *data); typedef void (*timer_handle_t)(void *data);
/**
* @brief Definition of timer tick mode
*/
enum tick_mode { enum tick_mode {
TICK_MODE_ONESHOT = 0, TICK_MODE_ONESHOT = 0, /**< one-shot mode */
TICK_MODE_PERIODIC, TICK_MODE_PERIODIC, /**< periodic mode */
}; };
/**
* @brief Definition of timers for per-cpu
*/
struct per_cpu_timers { struct per_cpu_timers {
struct list_head timer_list; /* it's for runtime active timer list */ struct list_head timer_list; /**< it's for runtime active timer list */
}; };
/**
* @brief Definition of timer
*/
struct hv_timer { struct hv_timer {
struct list_head node; /* link all timers */ struct list_head node; /**< link all timers */
enum tick_mode mode; /* timer mode: one-shot or periodic */ enum tick_mode mode; /**< timer mode: one-shot or periodic */
uint64_t fire_tsc; /* tsc deadline to interrupt */ uint64_t fire_tsc; /**< tsc deadline to interrupt */
uint64_t period_in_cycle; /* period of the periodic timer in unit of TSC cycles */ uint64_t period_in_cycle; /**< period of the periodic timer in unit of TSC cycles */
timer_handle_t func; /* callback if time reached */ timer_handle_t func; /**< callback if time reached */
void *priv_data; /* func private data */ void *priv_data; /**< func private data */
}; };
/* /* External Interfaces */
* Don't initialize a timer twice if it has been add to the timer list
* after call add_timer. If u want, delete the timer from the list first. /**
* @brief Initialize a timer structure.
*
* @param[in] timer Pointer to timer.
* @param[in] func irq callback if time reached.
* @param[in] priv_data func private data.
* @param[in] fire_tsc tsc deadline to interrupt.
* @param[in] mode timer mode.
* @param[in] period_in_cycle period of the periodic timer in unit of TSC cycles.
*
* @remark Don't initialize a timer twice if it has been added to the timer list
* after calling add_timer. If you want to, delete the timer from the list first.
*
* @return None
*/ */
static inline void initialize_timer(struct hv_timer *timer, static inline void initialize_timer(struct hv_timer *timer,
timer_handle_t func, timer_handle_t func, void *priv_data,
void *priv_data, uint64_t fire_tsc, int mode, uint64_t period_in_cycle)
uint64_t fire_tsc,
int mode,
uint64_t period_in_cycle)
{ {
if (timer != NULL) { if (timer != NULL) {
timer->func = func; timer->func = func;
@ -48,19 +74,62 @@ static inline void initialize_timer(struct hv_timer *timer,
} }
} }
/**
* @brief Check a timer whether expired.
*
* @param[in] timer Pointer to timer.
*
* @retval true if the timer is expired, false otherwise.
*/
static inline bool timer_expired(const struct hv_timer *timer) static inline bool timer_expired(const struct hv_timer *timer)
{ {
return ((timer->fire_tsc == 0UL) || (rdtsc() >= timer->fire_tsc)); return ((timer->fire_tsc == 0UL) || (rdtsc() >= timer->fire_tsc));
} }
/* /**
* Don't call add_timer/del_timer in the timer callback function. * @brief Add a timer.
*
* @param[in] timer Pointer to timer.
*
* @retval 0 on success
* @retval -EINVAL timer has an invalid value
*
* @remark Don't call it in the timer callback function or interrupt content.
*/ */
int add_timer(struct hv_timer *timer); int add_timer(struct hv_timer *timer);
/**
* @brief Delete a timer.
*
* @param[in] timer Pointer to timer.
*
* @return None
*
* @remark Don't call it in the timer callback function or interrupt content.
*/
void del_timer(struct hv_timer *timer); void del_timer(struct hv_timer *timer);
/**
* @brief Initialize timer.
*
* @return None
*/
void timer_init(void); void timer_init(void);
/**
* @brief Check tsc to make sure rdtsc is enabled.
*/
void check_tsc(void); void check_tsc(void);
/**
* @brief Calibrate tsc.
*
* @return None
*/
void calibrate_tsc(void); void calibrate_tsc(void);
/**
* @}
*/
#endif /* TIMER_H */ #endif /* TIMER_H */