From ba608513e64ad04cf1fc54bbbd688c347977bf0b Mon Sep 17 00:00:00 2001 From: Katharina Heidenreich Date: Sat, 4 Jul 2026 18:33:06 +0200 Subject: [PATCH] feat: main function --- kernel/include/acpi/discovery.h | 3 ++ kernel/include/apic/core.h | 4 ++- kernel/include/cpu/gdt.h | 19 ++++++++++ kernel/include/main.h | 4 ++- kernel/src/acpi/discovery.cpp | 63 +++++++++++++++++++++++++++++++++ kernel/src/apic/core.cpp | 58 +++++++++++++++++++++++++----- kernel/src/init/init.cpp | 50 ++++---------------------- kernel/src/main.cpp | 2 +- run.sh | 3 ++ testenv/qemuConfig.cfg | 2 -- 10 files changed, 151 insertions(+), 57 deletions(-) create mode 100644 kernel/src/acpi/discovery.cpp diff --git a/kernel/include/acpi/discovery.h b/kernel/include/acpi/discovery.h index 23aaa15..0b29c04 100644 --- a/kernel/include/acpi/discovery.h +++ b/kernel/include/acpi/discovery.h @@ -13,4 +13,7 @@ struct discovery_result_t { optional fadt; }; +void initDiscovery(); +const discovery_result_t& getDiscovery(); + } // namespace acpi diff --git a/kernel/include/apic/core.h b/kernel/include/apic/core.h index 1d1da06..7b499d7 100644 --- a/kernel/include/apic/core.h +++ b/kernel/include/apic/core.h @@ -3,6 +3,7 @@ #include "memory/pointer.h" #include "acpi/discovery.h" +#include "cpu/gdt.h" #include "memory/pagetable.h" namespace apic { @@ -18,12 +19,13 @@ struct Core { core_id id; stack_t stack; PageTable kernelPageTable; + Gdt gdt; }; optional initCore(acpi::Madt madt, core_id id); void initCores(acpi::discovery_result_t); -void transitionStartupCore(); +[[noreturn]] void transitionStartupCore(); } // namespace apic \ No newline at end of file diff --git a/kernel/include/cpu/gdt.h b/kernel/include/cpu/gdt.h index 054838d..31ef33e 100644 --- a/kernel/include/cpu/gdt.h +++ b/kernel/include/cpu/gdt.h @@ -56,3 +56,22 @@ struct [[gnu::packed]] tss_t { static_assert(sizeof(tss_t) == 104); void reloadSegments(Gdt::selector_t code_selector, Gdt::selector_t data_selector); + +[[noreturn]] inline void longjump( + uint64_t code, uint64_t stack, Gdt::selector_t code_selector, Gdt::selector_t stack_selector, uint64_t arg +) { + uint64_t code_sel = code_selector; + uint16_t stack_sel = stack_selector; + asm volatile( + "mov %[stack_sel], %%ss\n" + "mov %[stack], %%rsp\n" + "pushq %[code_sel]\n" + "pushq %[code]\n" + "mov %[arg], %%rdi\n" + "lretq\n" + : + : [stack_sel] "r"(stack_sel), [stack] "r"(stack), [code_sel] "r"(code_sel), [code] "r"(code), [arg] "r"(arg) + : "memory", "rdi" + ); + __builtin_unreachable(); +} diff --git a/kernel/include/main.h b/kernel/include/main.h index 2332afb..aa437b4 100644 --- a/kernel/include/main.h +++ b/kernel/include/main.h @@ -1,3 +1,5 @@ #pragma once -[[noreturn]] void main(); +#include "apic/core.h" + +[[noreturn]] void main(apic::Core* core); diff --git a/kernel/src/acpi/discovery.cpp b/kernel/src/acpi/discovery.cpp new file mode 100644 index 0000000..d623ba6 --- /dev/null +++ b/kernel/src/acpi/discovery.cpp @@ -0,0 +1,63 @@ +#include "acpi/discovery.h" +#include "init/multiboot2.h" +#include "util/function.h" + +namespace { + +paddr_t rsdp_physical_of(const uint8_t* rsdp_payload) { + const multiboot::info* mb = multiboot::get_multiboot_info(); + uint64_t info_phys = reinterpret_cast(mb) - high_base; + uint64_t offset_in_info = reinterpret_cast(rsdp_payload) - reinterpret_cast(mb); + return paddr_t{info_phys + offset_in_info}; +} + +optional findRsdp() { + optional rsdp{}; + multiboot::visit_all( + overloaded{ + [&](const multiboot::tag_new_acpi* tag) { + rsdp = rsdp_physical_of(tag->rsdp); + }, + [&](const multiboot::tag_old_acpi* tag) { + if (!rsdp.has_value()) { + rsdp = rsdp_physical_of(tag->rsdp); + } + } + } + ); + if (!rsdp.has_value()) { + return {}; + } + return acpi::Rsdp(*rsdp); +} + +acpi::discovery_result_t discover() { + acpi::discovery_result_t res{}; + res.rsdp = findRsdp(); + if (!res.rsdp.has_value()) { + return res; + } + res.rsdp->for_each_table( + overloaded{ + [&](const acpi::madt_t* header) { + res.madt = acpi::Madt{header}; + }, + [&](const acpi::fadt_t* header) { + res.fadt = acpi::Fadt{header}; + } + } + ); + return res; +} + +acpi::discovery_result_t cached_discovery{}; + +} // namespace + +void acpi::initDiscovery() { + cached_discovery = discover(); +} + +const acpi::discovery_result_t& acpi::getDiscovery() { + return cached_discovery; +} diff --git a/kernel/src/apic/core.cpp b/kernel/src/apic/core.cpp index 7e87df7..19746c1 100644 --- a/kernel/src/apic/core.cpp +++ b/kernel/src/apic/core.cpp @@ -2,8 +2,12 @@ #include "apic/lapic.h" #include "apic/timer.h" #include "cpu/gdt.h" +#include "main.h" #include "memory/allocator.h" +constexpr Gdt::selector_t kernel_code_selector = 0x08; +constexpr Gdt::selector_t kernel_data_selector = 0x10; + static volatile gdt_register_t secondary_gdt_register; static optional createSecondaryGdt() { @@ -70,6 +74,27 @@ bool startupCore(uint8_t apicId, paddr_t code, paddr_t stack, PageTable pageTabl return waitForStartedInfo(started_info, 2, apic::milliseconds(100)); } +struct core_stack_placement_t { + apic::Core* core; // high-half pointer to the Core value stored at the top of the stack + uint64_t rsp; // raw physical address to use as the initial stack pointer +}; + +static core_stack_placement_t placeCoreOnStack( + apic::core_id id, paddr_t stackBase, size_t stackPageCount, PageTable pageTable, Gdt gdt +) { + uint64_t stackBytes = stackPageCount * page_size; + uint64_t topPhys = stackBase.address + stackBytes; + uint64_t corePhys = (topPhys - sizeof(apic::Core)) & ~uint64_t{0xF}; + apic::Core* core = paddr_t{corePhys}.access(); + *core = apic::Core{ + .id = id, + .stack = {stackBase, stackBytes}, + .kernelPageTable = pageTable, + .gdt = gdt, + }; + return {core, corePhys - 8}; +} + PageTable createPageTable() { PageTable pageTable = PageTable::allocNew().value(); PageTable::flags_t cachedFlags = { @@ -121,20 +146,19 @@ optional apic::initCore(acpi::Madt madt, core_id id) { if (apicId.value() == apic::localApicId()) { return {}; } - apic::Core core{}; size_t stackPageCount = 256; paddr_t stackBase = PhysicalAllocator::getInstance().allocPages(stackPageCount).value().ptr; - paddr_t stackPtr = {stackBase.address + stackPageCount * page_size - 8}; paddr_t code = {read_symbol("__16bitStartup")}; auto pageTable = createPageTable(); optional gdt = createSecondaryGdt(); if (!gdt.has_value()) { return {}; } - if (!startupCore(apicId.value(), code, stackPtr, pageTable, gdt.value())) { + auto placement = placeCoreOnStack(id, stackBase, stackPageCount, pageTable, gdt.value()); + if (!startupCore(apicId.value(), code, paddr_t{placement.rsp}, pageTable, gdt.value())) { return {}; } - return core; + return *placement.core; } void apic::initCores(acpi::discovery_result_t discovery) { @@ -146,10 +170,28 @@ void apic::initCores(acpi::discovery_result_t discovery) { }); } -void apic::transitionStartupCore() {} +void apic::transitionStartupCore() { + core_id id = static_cast(apic::localApicId()); + size_t stackPageCount = 256; + paddr_t stackBase = PhysicalAllocator::getInstance().allocPages(stackPageCount).value().ptr; + PageTable pageTable = createPageTable(); + Gdt gdt = createSecondaryGdt().value(); + auto placement = placeCoreOnStack(id, stackBase, stackPageCount, pageTable, gdt); + gdt.activate(); + pageTable.activate(); + uint64_t rsp = reinterpret_cast(placement.core) - 8; + longjump( + reinterpret_cast(&main), rsp, kernel_code_selector, kernel_data_selector, + reinterpret_cast(placement.core) + ); +} extern "C" [[noreturn]] void __secondary_init() { - while (true) { - __asm__ volatile("hlt"); - } + uint64_t stack; + __asm__ volatile("mov %%rsp, %0" : "=r"(stack)); + auto* core = reinterpret_cast(stack + 8); + longjump( + reinterpret_cast(&main), stack, kernel_code_selector, kernel_data_selector, + reinterpret_cast(core) + ); } \ No newline at end of file diff --git a/kernel/src/init/init.cpp b/kernel/src/init/init.cpp index 5b140a6..61d8025 100644 --- a/kernel/src/init/init.cpp +++ b/kernel/src/init/init.cpp @@ -1,8 +1,5 @@ #include "init/init.h" -#include "acpi/acpi.h" #include "acpi/discovery.h" -#include "acpi/fadt.h" -#include "acpi/madt.h" #include "apic/core.h" #include "apic/lapic.h" #include "apic/timer.h" @@ -163,48 +160,13 @@ static void setupMemory() { }}); } -static paddr_t rsdp_physical_of(const uint8_t* rsdp_payload) { - const multiboot::info* mb = multiboot::get_multiboot_info(); - uint64_t info_phys = reinterpret_cast(mb) - high_base; - uint64_t offset_in_info = reinterpret_cast(rsdp_payload) - reinterpret_cast(mb); - return paddr_t{info_phys + offset_in_info}; -} - -static acpi::Rsdp findRsdp() { - optional rsdp{}; - multiboot::visit_all( - overloaded{ - [&](const multiboot::tag_new_acpi* tag) { - rsdp = rsdp_physical_of(tag->rsdp); - }, - [&](const multiboot::tag_old_acpi* tag) { - if (!rsdp.has_value()) { - rsdp = rsdp_physical_of(tag->rsdp); - } - } - } - ); - - if (!rsdp.has_value()) { +static acpi::discovery_result_t setupAcpi() { + acpi::initDiscovery(); + const acpi::discovery_result_t& discovery = acpi::getDiscovery(); + if (!discovery.rsdp.has_value()) { panic("System could not find ACPI RSDP!"); } - return acpi::Rsdp(*rsdp); -} - -static acpi::discovery_result_t setupAcpi() { - acpi::discovery_result_t res{}; - res.rsdp = findRsdp(); - res.rsdp->for_each_table( - overloaded{ - [&](const acpi::madt_t* header) { - res.madt = acpi::Madt{header}; - }, - [&](const acpi::fadt_t* header) { - res.fadt = acpi::Fadt{header}; - } - } - ); - return res; + return discovery; } static void calibrateTimer(acpi::discovery_result_t acpi) { @@ -226,5 +188,5 @@ static void calibrateTimer(acpi::discovery_result_t acpi) { print("\n"); step("timer", partial(calibrateTimer, acpi)); step("cpu startup", partial(apic::initCores, acpi)); - halt(); + apic::transitionStartupCore(); } diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 49a3652..4a6d45c 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,6 +1,6 @@ #include "main.h" -[[noreturn]] void main() { +[[noreturn]] void main([[maybe_unused]] apic::Core* core) { while (true) { __asm__ volatile("hlt"); } diff --git a/run.sh b/run.sh index 3253008..e030475 100755 --- a/run.sh +++ b/run.sh @@ -5,6 +5,9 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" bear --output "$SCRIPT_DIR/compile_commands.json" -- make -C "$SCRIPT_DIR/kernel" all || exit 1 mkdir -p "$SCRIPT_DIR/testenv/dist" cp "$SCRIPT_DIR/kernel/output/kernel.iso" "$SCRIPT_DIR/testenv/dist/kernel.iso" +if [ ! -f "$SCRIPT_DIR/testenv/image_file" ]; then + truncate -s 64M "$SCRIPT_DIR/testenv/image_file" +fi cd "$SCRIPT_DIR/testenv" || exit 1 CPU="-cpu Opteron_G1-v1,pdpe1gb=on" diff --git a/testenv/qemuConfig.cfg b/testenv/qemuConfig.cfg index 7b3f166..f903114 100644 --- a/testenv/qemuConfig.cfg +++ b/testenv/qemuConfig.cfg @@ -70,8 +70,6 @@ driver = "usb-kbd" bus = "usbDevice.0" [netdev "n1"] type = "user" -hostfwd = "udp:127.0.0.1:1234-:1234" -hostfwd = "tcp:127.0.0.1:1234-:1234" [object "net-dump"] qom-type = "filter-dump" netdev = "n1"