diff --git a/arch/x86_64/apic.c b/arch/x86_64/apic.c index 2540c4b..5277d73 100644 --- a/arch/x86_64/apic.c +++ b/arch/x86_64/apic.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -95,17 +96,22 @@ void lapic_init(struct local_apic* lapic) { clock_spin_ns(10'000'000); lapic->ticks_per_10ms = 0xFFFF'FFFF - lapic_read_reg(lapic, APIC_REG_CCR); - lapic_write_reg(lapic, APIC_REG_LVT_TR, IDT_IPI_RESCHED | 0x20000); - lapic_write_reg(lapic, APIC_REG_ICR_TIMER, lapic->ticks_per_10ms); + lapic_write_reg(lapic, APIC_REG_LVT_TR, mmio_field(APIC_LVT_TR_VECTOR, IDT_TIMER)); + lapic_write_reg(lapic, APIC_REG_ICR_TIMER, 0); +} + +void arch_timer_program(uint64_t deadline_ns) { + struct local_apic* lapic = &percpu_ref(arch_data)->lapic; + const uint64_t now = clock_get_elapsed_ns(); + const uint64_t delta = MIN(deadline_ns > now ? deadline_ns - now : 0, 1'000'000'000); + const uint64_t ticks = delta * lapic->ticks_per_10ms / 10'000'000; + lapic_write_reg(lapic, APIC_REG_ICR_TIMER, MIN(MAX(ticks, 1), 0xFFFF'FFFF)); } void lapic_eoi(struct local_apic* lapic) { lapic_write_reg(lapic, APIC_REG_EOI, 0); } -constexpr uint64_t the_icr = - mmio_field(APIC_ICR_VECTOR, 128) | mmio_field(APIC_ICR_DELIVERY_MODE, APIC_DELIVERY_STARTUP); - void lapic_send_ipi( struct local_apic* lapic, uint32_t target, diff --git a/include/arch/timer.h b/include/arch/timer.h new file mode 100644 index 0000000..dcc2312 --- /dev/null +++ b/include/arch/timer.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +void arch_timer_program(uint64_t deadline_ns);