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 9589e9a..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) @@ -175,20 +186,9 @@ void emk_entry(void) acpi_init(); log_early("Initialized ACPI"); - acpi_madt_t *madt = (acpi_madt_t *)acpi_find_table("APIC"); - if (!madt) - { - kpanic(NULL, "Failed to find MADT table"); - } - - log_early("Found MADT at %p", madt); - - if (!mp_request.response) - { - kpanic(NULL, "Failed to get MP request"); - } - - log_early("%d available cores", mp_request.response->cpu_count); + /* Setup MADT */ + madt_init(); + log_early("Initialized APIC"); hlt(); } \ No newline at end of file diff --git a/kernel/src/sys/acpi/madt.c b/kernel/src/sys/acpi/madt.c new file mode 100644 index 0000000..008b283 --- /dev/null +++ b/kernel/src/sys/acpi/madt.c @@ -0,0 +1,54 @@ +/* EMK 1.0 Copyright (c) 2025 Piraterna */ +#include +#include +#include + +acpi_madt_ioapic_t *madt_ioapic_list[256] = {0}; +acpi_madt_ioapic_src_ovr_t *madt_iso_list[256] = {0}; + +uint32_t madt_ioapic_len = 0; +uint32_t madt_iso_len = 0; + +uint64_t *lapic_addr = 0; + +void madt_init() +{ + acpi_madt_t *madt = (acpi_madt_t *)acpi_find_table("APIC"); + if (!madt) + { + kpanic(NULL, "Failed to find MADT table"); + } + + if (madt->sdt.length < sizeof(acpi_madt_t)) + { + 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->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) + { + 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 fb36505..748fc24 100644 --- a/kernel/src/sys/acpi/madt.h +++ b/kernel/src/sys/acpi/madt.h @@ -93,4 +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