Skip to content

Commit

Permalink
kern: Support systems with non working PIT
Browse files Browse the repository at this point in the history
  • Loading branch information
mintsuki committed Nov 26, 2024
1 parent 701d219 commit 3d1fd00
Showing 1 changed file with 26 additions and 11 deletions.
37 changes: 26 additions & 11 deletions kernel/modules/x86/apic/apic.v
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ module apic
import x86.kio
import x86.msr
import x86.cpu.local as cpulocal
import x86.cpu
import time

const lapic_reg_icr0 = 0x300
Expand Down Expand Up @@ -69,24 +70,38 @@ pub fn lapic_timer_stop() {
pub fn lapic_timer_calibrate(mut cpu_local cpulocal.Local) {
lapic_timer_stop()

samples := u64(0xfffff)

lapic_write(apic.lapic_reg_timer, (1 << 16) | 0xff) // Vector 0xff, masked
lapic_write(apic.lapic_reg_timer_div, 0)
lapic_write(apic.lapic_reg_timer_div, 0b1011) // Timer divisor = 1

cpuid_success, _, _, ecx, _ := cpu.cpuid(0x15, 0)
if cpuid_success == true && ecx != 0 {
cpu_local.lapic_timer_freq = ecx
return
}

time.pit_set_reload_value(0xffff)
mut samples := u64(16)
for {
time.pit_set_reload_value(0xfff0)

initial_pit_tick := u64(time.pit_get_current_count())
initial_pit_tick := u64(time.pit_get_current_count())

lapic_write(apic.lapic_reg_timer_initcnt, u32(samples))
lapic_write(apic.lapic_reg_timer_initcnt, u32(samples))

for lapic_read(apic.lapic_reg_timer_curcnt) != 0 {}
for lapic_read(apic.lapic_reg_timer_curcnt) != 0 {}

final_pit_tick := u64(time.pit_get_current_count())
final_pit_tick := u64(time.pit_get_current_count())

pit_ticks := initial_pit_tick - final_pit_tick
pit_ticks := initial_pit_tick - final_pit_tick

cpu_local.lapic_timer_freq = (samples / pit_ticks) * time.pit_dividend
if pit_ticks < 0x4000 {
samples *= 2
continue
}

cpu_local.lapic_timer_freq = (samples / pit_ticks) * time.pit_dividend

break
}

lapic_timer_stop()
}
Expand All @@ -97,7 +112,7 @@ pub fn lapic_timer_oneshot(mut cpu_local cpulocal.Local, vec u8, us u64) {
ticks := us * (cpu_local.lapic_timer_freq / 1000000)

lapic_write(apic.lapic_reg_timer, vec)
lapic_write(apic.lapic_reg_timer_div, 0)
lapic_write(apic.lapic_reg_timer_div, 0b1011)
lapic_write(apic.lapic_reg_timer_initcnt, u32(ticks))
}

Expand Down

0 comments on commit 3d1fd00

Please sign in to comment.