mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-11-01 15:08:21 +00:00
apic: local apic initialisation
This commit is contained in:
@@ -3,6 +3,8 @@
|
|||||||
#include <kernel/vmm.h>
|
#include <kernel/vmm.h>
|
||||||
#include <arch/mmu.h>
|
#include <arch/mmu.h>
|
||||||
#include <kernel/alloc.h>
|
#include <kernel/alloc.h>
|
||||||
|
#include <kernel/interrupt.h>
|
||||||
|
#include <arch/cpu.h>
|
||||||
|
|
||||||
#define IOAPIC_REG_ID 0
|
#define IOAPIC_REG_ID 0
|
||||||
#define IOAPIC_REG_ENTRYCOUNT 1
|
#define IOAPIC_REG_ENTRYCOUNT 1
|
||||||
@@ -46,6 +48,20 @@ typedef struct {
|
|||||||
uint32_t intbase;
|
uint32_t intbase;
|
||||||
} __attribute__((packed)) ioentry_t;
|
} __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 {
|
typedef struct {
|
||||||
void *addr;
|
void *addr;
|
||||||
int base;
|
int base;
|
||||||
@@ -61,6 +77,8 @@ static void *lapicaddr;
|
|||||||
|
|
||||||
static size_t overridecount;
|
static size_t overridecount;
|
||||||
static size_t iocount;
|
static size_t iocount;
|
||||||
|
static size_t lapiccount;
|
||||||
|
static size_t lapicnmicount;
|
||||||
|
|
||||||
static inline listheader_t *getnext(listheader_t *header) {
|
static inline listheader_t *getnext(listheader_t *header) {
|
||||||
uintptr_t ptr = (uintptr_t)header;
|
uintptr_t ptr = (uintptr_t)header;
|
||||||
@@ -94,6 +112,16 @@ static int getcount(int type) {
|
|||||||
return count;
|
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) {
|
static uint32_t readioapic(void *ioapic, int reg) {
|
||||||
volatile uint32_t *apic = ioapic;
|
volatile uint32_t *apic = ioapic;
|
||||||
*apic = reg & 0xff;
|
*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);
|
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() {
|
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() {
|
void arch_apic_init() {
|
||||||
@@ -131,6 +199,8 @@ void arch_apic_init() {
|
|||||||
|
|
||||||
overridecount = getcount(ACPI_MADT_TYPE_OVERRIDE);
|
overridecount = getcount(ACPI_MADT_TYPE_OVERRIDE);
|
||||||
iocount = getcount(ACPI_MADT_TYPE_IOAPIC);
|
iocount = getcount(ACPI_MADT_TYPE_IOAPIC);
|
||||||
|
lapiccount = getcount(ACPI_MADT_TYPE_LAPIC);
|
||||||
|
lapicnmicount = getcount(ACPI_MADT_TYPE_LANMI);
|
||||||
|
|
||||||
// map LAPIC to virtual memory
|
// 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);
|
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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,5 +28,6 @@ void kernel_entry() {
|
|||||||
alloc_init();
|
alloc_init();
|
||||||
arch_acpi_init();
|
arch_acpi_init();
|
||||||
arch_apic_init();
|
arch_apic_init();
|
||||||
|
arch_apic_initap();
|
||||||
__assert(!"kernel entry end");
|
__assert(!"kernel entry end");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,5 +2,6 @@
|
|||||||
#define _APIC_H
|
#define _APIC_H
|
||||||
|
|
||||||
void arch_apic_init();
|
void arch_apic_init();
|
||||||
|
void arch_apic_initap();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ typedef struct {
|
|||||||
long id;
|
long id;
|
||||||
isr_t isr[MAX_ISR_COUNT];
|
isr_t isr[MAX_ISR_COUNT];
|
||||||
vmmcontext_t *vmmctx;
|
vmmcontext_t *vmmctx;
|
||||||
|
int acpiid;
|
||||||
} cpu_t;
|
} cpu_t;
|
||||||
|
|
||||||
static inline cpu_t *_cpu() {
|
static inline cpu_t *_cpu() {
|
||||||
|
|||||||
Reference in New Issue
Block a user