SMP and timer interrupts
This commit is contained in:
@@ -1,8 +1,11 @@
|
||||
#include <amd64/apic.h>
|
||||
#include <amd64/msr-index.h>
|
||||
#include <amd64/msr.h>
|
||||
#include <libk/std.h>
|
||||
#include <limine/requests.h>
|
||||
#include <sys/debug.h>
|
||||
#include <sys/mm.h>
|
||||
#include <sys/time.h>
|
||||
#include <uacpi/acpi.h>
|
||||
#include <uacpi/status.h>
|
||||
#include <uacpi/tables.h>
|
||||
@@ -11,12 +14,22 @@
|
||||
#define IOAPICS_MAX 24
|
||||
#define INTERRUPT_SRC_OVERRIDES_MAX 24
|
||||
|
||||
#define LAPIC_ID 0x20 /* ID */
|
||||
#define LAPIC_EOI 0xB0 /* End of interrupt */
|
||||
#define LAPIC_SIVR 0xF0 /* Spurious interrupt vector register */
|
||||
#define LAPIC_ICR 0x300
|
||||
#define LAPIC_LVTTR 0x320 /* LVT timer register */
|
||||
#define LAPIC_TIMICT 0x380 /* Initial count register */
|
||||
#define LAPIC_TIMCCT 0x390 /* Current count register */
|
||||
#define LAPIC_DCR 0x3E0 /* Divide config register */
|
||||
|
||||
static struct acpi_madt_ioapic apics[IOAPICS_MAX];
|
||||
/* clang-format off */
|
||||
static struct acpi_madt_interrupt_source_override intr_src_overrides[INTERRUPT_SRC_OVERRIDES_MAX];
|
||||
/* clang-format on */
|
||||
static size_t ioapic_entries = 0;
|
||||
static size_t intr_src_override_entries = 0;
|
||||
static uintptr_t lapic_mmio_base = 0;
|
||||
|
||||
extern void amd64_spin (void);
|
||||
|
||||
@@ -37,13 +50,13 @@ static struct acpi_madt_ioapic* amd64_ioapic_find (uint8_t irq) {
|
||||
for (size_t i = 0; i < ioapic_entries; i++) {
|
||||
apic = &apics[i];
|
||||
uint32_t version = amd64_ioapic_read ((uintptr_t)hhdm->offset + (uintptr_t)apic->address, 1);
|
||||
uint32_t max = (version >> 16);
|
||||
uint32_t max = ((version >> 16) & 0xFF);
|
||||
|
||||
if ((apic->gsi_base <= irq) && ((apic->gsi_base + max) > irq))
|
||||
break;
|
||||
if ((irq >= apic->gsi_base) && (irq <= (apic->gsi_base + max)))
|
||||
return apic;
|
||||
}
|
||||
|
||||
return apic;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void amd64_ioapic_route_irq (uint8_t vec, uint8_t irq, uint64_t flags, uint64_t lapic_id) {
|
||||
@@ -65,7 +78,12 @@ void amd64_ioapic_route_irq (uint8_t vec, uint8_t irq, uint64_t flags, uint64_t
|
||||
if (found_override) {
|
||||
uint8_t polarity = ((override->flags & 0x03) == 0x03) ? 1 : 0;
|
||||
uint8_t mode = (((override->flags >> 2) & 0x03) == 0x03) ? 1 : 0;
|
||||
calc_flags = (lapic_id << 56) | (mode << 15) | (polarity << 14) | (vec & 0xFF) | flags;
|
||||
calc_flags |= (uint64_t)mode << 15;
|
||||
calc_flags |= (uint64_t)polarity << 13;
|
||||
|
||||
calc_flags |= flags;
|
||||
} else {
|
||||
calc_flags |= flags;
|
||||
}
|
||||
|
||||
apic = amd64_ioapic_find (irq);
|
||||
@@ -137,7 +155,7 @@ void amd64_ioapic_init (void) {
|
||||
struct acpi_madt_ioapic* ioapic = (struct acpi_madt_ioapic*)current;
|
||||
mm_map_kernel_page ((uintptr_t)ioapic->address,
|
||||
(uintptr_t)hhdm->offset + (uintptr_t)ioapic->address,
|
||||
MM_PG_USER | MM_PG_RW);
|
||||
MM_PG_PRESENT | MM_PG_RW);
|
||||
apics[ioapic_entries++] = *ioapic;
|
||||
} break;
|
||||
case ACPI_MADT_ENTRY_TYPE_INTERRUPT_SOURCE_OVERRIDE: {
|
||||
@@ -150,3 +168,60 @@ void amd64_ioapic_init (void) {
|
||||
current = (struct acpi_entry_hdr*)((uintptr_t)current + current->length);
|
||||
}
|
||||
}
|
||||
|
||||
static uintptr_t amd64_lapic_base (void) { return lapic_mmio_base; }
|
||||
|
||||
static void amd64_lapic_write (uint32_t reg, uint32_t value) {
|
||||
*(volatile uint32_t*)(amd64_lapic_base () + reg) = value;
|
||||
}
|
||||
|
||||
static uint32_t amd64_lapic_read (uint32_t reg) {
|
||||
return *(volatile uint32_t*)(amd64_lapic_base () + reg);
|
||||
}
|
||||
|
||||
uint32_t amd64_lapic_id (void) { return amd64_lapic_read (LAPIC_ID) >> 24; }
|
||||
|
||||
void amd64_lapic_eoi (void) { amd64_lapic_write (LAPIC_EOI, 0); }
|
||||
|
||||
void amd64_lapic_tick (uint32_t tick) { amd64_lapic_write (LAPIC_TIMICT, tick); }
|
||||
|
||||
static uint32_t amd64_lapic_calibrate (uint32_t us) {
|
||||
amd64_lapic_write (LAPIC_DCR, 0x03);
|
||||
|
||||
amd64_lapic_write (LAPIC_LVTTR, 0x20 | (1 << 16));
|
||||
|
||||
amd64_lapic_write (LAPIC_TIMICT, 0xFFFFFFFF);
|
||||
|
||||
sleep_micro (us);
|
||||
|
||||
uint32_t ticks = 0xFFFFFFFF - amd64_lapic_read (LAPIC_TIMCCT);
|
||||
|
||||
return ticks;
|
||||
}
|
||||
|
||||
static void amd64_lapic_start (uint32_t ticks) {
|
||||
amd64_lapic_write (LAPIC_DCR, 0x03);
|
||||
|
||||
amd64_lapic_write (LAPIC_LVTTR, 0x20 | (1 << 17));
|
||||
|
||||
amd64_lapic_write (LAPIC_TIMICT, ticks);
|
||||
}
|
||||
|
||||
uint64_t amd64_lapic_init (uint32_t us) {
|
||||
struct limine_hhdm_response* hhdm = limine_hhdm_request.response;
|
||||
|
||||
amd64_wrmsr (MSR_APIC_BASE, amd64_rdmsr (MSR_APIC_BASE) | (1 << 11));
|
||||
|
||||
uintptr_t lapic_paddr = amd64_rdmsr (MSR_APIC_BASE) & 0xFFFFF000;
|
||||
lapic_mmio_base = lapic_paddr + (uintptr_t)hhdm->offset;
|
||||
|
||||
mm_map_kernel_page (lapic_paddr, lapic_mmio_base, MM_PG_PRESENT | MM_PG_RW | MM_PD_LOCK);
|
||||
|
||||
amd64_lapic_write (LAPIC_SIVR, 0xFF | (1 << 8));
|
||||
|
||||
uint32_t ticks = amd64_lapic_calibrate (us);
|
||||
|
||||
amd64_lapic_start (ticks);
|
||||
|
||||
return ticks;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user