acrn-hypervisor/doc/developer-guides/hld/hv-timer.rst

61 lines
2.6 KiB
ReStructuredText

.. _timer-hld:
Timer
#####
Because ACRN is a flexible, lightweight reference hypervisor, we provide
limited timer management services:
- Only lapic tsc-deadline timer is supported as the clock source.
- A timer can only be added on the logical CPU for a process or thread. Timer
scheduling or timer migrating are not supported.
How it works
************
When the system boots, we check that the hardware supports lapic
tsc-deadline timer by checking CPUID.01H:ECX.TSC_Deadline[bit 24]. If
support is missing, we output an error message and panic the hypervisor.
If supported, we register the timer interrupt callback that raises a
timer softirq on each logical CPU and set the lapic timer mode to
tsc-deadline timer mode by writing the local APIC LVT register.
Data Structures and APIs
************************
.. note:: API link to hv_timer and per_cpu_timer structs in include/arch/x86/timer.h
And to the function APIs there too.
Before adding a timer, we must initialize the timer with
*initialize_timer*. The processor generates a timer interrupt when the
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
structure; it will not program the ``IA32_TSC_DEADLINE_MSR`` to generate
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
timer_list. Before calling the expired timer callback handler, it will
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::
Only call initialize_timer only once for each timer.
Don't call add_timer or del_timer in the timer callback function.