feat: main function

This commit is contained in:
Katharina 2026-07-04 18:33:06 +02:00
parent beb7fb38ae
commit ba608513e6
10 changed files with 151 additions and 57 deletions

View file

@ -13,4 +13,7 @@ struct discovery_result_t {
optional<Fadt> fadt;
};
void initDiscovery();
const discovery_result_t& getDiscovery();
} // namespace acpi

View file

@ -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<Core> initCore(acpi::Madt madt, core_id id);
void initCores(acpi::discovery_result_t);
void transitionStartupCore();
[[noreturn]] void transitionStartupCore();
} // namespace apic

View file

@ -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();
}

View file

@ -1,3 +1,5 @@
#pragma once
[[noreturn]] void main();
#include "apic/core.h"
[[noreturn]] void main(apic::Core* core);

View file

@ -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<uint64_t>(mb) - high_base;
uint64_t offset_in_info = reinterpret_cast<uint64_t>(rsdp_payload) - reinterpret_cast<uint64_t>(mb);
return paddr_t{info_phys + offset_in_info};
}
optional<acpi::Rsdp> findRsdp() {
optional<paddr_t> 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;
}

View file

@ -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<Gdt> 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<apic::Core>();
*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::Core> 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> 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<core_id>(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<uint64_t>(placement.core) - 8;
longjump(
reinterpret_cast<uint64_t>(&main), rsp, kernel_code_selector, kernel_data_selector,
reinterpret_cast<uint64_t>(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<apic::Core*>(stack + 8);
longjump(
reinterpret_cast<uint64_t>(&main), stack, kernel_code_selector, kernel_data_selector,
reinterpret_cast<uint64_t>(core)
);
}

View file

@ -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<uint64_t>(mb) - high_base;
uint64_t offset_in_info = reinterpret_cast<uint64_t>(rsdp_payload) - reinterpret_cast<uint64_t>(mb);
return paddr_t{info_phys + offset_in_info};
}
static acpi::Rsdp findRsdp() {
optional<paddr_t> 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();
}

View file

@ -1,6 +1,6 @@
#include "main.h"
[[noreturn]] void main() {
[[noreturn]] void main([[maybe_unused]] apic::Core* core) {
while (true) {
__asm__ volatile("hlt");
}