kernel: Implemented various features
+ lapic: Start implementation + ioapic: Start implementation + apic: Now properly working + madt: Start implementation + pit: Start implementation + smp: Start implementation (only grabs the bootstrap processor's LAPIC ID)
This commit is contained in:
parent
dcea7360d2
commit
b2cf9b4710
22 changed files with 520 additions and 79 deletions
|
@ -12,10 +12,41 @@
|
|||
#include <boot/limine.h>
|
||||
#include <lib/log.h>
|
||||
#include <mm/memop.h>
|
||||
#include <mm/pmm.h>
|
||||
#include <stdint.h>
|
||||
|
||||
static bool __acpi_use_xsdt;
|
||||
static uint64_t __acpi_rsdt_addr;
|
||||
|
||||
void *acpi_find_table(char *sign) {
|
||||
if (__acpi_use_xsdt) {
|
||||
acpi_xsdt_t *xsdt = (acpi_xsdt_t*)__acpi_rsdt_addr;
|
||||
uint32_t entries = (xsdt->hdr.len - sizeof(xsdt->hdr)) / 8;
|
||||
|
||||
for (uint32_t i = 0; i < entries; i++)
|
||||
{
|
||||
acpi_sdt_hdr_t *h = (acpi_sdt_hdr_t *)higher_half(*((uint64_t*)xsdt->entries + i));
|
||||
if (!memcmp(h->sign, sign, 4))
|
||||
return (void *) h;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
acpi_rsdt_t *rsdt = (acpi_rsdt_t*)__acpi_rsdt_addr;
|
||||
int entries = (rsdt->hdr.len - sizeof(rsdt->hdr)) / 4;
|
||||
uint32_t *entries_hhalf = (uint32_t *)higher_half((uint64_t)rsdt->entries);
|
||||
|
||||
for (int i = 0; i < entries; i++)
|
||||
{
|
||||
acpi_sdt_hdr_t *h = (acpi_sdt_hdr_t *)(entries_hhalf[i] + (i * sizeof(uint32_t)));
|
||||
if (!memcmp(h->sign, sign, 4))
|
||||
return (void *) h;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void acpi_init() {
|
||||
acpi_rsdp_t *rsdp = (acpi_rsdp_t*)limine_get_rsdp();
|
||||
if (memcmp(rsdp->sign, "RSD PTR ", 8))
|
||||
|
@ -30,13 +61,13 @@ void acpi_init() {
|
|||
|
||||
acpi_xsdp_t *xsdp = (acpi_xsdp_t *)rsdp;
|
||||
__acpi_use_xsdt = 1;
|
||||
__acpi_rsdt_addr = xsdp->xsdt_addr;
|
||||
__acpi_rsdt_addr = higher_half(xsdp->xsdt_addr);
|
||||
|
||||
goto initialized;
|
||||
}
|
||||
|
||||
__acpi_use_xsdt = 0;
|
||||
__acpi_rsdt_addr = rsdp->rsdt_addr; // Do not use a pointer, to shut up the compiler.
|
||||
__acpi_rsdt_addr = higher_half(rsdp->rsdt_addr); // Do not use a pointer, to shut up the compiler.
|
||||
|
||||
initialized:
|
||||
trace("acpi: Initialized!\n");
|
||||
|
|
|
@ -15,14 +15,36 @@ typedef struct {
|
|||
char oemid[6];
|
||||
char rev;
|
||||
uint32_t rsdt_addr;
|
||||
} acpi_rsdp_t;
|
||||
} __attribute__((packed)) acpi_rsdp_t;
|
||||
|
||||
typedef struct {
|
||||
acpi_rsdp_t base;
|
||||
uint32_t len;
|
||||
uint64_t xsdt_addr;
|
||||
char chksumex;
|
||||
} acpi_xsdp_t;
|
||||
} __attribute__((packed)) acpi_xsdp_t;
|
||||
|
||||
void acpi_init();
|
||||
void acpi_init();
|
||||
typedef struct {
|
||||
char sign[4];
|
||||
uint32_t len;
|
||||
uint8_t rev;
|
||||
uint8_t chksum;
|
||||
char oemid[6];
|
||||
char oemtabid[8];
|
||||
uint32_t oemrev;
|
||||
uint32_t creaid;
|
||||
uint32_t crearev;
|
||||
} __attribute__((packed)) acpi_sdt_hdr_t;
|
||||
|
||||
typedef struct {
|
||||
acpi_sdt_hdr_t hdr;
|
||||
char entries[];
|
||||
} acpi_rsdt_t;
|
||||
|
||||
typedef struct {
|
||||
acpi_sdt_hdr_t hdr;
|
||||
char entries[];
|
||||
} acpi_xsdt_t;
|
||||
|
||||
void *acpi_find_table(char *sign);
|
||||
void acpi_init();
|
42
kernel/src/acpi/madt.c
Normal file
42
kernel/src/acpi/madt.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* The Soaplin Kernel
|
||||
* Copyright (C) 2025 The SILD Project
|
||||
*
|
||||
* madt.c - MADT lookup
|
||||
*/
|
||||
|
||||
#include "acpi/acpi.h"
|
||||
#include "lib/log.h"
|
||||
#include <acpi/madt.h>
|
||||
|
||||
acpi_madt_ioapic_t* madt_ioapic_list[128];
|
||||
acpi_madt_iso_t* madt_iso_list[128];
|
||||
|
||||
uint32_t madt_ioapic_len = 0;
|
||||
uint32_t madt_iso_len = 0;
|
||||
|
||||
uint64_t *madt_lapic_addr = (uint64_t *)0;
|
||||
|
||||
void madt_init() {
|
||||
void *addr = acpi_find_table("APIC");
|
||||
acpi_madt_t *madt = (acpi_madt_t *)addr;
|
||||
uint64_t offset = 0;
|
||||
|
||||
while (1) {
|
||||
if (offset > madt->hdr.len - sizeof(acpi_madt_t))
|
||||
break;
|
||||
|
||||
madt_entry *entry = (madt_entry *)(madt->table + offset);
|
||||
|
||||
if (entry->type == 1)
|
||||
madt_ioapic_list[madt_ioapic_len++] = (acpi_madt_ioapic_t *)entry;
|
||||
else if (entry->type == 2)
|
||||
madt_iso_list[madt_iso_len++] = (acpi_madt_iso_t *)entry;
|
||||
else if (entry->type == 5)
|
||||
madt_lapic_addr = (uint64_t *)((acpi_madt_lapic_addr_override_t *)entry)->plapic;
|
||||
|
||||
offset += entry->len;
|
||||
}
|
||||
|
||||
trace("madt: Initialized\n");
|
||||
}
|
61
kernel/src/acpi/madt.h
Normal file
61
kernel/src/acpi/madt.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* The Soaplin Kernel
|
||||
* Copyright (C) 2025 The SILD Project
|
||||
*
|
||||
* madt.h - MADT lookup
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
acpi_sdt_hdr_t hdr;
|
||||
uint32_t lapic_addr;
|
||||
uint32_t flags;
|
||||
char table[];
|
||||
} acpi_madt_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t type;
|
||||
uint8_t len;
|
||||
} madt_entry;
|
||||
|
||||
typedef struct {
|
||||
madt_entry entry;
|
||||
uint8_t cpu_id;
|
||||
uint8_t lapic_id;
|
||||
uint32_t flags;
|
||||
} acpi_madt_lapic_t;
|
||||
|
||||
typedef struct {
|
||||
madt_entry entry;
|
||||
uint8_t ioapic_id;
|
||||
uint8_t reserved;
|
||||
uint32_t ioapic_addr;
|
||||
uint32_t gsi_base;
|
||||
} acpi_madt_ioapic_t;
|
||||
|
||||
typedef struct {
|
||||
madt_entry entry;
|
||||
uint8_t bus;
|
||||
uint8_t source;
|
||||
uint32_t gsi;
|
||||
uint16_t flags;
|
||||
} acpi_madt_iso_t; // iso = interrupt source override
|
||||
|
||||
typedef struct {
|
||||
madt_entry entry;
|
||||
uint16_t reserved;
|
||||
uint64_t plapic;
|
||||
} acpi_madt_lapic_addr_override_t;
|
||||
|
||||
extern acpi_madt_ioapic_t* madt_ioapic_list[128];
|
||||
extern acpi_madt_iso_t* madt_iso_list[128];
|
||||
|
||||
extern uint32_t madt_ioapic_len;
|
||||
extern uint32_t madt_iso_len;
|
||||
|
||||
extern uint64_t *lapic_addr;
|
||||
|
||||
void madt_init();
|
|
@ -18,5 +18,12 @@ void cpu_load_pm(pagemap_t pm);
|
|||
// Invalidate a page table entry
|
||||
void cpu_invalidate_page(uint64_t vaddr);
|
||||
|
||||
// Initialize SMP. The implementations are in arch since the Limine
|
||||
// structure changes depending on the architecture.
|
||||
void cpu_init_smp();
|
||||
|
||||
// Initialize the CPU's timer
|
||||
void cpu_init_timer();
|
||||
|
||||
// Disable interrupts and halt the system.
|
||||
void hcf();
|
0
kernel/src/arch/x86_64/cpu.h
Normal file
0
kernel/src/arch/x86_64/cpu.h
Normal file
|
@ -37,11 +37,9 @@
|
|||
|
||||
%macro isr_err_stub 1
|
||||
isr_stub_%+%1:
|
||||
push %1 ; push intno into the stack
|
||||
|
||||
push %1
|
||||
pushall
|
||||
|
||||
mov rdi, rsp ; put the stack as the first arg.
|
||||
mov rdi, rsp
|
||||
|
||||
call idt_interrupt_handler
|
||||
|
||||
|
@ -102,10 +100,17 @@ isr_no_err_stub 29
|
|||
isr_err_stub 30
|
||||
isr_no_err_stub 31
|
||||
|
||||
%assign i 32
|
||||
%rep 224
|
||||
isr_no_err_stub i
|
||||
%assign i i+1
|
||||
%endrep
|
||||
|
||||
|
||||
global isr_stub_table
|
||||
isr_stub_table:
|
||||
%assign i 0
|
||||
%rep 32
|
||||
%rep 256
|
||||
dq isr_stub_%+i
|
||||
%assign i i+1
|
||||
%endrep
|
|
@ -4,65 +4,38 @@
|
|||
*
|
||||
* idt.c - x86_64 Interrupt Descriptor Table implementation.
|
||||
*/
|
||||
|
||||
#include "dev/lapic.h"
|
||||
#if defined(__x86_64__)
|
||||
|
||||
#include "arch/cpu.h"
|
||||
#include "lib/log.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#include <arch/cpu.h>
|
||||
#include <arch/x86_64/idt.h>
|
||||
#include <arch/x86_64/smp.h>
|
||||
#include <dev/ioapic.h>
|
||||
#include <lib/log.h>
|
||||
|
||||
__attribute__((aligned(0x10)))
|
||||
static idt_entry_t idt[256];
|
||||
static idtr_t idtr;
|
||||
|
||||
static void __panic_display_bt(registers_t *regs) {
|
||||
if (regs->cs == 0x43 || regs->cs == 0x3B) {
|
||||
fatal("The backtrace can't be dumped from a userspace process.\n");
|
||||
return; // Don't try to backtrace userspace
|
||||
}
|
||||
static uint8_t __idt_vectors[256];
|
||||
static interrupt_handler __idt_external_handlers[256];
|
||||
|
||||
fatal("-- BACKTRACE --\n");
|
||||
void idt_register_handler(uint8_t vector, void *isr) {
|
||||
if (vector <= 16)
|
||||
ioapic_redir_irq(bootstrap_lapic_id, vector + 32, vector, false);
|
||||
|
||||
// First print the current instruction pointer from the interrupt frame
|
||||
if (regs->rip) {
|
||||
fatal("* %p (current)\n", regs->rip);
|
||||
}
|
||||
|
||||
uint64_t *frame = (uint64_t*)regs->rbp;
|
||||
if (!frame || (uint64_t)frame < 0xffffffff80000000) {
|
||||
fatal("No further stack frames available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Frame format in x86_64:
|
||||
// [rbp] -> previous rbp
|
||||
// [rbp+8] -> return address
|
||||
int depth = 0;
|
||||
while (frame && depth < 16) { // Limit depth to avoid infinite loops
|
||||
// Validate both frame and return address pointers
|
||||
uint64_t *ret_addr_ptr = frame + 1;
|
||||
if ((uint64_t)ret_addr_ptr < 0xffffffff80000000) {
|
||||
break;
|
||||
}
|
||||
|
||||
uint64_t ret_addr = *ret_addr_ptr;
|
||||
if (ret_addr < 0xffffffff80000000 || ret_addr > 0xfffffffffffff000) {
|
||||
break;
|
||||
}
|
||||
|
||||
fatal("* %p\n", ret_addr);
|
||||
|
||||
uint64_t next_rbp = *frame;
|
||||
if (next_rbp < 0xffffffff80000000 || next_rbp > 0xfffffffffffff000) {
|
||||
break;
|
||||
}
|
||||
|
||||
frame = (uint64_t*)next_rbp;
|
||||
depth++;
|
||||
}
|
||||
fatal("\n");
|
||||
__idt_external_handlers[vector] = isr;
|
||||
__idt_vectors[vector <= 16 ? vector + 32 : vector] = vector <= 16 ? VT_HWI : VT_SWI;
|
||||
}
|
||||
|
||||
void idt_interrupt_handler(registers_t *regs) {
|
||||
if (__idt_vectors[regs->int_no] == VT_SPURIOUS || __idt_vectors[regs->int_no] == VT_NONE)
|
||||
return;
|
||||
|
||||
if (regs->int_no < 32) {
|
||||
fatal("Kernel panic: CPU exception %d\n", regs->int_no);
|
||||
fatal("rax: %p, rbx: %p, rbp: %p, rdx\n", regs->rax, regs->rbx, regs->rbp, regs->rdx);
|
||||
fatal("rdi: %p, rsi: %p, rcx: %p\n", regs->rdi, regs->rsi, regs->rcx);
|
||||
|
@ -71,39 +44,65 @@ void idt_interrupt_handler(registers_t *regs) {
|
|||
fatal("r14: %p, r15: %p\n", regs->r14, regs->r15);
|
||||
fatal("rip: %p, cs: %p, ss: %p\n", regs->rip, regs->cs, regs->ss);
|
||||
fatal("rflags: %p, err: %d, rsp: %p\n", regs->rflags, regs->err_code, regs->rsp);
|
||||
__panic_display_bt(regs);
|
||||
hcf();
|
||||
}
|
||||
|
||||
int vec = regs->int_no;
|
||||
if (vec >= 32 && vec < 48)
|
||||
vec -= 32;
|
||||
|
||||
if (__idt_vectors[regs->int_no] == VT_HWI) {
|
||||
interrupt_handler i = __idt_external_handlers[vec];
|
||||
i(regs);
|
||||
} else if (__idt_vectors[regs->int_no] == VT_SWI) {
|
||||
interrupt_handler i = __idt_external_handlers[regs->int_no];
|
||||
i(regs);
|
||||
}
|
||||
|
||||
lapic_eoi();
|
||||
}
|
||||
|
||||
void idt_set_descriptor(uint8_t vector, void* isr, uint8_t flags) {
|
||||
idt_entry_t* descriptor = &idt[vector];
|
||||
idt_entry_t* descriptor = &idt[vector];
|
||||
|
||||
descriptor->isr_low = (uint64_t)isr & 0xFFFF;
|
||||
descriptor->kernel_cs = 0x08;
|
||||
descriptor->ist = 0;
|
||||
descriptor->attributes = flags;
|
||||
descriptor->isr_mid = ((uint64_t)isr >> 16) & 0xFFFF;
|
||||
descriptor->isr_high = ((uint64_t)isr >> 32) & 0xFFFFFFFF;
|
||||
descriptor->reserved = 0;
|
||||
descriptor->isr_low = (uint64_t)isr & 0xFFFF;
|
||||
descriptor->kernel_cs = 0x08;
|
||||
descriptor->ist = 0;
|
||||
descriptor->attributes = flags;
|
||||
descriptor->isr_mid = ((uint64_t)isr >> 16) & 0xFFFF;
|
||||
descriptor->isr_high = ((uint64_t)isr >> 32) & 0xFFFFFFFF;
|
||||
descriptor->reserved = 0;
|
||||
}
|
||||
|
||||
static bool vectors[32];
|
||||
|
||||
extern void* isr_stub_table[];
|
||||
|
||||
void idt_init() {
|
||||
idtr.base = (uintptr_t)&idt[0];
|
||||
idtr.limit = (uint16_t)sizeof(idt_entry_t) * 32 - 1;
|
||||
idtr.base = (uintptr_t)&idt[0];
|
||||
idtr.limit = (uint16_t)sizeof(idt_entry_t) * 256 - 1;
|
||||
|
||||
for (uint8_t vector = 0; vector < 32; vector++) {
|
||||
idt_set_descriptor(vector, isr_stub_table[vector], 0x8E);
|
||||
vectors[vector] = true;
|
||||
}
|
||||
for (uint8_t vector = 0; vector < 32; vector++) {
|
||||
idt_set_descriptor(vector, isr_stub_table[vector], 0x8E);
|
||||
__idt_vectors[vector] = VT_EXCEPTION;
|
||||
}
|
||||
trace("idt: Exception vectors has been set!\n");
|
||||
|
||||
__asm__ volatile ("lidt %0" : : "m"(idtr));
|
||||
__asm__ volatile ("sti");
|
||||
for (uint8_t vector = 32; vector < 48; vector++) {
|
||||
idt_set_descriptor(vector, isr_stub_table[vector], 0x8E);
|
||||
__idt_vectors[vector] = VT_HWI;
|
||||
}
|
||||
trace("idt: Hardware interrupt vectors has been set!\n");
|
||||
for (uint16_t vector = 48; vector < 256; vector++) {
|
||||
idt_set_descriptor(vector, isr_stub_table[vector], 0x8E);
|
||||
__idt_vectors[vector] = VT_NONE;
|
||||
}
|
||||
__idt_vectors[IDT_SPURIOUS_INT] = VT_SPURIOUS;
|
||||
trace("idt: Spurious interrupt vector has been set!\n");
|
||||
|
||||
trace("arch: IDT loaded successfully\n");
|
||||
__asm__ volatile ("lidt %0" : : "m"(idtr));
|
||||
__asm__ volatile ("sti");
|
||||
|
||||
trace("arch: IDT loaded successfully\n");
|
||||
}
|
||||
|
||||
#endif
|
|
@ -8,6 +8,14 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#define VT_NONE 0
|
||||
#define VT_EXCEPTION 1
|
||||
#define VT_HWI 2
|
||||
#define VT_SWI 3
|
||||
#define VT_SPURIOUS 4
|
||||
|
||||
#define IDT_SPURIOUS_INT 0xFF
|
||||
|
||||
typedef struct {
|
||||
uint64_t r15;
|
||||
uint64_t r14;
|
||||
|
@ -33,6 +41,8 @@ typedef struct {
|
|||
uint64_t ss;
|
||||
} __attribute__((packed)) registers_t;
|
||||
|
||||
typedef void(*interrupt_handler)(registers_t*);
|
||||
|
||||
typedef struct {
|
||||
uint16_t isr_low;
|
||||
uint16_t kernel_cs;
|
||||
|
@ -48,4 +58,5 @@ typedef struct {
|
|||
uint64_t base;
|
||||
} __attribute__((packed)) idtr_t;
|
||||
|
||||
void idt_register_handler(uint8_t vector, void *isr);
|
||||
void idt_init(void);
|
23
kernel/src/arch/x86_64/io.h
Normal file
23
kernel/src/arch/x86_64/io.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* The Soaplin Kernel
|
||||
* Copyright (C) 2025 The SILD Project
|
||||
*
|
||||
* io.h - x86_64 I/O functions
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
inline void outb(uint16_t port, uint8_t val) {
|
||||
__asm__ volatile ( "outb %b0, %w1" : : "a"(val), "Nd"(port) : "memory");
|
||||
}
|
||||
|
||||
inline uint8_t inb(uint16_t port) {
|
||||
uint8_t ret;
|
||||
__asm__ volatile ( "inb %w1, %b0"
|
||||
: "=a"(ret)
|
||||
: "Nd"(port)
|
||||
: "memory");
|
||||
return ret;
|
||||
}
|
30
kernel/src/arch/x86_64/pit.c
Normal file
30
kernel/src/arch/x86_64/pit.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* The Soaplin Kernel
|
||||
* Copyright (C) 2025 The SILD Project
|
||||
*
|
||||
* pit.c - x86_64 Programmable Interval Timer implementation.
|
||||
*/
|
||||
#if defined(__x86_64__)
|
||||
|
||||
#include <arch/x86_64/io.h>
|
||||
#include <arch/x86_64/idt.h>
|
||||
#include <lib/log.h>
|
||||
|
||||
void pit_handler(registers_t *reg) {
|
||||
trace("pit: Interrupt!\n");
|
||||
}
|
||||
|
||||
void cpu_init_timer() {
|
||||
outb(0x43, 0x36);
|
||||
|
||||
uint16_t div = (uint16_t)(1193180 / 1000);
|
||||
|
||||
// Since the PIT uses 8-bit IO operations,
|
||||
// we need to split div in 2.
|
||||
outb(0x40, (uint8_t)div);
|
||||
outb(0x40, (uint8_t)(div >> 8));
|
||||
|
||||
idt_register_handler(0, pit_handler);
|
||||
}
|
||||
|
||||
#endif
|
17
kernel/src/arch/x86_64/smp.c
Normal file
17
kernel/src/arch/x86_64/smp.c
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* The Soaplin Kernel
|
||||
* Copyright (C) 2025 The SILD Project
|
||||
*
|
||||
* smp.c - x86_64 Symetric Multiprocessing implementation
|
||||
*/
|
||||
|
||||
#include <boot/limine.h>
|
||||
#include <deps/limine.h>
|
||||
#include <stdint.h>
|
||||
|
||||
uint32_t bootstrap_lapic_id;
|
||||
|
||||
void cpu_init_smp() {
|
||||
struct limine_mp_response *smp = limine_get_smp();
|
||||
bootstrap_lapic_id = smp->bsp_lapic_id;
|
||||
}
|
12
kernel/src/arch/x86_64/smp.h
Normal file
12
kernel/src/arch/x86_64/smp.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* The Soaplin Kernel
|
||||
* Copyright (C) 2025 The SILD Project
|
||||
*
|
||||
* smp.c - x86_64 Symetric Multiprocessing definitions
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern uint32_t bootstrap_lapic_id;
|
|
@ -69,6 +69,12 @@ static volatile struct limine_rsdp_request rsdp_req = {
|
|||
.revision = 0
|
||||
};
|
||||
|
||||
__attribute__((used, section(".limine_requests")))
|
||||
static volatile struct limine_mp_request smp_req = {
|
||||
.id = LIMINE_MP_REQUEST,
|
||||
.revision = 0
|
||||
};
|
||||
|
||||
__attribute__((used, section(".limine_requests_start")))
|
||||
static volatile LIMINE_REQUESTS_START_MARKER;
|
||||
|
||||
|
@ -117,3 +123,4 @@ uint64_t limine_get_kernel_vaddr() { return kaddr_req.response->virtual_base; }
|
|||
uint64_t limine_get_kernel_paddr() { return kaddr_req.response->physical_base; }
|
||||
uint64_t limine_get_kernel_ehdr_addr() { return (uint64_t)execfile_req.response->executable_file->address; }
|
||||
uint64_t limine_get_rsdp() { return rsdp_req.response->address + limine_get_hhdm_offset(); }
|
||||
struct limine_mp_response *limine_get_smp() { return smp_req.response; }
|
|
@ -36,3 +36,4 @@ uint64_t limine_get_kernel_vaddr();
|
|||
uint64_t limine_get_kernel_paddr();
|
||||
uint64_t limine_get_kernel_ehdr_addr();
|
||||
uint64_t limine_get_rsdp();
|
||||
struct limine_mp_response *limine_get_smp();
|
87
kernel/src/dev/ioapic.c
Normal file
87
kernel/src/dev/ioapic.c
Normal file
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* The Soaplin Kernel
|
||||
* Copyright (C) 2025 The SILD Project
|
||||
*
|
||||
* ioapic.c - I/O APIC implementation.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <acpi/madt.h>
|
||||
#include <dev/ioapic.h>
|
||||
#include <lib/log.h>
|
||||
#include <mm/pmm.h>
|
||||
|
||||
static void __ioapic_write(acpi_madt_ioapic_t *ioapic, uint32_t reg, uint32_t val) {
|
||||
*(volatile uint32_t *)(higher_half(ioapic->ioapic_addr)) = reg;
|
||||
*(volatile uint32_t *)(higher_half(ioapic->ioapic_addr+0x10)) = val;
|
||||
}
|
||||
static uint32_t __ioapic_read(acpi_madt_ioapic_t *ioapic, uint32_t reg) {
|
||||
*(volatile uint32_t *)(higher_half(ioapic->ioapic_addr)) = reg;
|
||||
return *(volatile uint32_t *)(higher_half(ioapic->ioapic_addr+0x10));
|
||||
}
|
||||
|
||||
void ioapic_init() {
|
||||
acpi_madt_ioapic_t *ioapic = madt_ioapic_list[0];
|
||||
|
||||
uint32_t value = __ioapic_read(ioapic, IOAPIC_VERSION);
|
||||
uint32_t count = (value >> 16) & 0xFF;
|
||||
|
||||
for (uint8_t i = 0; i <= count; ++i) {
|
||||
__ioapic_write(ioapic,
|
||||
IOAPIC_REDTBL+2 * i,
|
||||
0x00010000 | (32 + i));
|
||||
__ioapic_write(ioapic,
|
||||
IOAPIC_REDTBL + 2 * i + 1, 0);
|
||||
}
|
||||
|
||||
trace("ioapic: Initialized\n");
|
||||
}
|
||||
|
||||
uint32_t ioapic_gsi_count(acpi_madt_ioapic_t* ioapic) {
|
||||
return (__ioapic_read(ioapic, 1) & 0xff0000) >> 16;
|
||||
}
|
||||
|
||||
acpi_madt_ioapic_t *ioapic_get_gsi(uint32_t gsi) {
|
||||
for (uint32_t i = 0; i < madt_ioapic_len; i++) {
|
||||
acpi_madt_ioapic_t* ioapic = madt_ioapic_list[i];
|
||||
if (ioapic->gsi_base <= gsi && ioapic->gsi_base + ioapic_gsi_count(ioapic) > gsi)
|
||||
return ioapic;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ioapic_redirect_gsi(uint32_t lapic_id, uint8_t vec, uint32_t gsi, uint16_t flags, bool mask) {
|
||||
acpi_madt_ioapic_t* ioapic = ioapic_get_gsi(gsi);
|
||||
|
||||
uint64_t redirect = vec;
|
||||
|
||||
if ((flags & (1 << 1)) != 0) {
|
||||
redirect |= (1 << 13);
|
||||
}
|
||||
|
||||
if ((flags & (1 << 3)) != 0) {
|
||||
redirect |= (1 << 15);
|
||||
}
|
||||
|
||||
if (mask) redirect |= (1 << 16);
|
||||
else redirect &= ~(1 << 16);
|
||||
|
||||
redirect |= (uint64_t)lapic_id << 56;
|
||||
|
||||
uint32_t redtbl = (gsi - ioapic->gsi_base) * 2 + 16;
|
||||
__ioapic_write(ioapic, redtbl, (uint32_t)redirect);
|
||||
__ioapic_write(ioapic, redtbl + 1, (uint32_t)(redirect >> 32));
|
||||
}
|
||||
|
||||
void ioapic_redir_irq(uint32_t lapic_id, uint8_t vec, uint8_t irq, bool mask) {
|
||||
uint8_t idx = 0;
|
||||
acpi_madt_iso_t* iso = NULL;
|
||||
|
||||
for (idx = 0; idx < madt_iso_len; ++idx) {
|
||||
iso = madt_iso_list[idx];
|
||||
if (iso->source == irq) { ioapic_redirect_gsi(lapic_id, vec, iso->gsi, iso->flags, mask); return; }
|
||||
}
|
||||
ioapic_redirect_gsi(lapic_id, vec, irq, 0, mask);
|
||||
}
|
17
kernel/src/dev/ioapic.h
Normal file
17
kernel/src/dev/ioapic.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* The Soaplin Kernel
|
||||
* Copyright (C) 2025 The SILD Project
|
||||
*
|
||||
* ioapic.c - I/O APIC definitions.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define IOAPIC_VERSION 0x1
|
||||
#define IOAPIC_REDTBL 0x10
|
||||
|
||||
void ioapic_init();
|
||||
void ioapic_redir_irq(uint32_t lapic_id, uint8_t vec, uint8_t irq, bool mask);
|
33
kernel/src/dev/lapic.c
Normal file
33
kernel/src/dev/lapic.c
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* The Soaplin Kernel
|
||||
* Copyright (C) 2025 The SILD Project
|
||||
*
|
||||
* lapic.c - Local APIC implementation.
|
||||
*/
|
||||
|
||||
#include "dev/lapic.h"
|
||||
#include "arch/x86_64/idt.h"
|
||||
#include "lib/log.h"
|
||||
#include "mm/pmm.h"
|
||||
#include <stdint.h>
|
||||
|
||||
static uint64_t __lapic_pbase = 0xfee00000;
|
||||
static uint64_t __lapic_vbase;
|
||||
|
||||
static void __lapic_write(uint32_t reg, uint32_t val) { *(volatile uint32_t *)(__lapic_vbase + reg) = val; }
|
||||
static uint32_t __lapic_read(uint32_t reg) { return *(volatile uint32_t *)(__lapic_vbase + reg); }
|
||||
static void __lapic_write_svr(uint32_t reg, lapic_svr_entry e) { *(volatile uint32_t *)(__lapic_vbase + reg) = *(uint32_t*)&e; }
|
||||
|
||||
void lapic_init() {
|
||||
__lapic_vbase = higher_half(__lapic_pbase);
|
||||
__lapic_write_svr(LAPIC_SVR, (lapic_svr_entry){ .swenabled = true, .vec = IDT_SPURIOUS_INT });
|
||||
trace("lapic: Initialized\n");
|
||||
}
|
||||
|
||||
void lapic_eoi() {
|
||||
__lapic_write(LAPIC_EOI, 0x0);
|
||||
}
|
||||
|
||||
uint32_t lapic_get_id() {
|
||||
return __lapic_read(LAPIC_ID) >> LAPIC_ICDESTSHIFT;
|
||||
}
|
26
kernel/src/dev/lapic.h
Normal file
26
kernel/src/dev/lapic.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* The Soaplin Kernel
|
||||
* Copyright (C) 2025 The SILD Project
|
||||
*
|
||||
* lapic.h - Local APIC definitions.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define LAPIC_ID 0x20
|
||||
#define LAPIC_SVR 0xF0
|
||||
#define LAPIC_EOI 0xB0
|
||||
|
||||
#define LAPIC_ICDESTSHIFT 24
|
||||
|
||||
typedef struct {
|
||||
uint8_t vec;
|
||||
bool swenabled;
|
||||
} lapic_svr_entry;
|
||||
|
||||
void lapic_init();
|
||||
void lapic_eoi();
|
||||
uint32_t lapic_get_id();
|
|
@ -10,6 +10,7 @@
|
|||
#include <stdbool.h>
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/madt.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <boot/limine.h>
|
||||
#include <config.h>
|
||||
|
@ -19,6 +20,8 @@
|
|||
#include <lib/logoutputs_sk.h>
|
||||
#include <mm/memop.h>
|
||||
#include <mm/pmm.h>
|
||||
#include "dev/ioapic.h"
|
||||
#include "dev/lapic.h"
|
||||
#include "mm/paging.h"
|
||||
#include "mm/vma.h"
|
||||
|
||||
|
@ -37,7 +40,14 @@ void kmain(void) {
|
|||
pg_init();
|
||||
|
||||
acpi_init();
|
||||
madt_init();
|
||||
lapic_init();
|
||||
ioapic_init();
|
||||
cpu_init_smp();
|
||||
cpu_init_timer();
|
||||
|
||||
while (1)
|
||||
;;
|
||||
// We're done, just hang... for now.
|
||||
hcf();
|
||||
//hcf();
|
||||
}
|
||||
|
|
0
kernel/src/mm/pmm.md
Normal file
0
kernel/src/mm/pmm.md
Normal file
0
kernel/src/mm/vmm.c
Normal file
0
kernel/src/mm/vmm.c
Normal file
Loading…
Add table
Add a link
Reference in a new issue