Document amd64 platform-specific code

This commit is contained in:
2025-12-30 16:50:15 +01:00
parent 4f4f5c3d2f
commit 34f1e0ba30
17 changed files with 171 additions and 19 deletions

View File

@@ -37,6 +37,7 @@
#define IDT_ENTRIES_MAX 256
/// 64-bit <IDT entry structure: https://wiki.osdev.org/Interrupt_Descriptor_Table
struct idt_entry {
uint16_t intrlow;
uint16_t kernel_cs;
@@ -52,16 +53,22 @@ struct idt {
uint64_t base;
} PACKED;
/** @cond DOXYGEN_IGNORE */
ALIGNED (16) static volatile struct idt_entry idt_entries[IDT_ENTRIES_MAX];
/** @endcond */
static volatile struct idt idt;
/** @cond DOXYGEN_IGNORE */
extern void amd64_spin (void);
/** @endcond */
/* Remaps and disables old 8259 PIC, since we'll be using APIC. */
/// Remaps and disables old 8259 PIC, since we'll be using APIC.
static void amd64_init_pic (void) {
/** @cond DOXYGEN_IGNORE */
#define IO_OP(fn, ...) \
fn (__VA_ARGS__); \
amd64_io_wait ()
/** @endcond */
IO_OP (amd64_io_outb, PIC1_CMD, (ICW1_INIT | ICW1_ICW4));
IO_OP (amd64_io_outb, PIC2_CMD, (ICW1_INIT | ICW1_ICW4));
@@ -82,6 +89,7 @@ static void amd64_init_pic (void) {
#undef IO_OP
}
/// Set IDT entry
static void amd64_idt_set (volatile struct idt_entry* ent, uint64_t handler, uint8_t flags,
uint8_t ist) {
ent->intrlow = (handler & 0xFFFF);
@@ -93,14 +101,18 @@ static void amd64_idt_set (volatile struct idt_entry* ent, uint64_t handler, uin
ent->resv = 0;
}
/// Load the IDT
void amd64_load_idt (void) { __asm__ volatile ("lidt %0" ::"m"(idt)); }
/// Initialize IDT entries
static void amd64_idt_init (void) {
memset ((void*)idt_entries, 0, sizeof (idt_entries));
/** @cond DOXYGEN_IGNORE */
#define IDT_ENTRY(n, ist) \
extern void amd64_intr##n (void); \
amd64_idt_set (&idt_entries[(n)], (uint64_t)&amd64_intr##n, 0x8E, (ist))
/** @endcond */
/* clang-format off */
IDT_ENTRY (0, 0); IDT_ENTRY (1, 0); IDT_ENTRY (2, 0); IDT_ENTRY (3, 0);
IDT_ENTRY (4, 0); IDT_ENTRY (5, 0); IDT_ENTRY (6, 0); IDT_ENTRY (7, 0);
@@ -126,6 +138,13 @@ static void amd64_idt_init (void) {
amd64_load_idt ();
}
/**
* @brief Handle CPU exception and dump registers. If incoming CS has CPL3, kill the
* process.
*
* @param regs
* saved registers
*/
static void amd64_intr_exception (struct saved_regs* regs) {
DEBUG ("cpu exception %lu (%lu)\n", regs->trap, regs->error);
@@ -154,6 +173,7 @@ static void amd64_intr_exception (struct saved_regs* regs) {
}
}
/// Handle incoming interrupt, dispatch IRQ handlers.
void amd64_intr_handler (void* stack_ptr) {
struct saved_regs* regs = stack_ptr;
@@ -176,6 +196,7 @@ void amd64_intr_handler (void* stack_ptr) {
}
}
/// Initialize interrupts
void amd64_intr_init (void) {
amd64_init_pic ();
amd64_idt_init ();
@@ -183,17 +204,20 @@ void amd64_intr_init (void) {
/* Aux. */
/// Save RFLAGS of the current CPU
static uint64_t amd64_irq_save_flags (void) {
uint64_t rflags;
__asm__ volatile ("pushfq; cli; popq %0" : "=r"(rflags)::"memory", "cc");
return rflags;
}
/// Restore interrupts (IF bit) from RFLAGS
static void amd64_irq_restore_flags (uint64_t rflags) {
if (rflags & (1ULL << 9))
__asm__ volatile ("sti");
}
/// Save current interrupt state
void irq_save (void) {
/* before smp init. */
if (thiscpu == NULL)
@@ -204,6 +228,7 @@ void irq_save (void) {
thiscpu->irq_ctx.rflags = amd64_irq_save_flags ();
}
/// Restore interrupt state
void irq_restore (void) {
/* before smp init. */
if (thiscpu == NULL)
@@ -214,6 +239,7 @@ void irq_restore (void) {
amd64_irq_restore_flags (thiscpu->irq_ctx.rflags);
}
/// Map custom IRQ mappings to legacy IRQs
uint8_t amd64_resolve_irq (uint8_t irq) {
static const uint8_t mappings[] = {
[SCHED_PREEMPT_TIMER] = 0,