diff --git a/kernel-src/arch/x86-64/apic.c b/kernel-src/arch/x86-64/apic.c index 881f6368..176c78e9 100644 --- a/kernel-src/arch/x86-64/apic.c +++ b/kernel-src/arch/x86-64/apic.c @@ -3,6 +3,8 @@ #include #include #include +#include +#include #define IOAPIC_REG_ID 0 #define IOAPIC_REG_ENTRYCOUNT 1 @@ -46,6 +48,20 @@ typedef struct { uint32_t intbase; } __attribute__((packed)) ioentry_t; +typedef struct { + listheader_t header; + uint8_t acpiid; + uint8_t lapicid; + uint32_t flags; +} __attribute__((packed)) lapicentry_t; + +typedef struct { + listheader_t header; + uint8_t acpiid; + uint16_t flags; + uint8_t lint; +} __attribute__((packed)) lapicnmientry_t; + typedef struct { void *addr; int base; @@ -61,6 +77,8 @@ static void *lapicaddr; static size_t overridecount; static size_t iocount; +static size_t lapiccount; +static size_t lapicnmicount; static inline listheader_t *getnext(listheader_t *header) { uintptr_t ptr = (uintptr_t)header; @@ -94,6 +112,16 @@ static int getcount(int type) { return count; } +static void writelapic(int reg, uint32_t v) { + volatile uint32_t *ptr = (void *)((uintptr_t)lapicaddr + reg); + *ptr = v; +} + +static uint32_t readlapic(int reg) { + volatile uint32_t *ptr = (void *)((uintptr_t)lapicaddr + reg); + return *ptr; +} + static uint32_t readioapic(void *ioapic, int reg) { volatile uint32_t *apic = ioapic; *apic = reg & 0xff; @@ -118,8 +146,48 @@ static void writeiored(void *ioapic, uint8_t entry, uint8_t vector, uint8_t deli writeioapic(ioapic, 0x11 + entry * 2, (uint32_t)dest << 24); } +static void spurious(isr_t *self, context_t *ctx) { + __assert(!"Spurious interrupt"); +} + +static void nmi(isr_t *self, context_t *ctx) { + __assert(!"NMI"); +} + void arch_apic_initap() { + writelapic(APIC_LVT_THERMAL, LVT_MASK); + writelapic(APIC_LVT_PERFORMANCE, LVT_MASK); + writelapic(APIC_LVT_LINT0, LVT_MASK); + writelapic(APIC_LVT_LINT1, LVT_MASK); + writelapic(APIC_LVT_ERROR, LVT_MASK); + writelapic(APIC_LVT_TIMER, LVT_MASK); + interrupt_register(0xff, spurious, NULL, 0); // TODO when priorities are decided on, change it here + writelapic(APIC_REG_SPURIOUS, 0x1FF); + + _cpu()->id = readlapic(APIC_REG_ID) >> 24; + + // get the acpi id for the local nmi sources + + for (size_t i = 0; i < lapiccount; ++i) { + lapicentry_t *current = getentry(ACPI_MADT_TYPE_LAPIC, i); + if (_cpu()->id == current->lapicid) { + _cpu()->acpiid = current->acpiid; + break; + } + } + + printf("processor id: %lu (APIC) %lu (ACPI)\n", _cpu()->id, _cpu()->acpiid); + + isr_t *nmiisr = interrupt_allocate(nmi, NULL, 0); // TODO when priorities are decided on, change it here + __assert(nmiisr); + for (size_t i = 0; i < lapicnmicount; ++i) { + lapicnmientry_t* current = getentry(ACPI_MADT_TYPE_LANMI, i); + if (current->acpiid == _cpu()->acpiid || current->acpiid == 0xff) + writelapic(APIC_LVT_LINT0 + 0x10 * current->lint, (nmiisr->id & 0xff) | LVT_DELIVERY_NMI | (current->flags << 12)); + } + + // TODO enable interrupts here } void arch_apic_init() { @@ -131,6 +199,8 @@ void arch_apic_init() { overridecount = getcount(ACPI_MADT_TYPE_OVERRIDE); iocount = getcount(ACPI_MADT_TYPE_IOAPIC); + lapiccount = getcount(ACPI_MADT_TYPE_LAPIC); + lapicnmicount = getcount(ACPI_MADT_TYPE_LANMI); // map LAPIC to virtual memory @@ -162,4 +232,6 @@ void arch_apic_init() { writeiored(ioapics[i].addr, j - ioapics[i].base, 0xfe, 0, 0, 0, 0, 1, 0); } + + // FIXME limine does this already but just in case the PIC should be masked } diff --git a/kernel-src/arch/x86-64/main.c b/kernel-src/arch/x86-64/main.c index b0c45196..ef786a40 100644 --- a/kernel-src/arch/x86-64/main.c +++ b/kernel-src/arch/x86-64/main.c @@ -28,5 +28,6 @@ void kernel_entry() { alloc_init(); arch_acpi_init(); arch_apic_init(); + arch_apic_initap(); __assert(!"kernel entry end"); } diff --git a/kernel-src/include/x86-64/arch/apic.h b/kernel-src/include/x86-64/arch/apic.h index bb3e9a6a..9d2b6f53 100644 --- a/kernel-src/include/x86-64/arch/apic.h +++ b/kernel-src/include/x86-64/arch/apic.h @@ -2,5 +2,6 @@ #define _APIC_H void arch_apic_init(); +void arch_apic_initap(); #endif diff --git a/kernel-src/include/x86-64/arch/cpu.h b/kernel-src/include/x86-64/arch/cpu.h index 509eeb7b..1a04e754 100644 --- a/kernel-src/include/x86-64/arch/cpu.h +++ b/kernel-src/include/x86-64/arch/cpu.h @@ -15,6 +15,7 @@ typedef struct { long id; isr_t isr[MAX_ISR_COUNT]; vmmcontext_t *vmmctx; + int acpiid; } cpu_t; static inline cpu_t *_cpu() {