summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Moffett <ian@osmora.org>2025-11-18 16:05:25 -0500
committerIan Moffett <ian@osmora.org>2025-11-18 16:05:25 -0500
commit0527ef090e4a5ff2dd8dc32170d505c44ee015fa (patch)
treee061425468803e33ea9a5e14627f4d51c6ca6f5e
parent32a88e354f6936ae0e2ab9c564293a09c6d77902 (diff)
kern/amd64: lapic: Add Local APIC timer interfacedev
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>
-rw-r--r--sys/arch/amd64/cpu/idt.S9
-rw-r--r--sys/arch/amd64/cpu/lapic.c24
-rw-r--r--sys/inc/arch/amd64/lapic.h7
3 files changed, 40 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);
}
diff --git a/sys/inc/arch/amd64/lapic.h b/sys/inc/arch/amd64/lapic.h
index 35ba778..d22a560 100644
--- a/sys/inc/arch/amd64/lapic.h
+++ b/sys/inc/arch/amd64/lapic.h
@@ -31,6 +31,7 @@
#define _MACHINE_LAPIC_H_ 1
#include <sys/types.h>
+#include <lib/stdbool.h>
#include <mu/cpu.h>
#define LAPIC_TMR_VEC 0x81
@@ -91,6 +92,12 @@ struct lapic_ipi {
};
/*
+ * Put the local APIC timer in one shot mode and fire it
+ * off
+ */
+void lapic_oneshot_usec(struct mcb *mcb, size_t usec);
+
+/*
* Read the current local APIC id
*/
uint32_t lapic_read_id(struct mcb *mcb);