-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathlapic_timer.c
48 lines (37 loc) · 1.2 KB
/
lapic_timer.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <kernel.h>
static const uint64_t quantum = 100;
void lapic_spurious([[maybe_unused]] uint8_t isr, [[maybe_unused]] uint64_t errorcode, [[maybe_unused]] uint64_t irq, void* opaque)
{
return;
}
void init_lapic_timer()
{
if (quantum == 0) {
return;
}
register_interrupt_handler(IRQ7, lapic_spurious, dev_zero, NULL);
register_interrupt_handler(IRQ16, timer_callback, dev_zero, NULL);
// Divisor = 16
apic_write(APIC_TMRDIV, 0x3);
datetime_t t;
get_datetime(&t);
uint8_t secs = t.second;
// Busy-loop to calculate number of APIC timer ticks per second
kprintf("APIC timer calibration... ");
while (t.second == secs) {
get_datetime(&t);
}
secs = t.second;
apic_write(APIC_TMRINITCNT, 0xFFFFFFFF);
while (t.second == secs) {
get_datetime(&t);
}
kprintf("Done!\n");
uint64_t ticks_per_second = 0xFFFFFFFF - apic_read(APIC_TMRCURRCNT);
uint64_t ticks_per_quantum = ticks_per_second / quantum;
add_random_entropy(ticks_per_second);
dprintf("ticks_per_second = %d; ticks_per_quantum = %d; quantum = %d\n", ticks_per_second, ticks_per_quantum, quantum);
apic_write(APIC_TMRINITCNT, ticks_per_quantum);
apic_write(APIC_LVT_TMR, IRQ16 | TMR_PERIODIC);
apic_write(APIC_TMRDIV, 0x03);
}