Aufgabe 5: Zeitscheiben
The Local APIC of each processor core has a high-resolution timer which can be utilized to generate interrupts. Unfortunately, the timer's frequency has not been standardized and may vary across different processor generations. Therefore it is necessary to calibrate it using another time source, like the Programmable Interrupt Timer (PIT) for example.
Programming the Timer
There are four memory mapped 32-bit registers used to program the LAPIC's timer. Below is a table showing each register with its address in physical memory:
Address | Register Name |
---|---|
0xfee00320 | LVT Timer Register (aka Timer Control Register) |
0xfee00380 | Initial Count Register (*ICR*) |
0xfee00390 | Current Count Register (*CCR*) |
0xfee003e0 | Divide Configuration Register |
The ICR is used to program the timer's initial value from which it will count down to zero. The CCR, on the other hand, can be read to get the timer's current value. In order to reset the timer, effectively stopping it, you can set the ICR to 0.
The Control Register, as well as the Divider Configuration Register are used to control the timer's behavior. The Control Register comprises the following control bits:
Bit(s) | Value & Meaning |
---|---|
31-19 | *(reserviert)* |
18-17 | Mode of Operation |
0 one-shot (stops at 0) | |
1 periodic (restarts the timer, using the ICR's value each time the timer reaches 0)) | |
2 TSC-Deadline (Compare with an absolute time via a special register, ICR and CCR are ignored) | |
3 *(reserved)* | |
16 | Mask Interrupts |
0 generate interrupts | |
1 do not generate interrupts | |
15-13 | *(reserviert)* |
12 | Interrupt Status (read-only) |
0 idle (no interrupts is pending) | |
1 interrupt pending | |
7-0 | interrupt vector used when delivering interrupts |
The Divider Configuration Register is used to control the timer's tick rate. We already have implemented the mapping from dividers to their respective register values for you. You can simply call the function LAPIC::Timer::getClockDiv() to retrieve it. A detailed explanation of how the mapping works can be found in the Intel Software Developer's Manual.