Clean up IOAPIC and LAPIC implementations
All checks were successful
Build documentation / build-and-deploy (push) Successful in 33s
All checks were successful
Build documentation / build-and-deploy (push) Successful in 33s
This commit is contained in:
@@ -8,11 +8,11 @@ void app_main (void) {
|
|||||||
uintptr_t out_paddr;
|
uintptr_t out_paddr;
|
||||||
int mem_rid = m_proc_create_resource_mem (16, RV_PRIVATE, &out_paddr);
|
int mem_rid = m_proc_create_resource_mem (16, RV_PRIVATE, &out_paddr);
|
||||||
|
|
||||||
m_proc_map (out_paddr, M_PROC_MAP_BASE, 16, PM_PRESENT | PM_RW | PM_USER);
|
/* m_proc_map (out_paddr, M_PROC_MAP_BASE, 16, PM_PRESENT | PM_RW | PM_USER); */
|
||||||
|
|
||||||
memset ((void*)M_PROC_MAP_BASE, 0, M_PAGE_SIZE * 16);
|
/* memset ((void*)M_PROC_MAP_BASE, 0, M_PAGE_SIZE * 16); */
|
||||||
|
|
||||||
m_proc_unmap (M_PROC_MAP_BASE, 16);
|
/* m_proc_unmap (M_PROC_MAP_BASE, 16); */
|
||||||
|
|
||||||
m_proc_drop_resource (mem_rid);
|
/* m_proc_drop_resource (mem_rid); */
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <amd64/msr.h>
|
#include <amd64/msr.h>
|
||||||
#include <libk/std.h>
|
#include <libk/std.h>
|
||||||
#include <limine/requests.h>
|
#include <limine/requests.h>
|
||||||
|
#include <sync/spin_lock.h>
|
||||||
#include <sys/debug.h>
|
#include <sys/debug.h>
|
||||||
#include <sys/mm.h>
|
#include <sys/mm.h>
|
||||||
#include <sys/spin.h>
|
#include <sys/spin.h>
|
||||||
@@ -33,8 +34,14 @@
|
|||||||
/* Divide config register */
|
/* Divide config register */
|
||||||
#define LAPIC_DCR 0x3E0
|
#define LAPIC_DCR 0x3E0
|
||||||
|
|
||||||
|
struct ioapic {
|
||||||
|
struct acpi_madt_ioapic table_data;
|
||||||
|
spin_lock_t lock;
|
||||||
|
uintptr_t mmio_base;
|
||||||
|
};
|
||||||
|
|
||||||
/* Table of IOAPICS */
|
/* Table of IOAPICS */
|
||||||
static struct acpi_madt_ioapic apics[IOAPICS_MAX];
|
static struct ioapic ioapics[IOAPICS_MAX];
|
||||||
/* Table of interrupt source overrides */
|
/* Table of interrupt source overrides */
|
||||||
/* clang-format off */
|
/* clang-format off */
|
||||||
static struct acpi_madt_interrupt_source_override intr_src_overrides[INTERRUPT_SRC_OVERRIDES_MAX];
|
static struct acpi_madt_interrupt_source_override intr_src_overrides[INTERRUPT_SRC_OVERRIDES_MAX];
|
||||||
@@ -43,33 +50,39 @@ static struct acpi_madt_interrupt_source_override intr_src_overrides[INTERRUPT_S
|
|||||||
static size_t ioapic_entries = 0;
|
static size_t ioapic_entries = 0;
|
||||||
/* Count of actual interrupt source overrides */
|
/* Count of actual interrupt source overrides */
|
||||||
static size_t intr_src_override_entries = 0;
|
static size_t intr_src_override_entries = 0;
|
||||||
/* Local APIC MMIO base address. It comes from MSR_APIC_BASE */
|
|
||||||
static uintptr_t lapic_mmio_base = 0;
|
static uint64_t lapic_ticks;
|
||||||
|
|
||||||
/* Read IOAPIC */
|
/* Read IOAPIC */
|
||||||
static uint32_t amd64_ioapic_read (uintptr_t vaddr, uint32_t reg) {
|
static uint32_t amd64_ioapic_read (struct ioapic* ioapic, uint32_t reg) {
|
||||||
*(volatile uint32_t*)vaddr = reg;
|
spin_lock (&ioapic->lock);
|
||||||
return *(volatile uint32_t*)(vaddr + 0x10);
|
*(volatile uint32_t*)ioapic->mmio_base = reg;
|
||||||
|
uint32_t ret = *(volatile uint32_t*)(ioapic->mmio_base + 0x10);
|
||||||
|
spin_unlock (&ioapic->lock);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write IOAPIC */
|
/* Write IOAPIC */
|
||||||
static void amd64_ioapic_write (uintptr_t vaddr, uint32_t reg, uint32_t value) {
|
static void amd64_ioapic_write (struct ioapic* ioapic, uint32_t reg, uint32_t value) {
|
||||||
*(volatile uint32_t*)vaddr = reg;
|
spin_lock (&ioapic->lock);
|
||||||
*(volatile uint32_t*)(vaddr + 0x10) = value;
|
*(volatile uint32_t*)ioapic->mmio_base = reg;
|
||||||
|
*(volatile uint32_t*)(ioapic->mmio_base + 0x10) = value;
|
||||||
|
spin_unlock (&ioapic->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find an IOAPIC corresposting to provided IRQ */
|
/* Find an IOAPIC corresposting to provided IRQ */
|
||||||
static struct acpi_madt_ioapic* amd64_ioapic_find (uint8_t irq) {
|
static struct ioapic* amd64_ioapic_find (uint8_t irq) {
|
||||||
struct acpi_madt_ioapic* apic = NULL;
|
struct ioapic* ioapic = NULL;
|
||||||
struct limine_hhdm_response* hhdm = limine_hhdm_request.response;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < ioapic_entries; i++) {
|
for (size_t i = 0; i < ioapic_entries; i++) {
|
||||||
apic = &apics[i];
|
ioapic = &ioapics[i];
|
||||||
uint32_t version = amd64_ioapic_read ((uintptr_t)hhdm->offset + (uintptr_t)apic->address, 1);
|
/* uint32_t version = amd64_ioapic_read ((uintptr_t)hhdm->offset +
|
||||||
|
* (uintptr_t)ioapic->table_data.address, 1); */
|
||||||
|
uint32_t version = amd64_ioapic_read (ioapic, 1);
|
||||||
uint32_t max = ((version >> 16) & 0xFF);
|
uint32_t max = ((version >> 16) & 0xFF);
|
||||||
|
|
||||||
if ((irq >= apic->gsi_base) && (irq <= (apic->gsi_base + max)))
|
if ((irq >= ioapic->table_data.gsi_base) && (irq <= (ioapic->table_data.gsi_base + max)))
|
||||||
return apic;
|
return ioapic;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -85,10 +98,9 @@ static struct acpi_madt_ioapic* amd64_ioapic_find (uint8_t irq) {
|
|||||||
* lapic_id - Local APIC that will receive the interrupt.
|
* lapic_id - Local APIC that will receive the interrupt.
|
||||||
*/
|
*/
|
||||||
void amd64_ioapic_route_irq (uint8_t vec, uint8_t irq, uint64_t flags, uint64_t lapic_id) {
|
void amd64_ioapic_route_irq (uint8_t vec, uint8_t irq, uint64_t flags, uint64_t lapic_id) {
|
||||||
struct acpi_madt_ioapic* apic = NULL;
|
struct ioapic* ioapic = NULL;
|
||||||
struct acpi_madt_interrupt_source_override* override;
|
struct acpi_madt_interrupt_source_override* override;
|
||||||
bool found_override = false;
|
bool found_override = false;
|
||||||
struct limine_hhdm_response* hhdm = limine_hhdm_request.response;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < intr_src_override_entries; i++) {
|
for (size_t i = 0; i < intr_src_override_entries; i++) {
|
||||||
override = &intr_src_overrides[i];
|
override = &intr_src_overrides[i];
|
||||||
@@ -111,52 +123,15 @@ void amd64_ioapic_route_irq (uint8_t vec, uint8_t irq, uint64_t flags, uint64_t
|
|||||||
calc_flags |= flags;
|
calc_flags |= flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
apic = amd64_ioapic_find (irq);
|
ioapic = amd64_ioapic_find (irq);
|
||||||
|
|
||||||
if (apic == NULL)
|
if (ioapic == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uint32_t irq_reg = ((irq - apic->gsi_base) * 2) + 0x10;
|
uint32_t irq_reg = ((irq - ioapic->table_data.gsi_base) * 2) + 0x10;
|
||||||
|
|
||||||
amd64_ioapic_write ((uintptr_t)hhdm->offset + (uintptr_t)apic->address, irq_reg,
|
amd64_ioapic_write (ioapic, irq_reg + 1, (uint32_t)(calc_flags >> 32));
|
||||||
(uint32_t)calc_flags);
|
amd64_ioapic_write (ioapic, irq_reg, (uint32_t)calc_flags);
|
||||||
|
|
||||||
amd64_ioapic_write ((uintptr_t)hhdm->offset + (uintptr_t)apic->address, irq_reg + 1,
|
|
||||||
(uint32_t)(calc_flags >> 32));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Mask a given IRQ */
|
|
||||||
void amd64_ioapic_mask (uint8_t irq) {
|
|
||||||
struct acpi_madt_ioapic* apic;
|
|
||||||
struct limine_hhdm_response* hhdm = limine_hhdm_request.response;
|
|
||||||
|
|
||||||
apic = amd64_ioapic_find (irq);
|
|
||||||
|
|
||||||
if (apic == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
uint32_t irq_reg = ((irq - apic->gsi_base) * 2) + 0x10;
|
|
||||||
|
|
||||||
uint32_t value = amd64_ioapic_read ((uintptr_t)hhdm->offset + (uintptr_t)apic->address, irq_reg);
|
|
||||||
amd64_ioapic_write ((uintptr_t)hhdm->offset + (uintptr_t)apic->address, irq_reg,
|
|
||||||
value | (1 << 16));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Unmask a given IRQ */
|
|
||||||
void amd64_ioapic_unmask (uint8_t irq) {
|
|
||||||
struct acpi_madt_ioapic* apic;
|
|
||||||
struct limine_hhdm_response* hhdm = limine_hhdm_request.response;
|
|
||||||
|
|
||||||
apic = amd64_ioapic_find (irq);
|
|
||||||
|
|
||||||
if (apic == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
uint32_t irq_reg = ((irq - apic->gsi_base) * 2) + 0x10;
|
|
||||||
|
|
||||||
uint32_t value = amd64_ioapic_read ((uintptr_t)hhdm->offset + (uintptr_t)apic->address, irq_reg);
|
|
||||||
amd64_ioapic_write ((uintptr_t)hhdm->offset + (uintptr_t)apic->address, irq_reg,
|
|
||||||
value & ~(1 << 16));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find and initialize the IOAPIC */
|
/* Find and initialize the IOAPIC */
|
||||||
@@ -180,11 +155,15 @@ void amd64_ioapic_init (void) {
|
|||||||
|
|
||||||
switch (current->type) {
|
switch (current->type) {
|
||||||
case ACPI_MADT_ENTRY_TYPE_IOAPIC: {
|
case ACPI_MADT_ENTRY_TYPE_IOAPIC: {
|
||||||
struct acpi_madt_ioapic* ioapic = (struct acpi_madt_ioapic*)current;
|
struct acpi_madt_ioapic* ioapic_table_data = (struct acpi_madt_ioapic*)current;
|
||||||
mm_map_kernel_page ((uintptr_t)ioapic->address,
|
mm_map_kernel_page ((uintptr_t)ioapic_table_data->address,
|
||||||
(uintptr_t)hhdm->offset + (uintptr_t)ioapic->address,
|
(uintptr_t)hhdm->offset + (uintptr_t)ioapic_table_data->address,
|
||||||
MM_PG_PRESENT | MM_PG_RW | MM_PD_RELOAD);
|
MM_PG_PRESENT | MM_PG_RW | MM_PD_RELOAD);
|
||||||
apics[ioapic_entries++] = *ioapic;
|
ioapics[ioapic_entries++] = (struct ioapic){
|
||||||
|
.lock = SPIN_LOCK_INIT,
|
||||||
|
.table_data = *ioapic_table_data,
|
||||||
|
.mmio_base = ((uintptr_t)hhdm->offset + (uintptr_t)ioapic_table_data->address),
|
||||||
|
};
|
||||||
} break;
|
} break;
|
||||||
case ACPI_MADT_ENTRY_TYPE_INTERRUPT_SOURCE_OVERRIDE: {
|
case ACPI_MADT_ENTRY_TYPE_INTERRUPT_SOURCE_OVERRIDE: {
|
||||||
struct acpi_madt_interrupt_source_override* override =
|
struct acpi_madt_interrupt_source_override* override =
|
||||||
@@ -198,7 +177,7 @@ void amd64_ioapic_init (void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get MMIO base of Local APIC */
|
/* Get MMIO base of Local APIC */
|
||||||
static uintptr_t amd64_lapic_base (void) { return lapic_mmio_base; }
|
static uintptr_t amd64_lapic_base (void) { return thiscpu->lapic_mmio_base; }
|
||||||
|
|
||||||
/* Write Local APIC */
|
/* Write Local APIC */
|
||||||
static void amd64_lapic_write (uint32_t reg, uint32_t value) {
|
static void amd64_lapic_write (uint32_t reg, uint32_t value) {
|
||||||
@@ -216,9 +195,6 @@ uint32_t amd64_lapic_id (void) { return amd64_lapic_read (LAPIC_ID) >> 24; }
|
|||||||
/* Send End of interrupt command to Local APIC */
|
/* Send End of interrupt command to Local APIC */
|
||||||
void amd64_lapic_eoi (void) { amd64_lapic_write (LAPIC_EOI, 0); }
|
void amd64_lapic_eoi (void) { amd64_lapic_write (LAPIC_EOI, 0); }
|
||||||
|
|
||||||
/* Set initial counter value in Local APIC timer */
|
|
||||||
void amd64_lapic_tick (uint32_t tick) { amd64_lapic_write (LAPIC_TIMICT, tick); }
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Calibrate Local APIC to send interrupts in a set interval.
|
* Calibrate Local APIC to send interrupts in a set interval.
|
||||||
*
|
*
|
||||||
@@ -255,24 +231,24 @@ static void amd64_lapic_start (uint32_t ticks) {
|
|||||||
* Initialize Local APIC, configure to send timer interrupts at a given period. See
|
* Initialize Local APIC, configure to send timer interrupts at a given period. See
|
||||||
* amd64_lapic_calibrate and amd64_lapic_start.
|
* amd64_lapic_calibrate and amd64_lapic_start.
|
||||||
*/
|
*/
|
||||||
uint64_t amd64_lapic_init (uint32_t us) {
|
void amd64_lapic_init (uint32_t us) {
|
||||||
struct limine_hhdm_response* hhdm = limine_hhdm_request.response;
|
struct limine_hhdm_response* hhdm = limine_hhdm_request.response;
|
||||||
|
|
||||||
amd64_wrmsr (MSR_APIC_BASE, amd64_rdmsr (MSR_APIC_BASE) | (1 << 11));
|
amd64_wrmsr (MSR_APIC_BASE, amd64_rdmsr (MSR_APIC_BASE) | (1 << 11));
|
||||||
|
|
||||||
uintptr_t lapic_paddr = amd64_rdmsr (MSR_APIC_BASE) & 0xFFFFF000;
|
uintptr_t lapic_paddr = amd64_rdmsr (MSR_APIC_BASE) & 0xFFFFF000;
|
||||||
lapic_mmio_base = lapic_paddr + (uintptr_t)hhdm->offset;
|
thiscpu->lapic_mmio_base = lapic_paddr + (uintptr_t)hhdm->offset;
|
||||||
|
|
||||||
mm_map_kernel_page (lapic_paddr, lapic_mmio_base,
|
mm_map_kernel_page (lapic_paddr, thiscpu->lapic_mmio_base,
|
||||||
MM_PG_PRESENT | MM_PG_RW | MM_PD_LOCK | MM_PD_RELOAD);
|
MM_PG_PRESENT | MM_PG_RW | MM_PD_LOCK | MM_PD_RELOAD);
|
||||||
|
|
||||||
amd64_lapic_write (LAPIC_SIVR, 0xFF | (1 << 8));
|
amd64_lapic_write (LAPIC_SIVR, 0xFF | (1 << 8));
|
||||||
|
|
||||||
uint32_t ticks = amd64_lapic_calibrate (us);
|
if (thiscpu->id == 0) {
|
||||||
|
lapic_ticks = amd64_lapic_calibrate (us);
|
||||||
|
}
|
||||||
|
|
||||||
amd64_lapic_start (ticks);
|
amd64_lapic_start (lapic_ticks);
|
||||||
|
|
||||||
return ticks;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -282,6 +258,11 @@ uint64_t amd64_lapic_init (uint32_t us) {
|
|||||||
* vec - Interrupt vector/IDT stub, which will be invoked by the IPI.
|
* vec - Interrupt vector/IDT stub, which will be invoked by the IPI.
|
||||||
*/
|
*/
|
||||||
void amd64_lapic_ipi (uint8_t lapic_id, uint8_t vec) {
|
void amd64_lapic_ipi (uint8_t lapic_id, uint8_t vec) {
|
||||||
|
/* wait for previous IPI to finish */
|
||||||
|
while (amd64_lapic_read (LAPIC_ICR) & (1 << 12)) {
|
||||||
|
__asm__ volatile ("pause");
|
||||||
|
}
|
||||||
|
|
||||||
amd64_lapic_write (LAPIC_ICR + 0x10, (lapic_id << 24));
|
amd64_lapic_write (LAPIC_ICR + 0x10, (lapic_id << 24));
|
||||||
amd64_lapic_write (LAPIC_ICR, vec);
|
amd64_lapic_write (LAPIC_ICR, vec);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,14 +4,11 @@
|
|||||||
#include <libk/std.h>
|
#include <libk/std.h>
|
||||||
|
|
||||||
void amd64_ioapic_route_irq (uint8_t vec, uint8_t irq, uint64_t flags, uint64_t lapic_id);
|
void amd64_ioapic_route_irq (uint8_t vec, uint8_t irq, uint64_t flags, uint64_t lapic_id);
|
||||||
void amd64_ioapic_mask (uint8_t irq);
|
|
||||||
void amd64_ioapic_unmask (uint8_t irq);
|
|
||||||
void amd64_ioapic_init (void);
|
void amd64_ioapic_init (void);
|
||||||
|
|
||||||
uint32_t amd64_lapic_id (void);
|
uint32_t amd64_lapic_id (void);
|
||||||
void amd64_lapic_tick (uint32_t tick);
|
|
||||||
void amd64_lapic_eoi (void);
|
void amd64_lapic_eoi (void);
|
||||||
void amd64_lapic_ipi (uint8_t lapic_id, uint8_t vec);
|
void amd64_lapic_ipi (uint8_t lapic_id, uint8_t vec);
|
||||||
uint64_t amd64_lapic_init (uint32_t us);
|
void amd64_lapic_init (uint32_t us);
|
||||||
|
|
||||||
#endif // _KERNEL_AMD64_APIC_H
|
#endif // _KERNEL_AMD64_APIC_H
|
||||||
|
|||||||
@@ -61,8 +61,7 @@ static void amd64_smp_bootstrap (struct limine_mp_info* mp_info) {
|
|||||||
amd64_init (cpu, true); /* gdt + idt */
|
amd64_init (cpu, true); /* gdt + idt */
|
||||||
syscall_init ();
|
syscall_init ();
|
||||||
|
|
||||||
thiscpu->lapic_ticks = amd64_lapic_init (10000);
|
amd64_lapic_init (0);
|
||||||
amd64_lapic_tick (thiscpu->lapic_ticks);
|
|
||||||
|
|
||||||
DEBUG ("CPU %u is online!\n", thiscpu->id);
|
DEBUG ("CPU %u is online!\n", thiscpu->id);
|
||||||
|
|
||||||
@@ -76,7 +75,7 @@ static void amd64_smp_bootstrap (struct limine_mp_info* mp_info) {
|
|||||||
|
|
||||||
/// Initialize SMP subsystem for AMD64. Start AP CPUs
|
/// Initialize SMP subsystem for AMD64. Start AP CPUs
|
||||||
void smp_init (void) {
|
void smp_init (void) {
|
||||||
thiscpu->lapic_ticks = amd64_lapic_init (10000);
|
amd64_lapic_init (10000);
|
||||||
|
|
||||||
struct limine_mp_response* mp = limine_mp_request.response;
|
struct limine_mp_response* mp = limine_mp_request.response;
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ struct cpu {
|
|||||||
volatile struct gdt_extended gdt ALIGNED (16);
|
volatile struct gdt_extended gdt ALIGNED (16);
|
||||||
volatile struct tss tss;
|
volatile struct tss tss;
|
||||||
|
|
||||||
uint64_t lapic_ticks;
|
uintptr_t lapic_mmio_base;
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ void proc_cleanup_resources (struct proc* proc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void proc_drop_resource (struct proc* proc, struct proc_resource* resource) {
|
void proc_drop_resource (struct proc* proc, struct proc_resource* resource) {
|
||||||
|
DEBUG ("resource=%p, type=%d, rid=%d\n", resource, resource->type, resource->rid);
|
||||||
|
|
||||||
if (atomic_fetch_sub (&resource->refs, 1) == 1) {
|
if (atomic_fetch_sub (&resource->refs, 1) == 1) {
|
||||||
spin_lock (&proc->lock);
|
spin_lock (&proc->lock);
|
||||||
rbtree_delete (&proc->resource_tree, &resource->proc_resource_tree_link);
|
rbtree_delete (&proc->resource_tree, &resource->proc_resource_tree_link);
|
||||||
@@ -47,7 +49,6 @@ static bool proc_create_resource_mem (struct proc_resource_mem* mem,
|
|||||||
|
|
||||||
mem->paddr = paddr;
|
mem->paddr = paddr;
|
||||||
mem->pages = init->pages;
|
mem->pages = init->pages;
|
||||||
DEBUG ("paddr=%p, pages=%zu\n", mem->paddr, mem->pages);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -82,6 +83,8 @@ struct proc_resource* proc_create_resource (struct proc* proc, int rid, int type
|
|||||||
struct proc_resource_mem_init* mem_init = data;
|
struct proc_resource_mem_init* mem_init = data;
|
||||||
proc_create_resource_mem (&resource->u.mem, mem_init);
|
proc_create_resource_mem (&resource->u.mem, mem_init);
|
||||||
resource->ops.cleanup = &proc_cleanup_resource_mem;
|
resource->ops.cleanup = &proc_cleanup_resource_mem;
|
||||||
|
DEBUG ("resource=%p paddr=%p, pages=%zu\n", resource, resource->u.mem.paddr,
|
||||||
|
resource->u.mem.pages);
|
||||||
} break;
|
} break;
|
||||||
default: {
|
default: {
|
||||||
free (resource);
|
free (resource);
|
||||||
|
|||||||
Reference in New Issue
Block a user