#define MODULE "main" #include "config.h" #include "cpu/CPU.h" #include "fs/devices/DeviceFS.h" #include "gdt/GDT.h" #include "init/Init.h" #include "interrupts/IDT.h" #include "interrupts/Install.h" #include "interrupts/Interrupts.h" #include "io/PIC.h" #include "log/Log.h" #include "memory/Memory.h" #include "memory/MemoryMap.h" #include "misc/hang.h" #include "std/ensure.h" #include "std/stdlib.h" #include "thread/PIT.h" #include "thread/Scheduler.h" #define STRINGIZE(x) #x #define STRINGIZE_VALUE_OF(x) STRINGIZE(x) extern "C" void _start() { Init::disable_smp(); // Put all other cores except the bootstrap one in an infinite loop Init::check_magic(); Init::early_init(); kinfoln("Starting Moon %s", moon_version()); CPU::log_cpu_information(); Memory::walk_memory_map(); GDT::load(); Interrupts::install(); IDT::load(); PIT::initialize(1000); // 1000 times per second Scheduler::init(); #ifdef RUN_TEST_AS_INIT ensure(Scheduler::load_user_task(STRINGIZE_VALUE_OF(RUN_TEST_AS_INIT)) > 0); #else ensure(Scheduler::load_user_task("/bin/init") > 0); #endif Scheduler::add_kernel_task("[reaper]", []() { while (1) { sleep(400); Scheduler::reap_tasks(); } }); ensure(VFS::mkdir("/dev") == 0); VFS::mount("/dev", DeviceFS::get()); Init::finish_kernel_boot(); PIC::remap(); PIC::enable_master(0b11111100); PIC::enable_slave(0b11111111); Interrupts::enable(); while (1) halt(); // As soon as the first timer interrupt arrives, this idle loop is gone, since the main function is not // registered as a task and thus the scheduler will never schedule this again. We still have to do // something while waiting for a timer interrupt to arrive, though. In fact, in most cases, calling // halt() once would be enough, since that function halts the CPU until the next interrupt (most likely // the timer one) arrives. But we have to guarantee this function never returns. }