From cdceef1da773b830163e252cfad03a2479f494b4 Mon Sep 17 00:00:00 2001 From: Kevin Alavik Date: Fri, 16 May 2025 19:45:59 +0200 Subject: [PATCH] feat/kernel: Added MADT support and SMP --- .vscode/settings.json | 4 +++- kernel/src/arch/smp.c | 44 ++++++++++++++++++++++++++++++++++++++ kernel/src/arch/smp.h | 10 +++++++++ kernel/src/boot/emk.h | 1 + kernel/src/emk.c | 19 +++++++++------- kernel/src/sys/acpi/madt.c | 33 +++++++++++++++++++--------- kernel/src/sys/acpi/madt.h | 6 ++++++ 7 files changed, 98 insertions(+), 19 deletions(-) create mode 100644 kernel/src/arch/smp.c create mode 100644 kernel/src/arch/smp.h diff --git a/.vscode/settings.json b/.vscode/settings.json index 3cef7d5..09e2812 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -18,6 +18,8 @@ "nanoprintf.h": "c", "flanterm.h": "c", "serial.h": "c", - "kpanic.h": "c" + "kpanic.h": "c", + "smp.h": "c", + "string_view": "c" } } \ No newline at end of file diff --git a/kernel/src/arch/smp.c b/kernel/src/arch/smp.c new file mode 100644 index 0000000..338c07e --- /dev/null +++ b/kernel/src/arch/smp.c @@ -0,0 +1,44 @@ +/* EMK 1.0 Copyright (c) 2025 Piraterna */ +#include +#include +#include +#include + +uint32_t bootstrap_lapic_id = 0; +uint32_t cpu_count = 0; + +uint32_t ctr = 0; + +void smp_entry(struct limine_mp_info *smp_info) +{ + + log_early("CPU %d started", smp_info->processor_id); + __atomic_fetch_add(&ctr, 1, __ATOMIC_SEQ_CST); + + while (1) + ; +} + +void smp_init() +{ + bootstrap_lapic_id = mp_response->bsp_lapic_id; + cpu_count = mp_response->cpu_count; + + for (uint64_t i = 0; i < cpu_count; i++) + { + if (mp_response->cpus[i]->lapic_id != bootstrap_lapic_id) + { + uint32_t old_ctr = __atomic_load_n(&ctr, __ATOMIC_SEQ_CST); + + __atomic_store_n(&mp_response->cpus[i]->goto_address, smp_entry, + __ATOMIC_SEQ_CST); + + while (__atomic_load_n(&ctr, __ATOMIC_SEQ_CST) == old_ctr) + ; + } + else + { + log_early("CPU %d is the bootstrap processor", i); + } + } +} \ No newline at end of file diff --git a/kernel/src/arch/smp.h b/kernel/src/arch/smp.h new file mode 100644 index 0000000..59f7f71 --- /dev/null +++ b/kernel/src/arch/smp.h @@ -0,0 +1,10 @@ +/* EMK 1.0 Copyright (c) 2025 Piraterna */ +#ifndef SMP_H +#define SMP_H + +#include + +extern uint32_t bootstrap_lapic_id; +void smp_init(); + +#endif // SMP_H \ No newline at end of file diff --git a/kernel/src/boot/emk.h b/kernel/src/boot/emk.h index bf82d3b..05ef935 100644 --- a/kernel/src/boot/emk.h +++ b/kernel/src/boot/emk.h @@ -16,6 +16,7 @@ extern uint64_t kphys; extern uint64_t kstack_top; extern vctx_t *kvm_ctx; extern struct limine_rsdp_response *rsdp_response; +extern struct limine_mp_response *mp_response; #define HIGHER_HALF(ptr) ((void *)((uint64_t)(ptr) < hhdm_offset ? (uint64_t)(ptr) + hhdm_offset : (uint64_t)(ptr))) #define PHYSICAL(ptr) ((void *)((uint64_t)(ptr) >= hhdm_offset ? (uint64_t)(ptr) - hhdm_offset : (uint64_t)(ptr))) diff --git a/kernel/src/emk.c b/kernel/src/emk.c index 3be9c61..7f2269d 100644 --- a/kernel/src/emk.c +++ b/kernel/src/emk.c @@ -19,6 +19,7 @@ #endif // FLANTERM_SUPPORT #include #include +#include __attribute__((used, section(".limine_requests"))) static volatile LIMINE_BASE_REVISION(3); __attribute__((used, section(".limine_requests"))) static volatile struct limine_memmap_request memmap_request = { @@ -51,6 +52,7 @@ uint64_t kphys = 0; uint64_t kstack_top = 0; vctx_t *kvm_ctx = NULL; struct limine_rsdp_response *rsdp_response = NULL; +struct limine_mp_response *mp_response = NULL; #if FLANTERM_SUPPORT struct flanterm_context *ft_ctx = NULL; @@ -166,6 +168,15 @@ void emk_entry(void) kfree(c); log_early("Initialized kernel heap"); + /* Setup SMP */ + if (!mp_request.response) + { + kpanic(NULL, "Failed to get MP request"); + } + + mp_response = mp_request.response; + smp_init(); + /* Setup ACPI and APIC */ rsdp_response = rsdp_request.response; if (!rsdp_response) @@ -179,13 +190,5 @@ void emk_entry(void) madt_init(); log_early("Initialized APIC"); - /* Setup SMP */ - if (!mp_request.response) - { - kpanic(NULL, "Failed to get MP request"); - } - - log_early("%d available cores", mp_request.response->cpu_count); - hlt(); } \ No newline at end of file diff --git a/kernel/src/sys/acpi/madt.c b/kernel/src/sys/acpi/madt.c index aed97a4..008b283 100644 --- a/kernel/src/sys/acpi/madt.c +++ b/kernel/src/sys/acpi/madt.c @@ -19,23 +19,36 @@ void madt_init() kpanic(NULL, "Failed to find MADT table"); } - uint64_t offset = 0; - int i = 0; - while (1) + if (madt->sdt.length < sizeof(acpi_madt_t)) { - if (offset > madt->sdt.length - sizeof(acpi_madt_t)) - break; + kpanic(NULL, "MADT table is too small"); + } + uint64_t offset = 0; + while (offset < madt->sdt.length - sizeof(acpi_madt_t)) + { acpi_madt_entry_t *entry = (acpi_madt_entry_t *)(madt->table + offset); - if (entry->type == 0) - i++; - else if (entry->type == MADT_ENTRY_IOAPIC) - madt_ioapic_list[madt_ioapic_len++] = (acpi_madt_ioapic_t *)entry; + if (entry->length == 0 || offset + entry->length > madt->sdt.length - sizeof(acpi_madt_t)) + { + kpanic(NULL, "Invalid MADT entry length or overflow"); + } + + if (entry->type == MADT_ENTRY_IOAPIC) + { + if (madt_ioapic_len < 256) + madt_ioapic_list[madt_ioapic_len++] = (acpi_madt_ioapic_t *)entry; + } else if (entry->type == MADT_ENTRY_IOAPIC_SRC_OVR) - madt_iso_list[madt_iso_len++] = (acpi_madt_ioapic_src_ovr_t *)entry; + { + if (madt_iso_len < 256) + madt_iso_list[madt_iso_len++] = (acpi_madt_ioapic_src_ovr_t *)entry; + } else if (entry->type == MADT_ENTRY_LAPIC_ADDR_OVR) + { lapic_addr = (uint64_t *)((acpi_madt_lapic_addr_ovr_t *)entry)->lapic_addr; + } + offset += entry->length; } } \ No newline at end of file diff --git a/kernel/src/sys/acpi/madt.h b/kernel/src/sys/acpi/madt.h index 64faecd..748fc24 100644 --- a/kernel/src/sys/acpi/madt.h +++ b/kernel/src/sys/acpi/madt.h @@ -93,6 +93,12 @@ typedef struct acpi_madt_lx2apic uint32_t acpi_id; /* ACPI ID */ } __attribute__((packed)) acpi_madt_lx2apic_t; +extern acpi_madt_ioapic_t *madt_ioapic_list[256]; +extern acpi_madt_ioapic_src_ovr_t *madt_iso_list[256]; +extern uint32_t madt_ioapic_len; +extern uint32_t madt_iso_len; +extern uint64_t *lapic_addr; + void madt_init(); #endif // MADT_H \ No newline at end of file