diff options
| author | Ian Moffett <ian@osmora.org> | 2025-11-18 16:05:25 -0500 |
|---|---|---|
| committer | Ian Moffett <ian@osmora.org> | 2025-11-18 16:05:25 -0500 |
| commit | 0527ef090e4a5ff2dd8dc32170d505c44ee015fa (patch) | |
| tree | e061425468803e33ea9a5e14627f4d51c6ca6f5e /sys/arch/amd64 | |
| parent | 32a88e354f6936ae0e2ab9c564293a09c6d77902 (diff) | |
kern/amd64: lapic: Add Local APIC timer interface
This commit adds an interface to perform a oneshot operation with the
Local APIC timer as well as providing a stub interrupt service routine
for it.
Signed-off-by: Ian Moffett <ian@osmora.org>
Diffstat (limited to 'sys/arch/amd64')
| -rw-r--r-- | sys/arch/amd64/cpu/idt.S | 9 | ||||
| -rw-r--r-- | sys/arch/amd64/cpu/lapic.c | 24 |
2 files changed, 33 insertions, 0 deletions
diff --git a/sys/arch/amd64/cpu/idt.S b/sys/arch/amd64/cpu/idt.S index c430a44..729d958 100644 --- a/sys/arch/amd64/cpu/idt.S +++ b/sys/arch/amd64/cpu/idt.S @@ -306,6 +306,15 @@ page_fault: jmp 1b hlt + .globl lapic_tmr_isr +lapic_tmr_isr: + KFENCE + push_frame 0x81 + nop + pop_frame 0x81 + KFENCE + iretq + .section .data .align 8 IDT: diff --git a/sys/arch/amd64/cpu/lapic.c b/sys/arch/amd64/cpu/lapic.c index acf2573..076ddd3 100644 --- a/sys/arch/amd64/cpu/lapic.c +++ b/sys/arch/amd64/cpu/lapic.c @@ -43,6 +43,7 @@ #include <md/i8254.h> #include <md/cpuid.h> #include <md/msr.h> +#include <md/idt.h> #define dtrace(fmt, ...) trace("lapic: " fmt, ##__VA_ARGS__) @@ -82,6 +83,7 @@ /* Accessed via RDMSR/WRMSR */ #define X2APIC_MSR_BASE 0x00000800 +extern void lapic_tmr_isr(void); static struct acpi_madt *madt; /* @@ -337,6 +339,17 @@ lapic_enable(struct mcb *mcb) lapic_write(mcb, LAPIC_REG_SVR, svr | 0xFF); } +static void +lapic_timer_oneshot(struct mcb *mcb, size_t count) +{ + if (mcb == NULL) { + return; + } + + lapic_tmr_enable(mcb, LAPIC_TMR_ONESHOT); + lapic_write(mcb, LAPIC_REG_TICR, count); +} + uint32_t lapic_read_id(struct mcb *mcb) { @@ -350,6 +363,16 @@ lapic_read_id(struct mcb *mcb) } void +lapic_oneshot_usec(struct mcb *mcb, size_t usec) +{ + if (mcb == NULL) { + return; + } + + lapic_timer_oneshot(mcb, mcb->lapic_tmr_freq / 1000000); +} + +void lapic_init(void) { struct cpu_info *ci; @@ -375,4 +398,5 @@ lapic_init(void) lapic_enable(mcb); mcb->lapic_tmr_freq = lapic_tmr_clbr(mcb); + idt_set_gate(LAPIC_TMR_VEC, INT_GATE, (uintptr_t)lapic_tmr_isr, 0); } |
