88#include "pedigree/kernel/Archive.h"
89#include "pedigree/kernel/Atomic.h"
90#include "pedigree/kernel/BootstrapInfo.h"
91#include "pedigree/kernel/Log.h"
92#include "pedigree/kernel/ServiceManager.h"
93#include "pedigree/kernel/Subsystem.h"
94#include "pedigree/kernel/Version.h"
95#include "pedigree/kernel/compiler.h"
96#include "pedigree/kernel/core/BootIO.h"
97#include "pedigree/kernel/core/SlamAllocator.h"
98#include "pedigree/kernel/core/cppsupport.h"
99#include "pedigree/kernel/graphics/GraphicsService.h"
100#include "pedigree/kernel/linker/KernelElf.h"
101#include "pedigree/kernel/machine/InputManager.h"
102#include "pedigree/kernel/machine/Machine.h"
103#include "pedigree/kernel/machine/Trace.h"
104#include "pedigree/kernel/panic.h"
105#include "pedigree/kernel/process/InfoBlock.h"
106#include "pedigree/kernel/process/MemoryPressureKiller.h"
107#include "pedigree/kernel/process/MemoryPressureManager.h"
108#include "pedigree/kernel/process/OwnedThread.h"
109#include "pedigree/kernel/process/PerProcessorScheduler.h"
110#include "pedigree/kernel/process/Process.h"
111#include "pedigree/kernel/process/Scheduler.h"
112#include "pedigree/kernel/process/Thread.h"
113#include "pedigree/kernel/processor/KernelCoreSyscallManager.h"
114#include "pedigree/kernel/processor/PhysicalMemoryManager.h"
115#include "pedigree/kernel/processor/Processor.h"
116#include "pedigree/kernel/processor/ProcessorInformation.h"
117#include "pedigree/kernel/processor/types.h"
118#include "pedigree/kernel/utilities/Cache.h"
119#include "pedigree/kernel/utilities/StaticString.h"
120#include "pedigree/kernel/utilities/String.h"
121#include "pedigree/kernel/utilities/new"
122#include "pedigree/kernel/utilities/utility.h"
125#include "pedigree/kernel/debugger/Debugger.h"
126#include "pedigree/kernel/debugger/commands/LocksCommand.h"
130#include "pedigree/kernel/utilities/ZombieQueue.h"
134namespace __pedigree_hosted {};
135using namespace __pedigree_hosted;
140EXPORTED_PUBLIC
BootIO bootIO;
147static Machine::ShutdownType g_ShutdownType = Machine::ShutdownType::Halt;
150#if HOSTED && PEDIGREE_HOSTED_IRQ_CLOSURE_TESTS
151extern bool runHostedIrqClosureRegressions();
184size_t g_StaticDriverN = 0;
187static int loadModules(
void* inf) {
191 extern uintptr_t start_module_ctors;
192 extern uintptr_t end_module_ctors;
196 uintptr_t* iterator = &start_module_ctors;
197 while (iterator < &end_module_ctors) {
198 void (*fp)(void) =
reinterpret_cast<void (*)(
void)
>(*iterator);
203 for (
size_t i = 0; i < g_StaticDriverN; ++i) {
204 assert(g_StaticDrivers[i]->tag == MODULE_TAG);
213 NOTICE(
"initrd @ " <<
Hex << bsInf->getInitrdAddress() <<
" -> "
214 << (bsInf->getInitrdAddress() + bsInf->getInitrdSize()) <<
", " <<
Dec
215 << bsInf->getInitrdSize() <<
" bytes");
220 initrd =
new Archive(bsInf->getInitrdAddress(), bsInf->getInitrdSize());
224 NOTICE(
"there are " << nFiles <<
" files");
225 g_BootProgressTotal = nFiles * 2;
226 for (
size_t i = 0; i < nFiles; i++) {
229 if (!StringCompareN(initrd->
getFileName(i),
"._", 2)) {
233 NOTICE(
"loading module #" << i <<
" (" << initrd->
getFileName(i) <<
")...");
238 WARNING(
"A loaded module disabled interrupts.");
253#if PEDIGREE_CONCURRENCY_SMOKE_TESTS
257 g_NeedsShutdown =
true;
264 FATAL(
"At least one module's dependencies were never met.");
274 fprintf(stderr,
"Pedigree has started: all modules have been loaded.\n");
277 NOTICE(
"module load thread is terminating");
289 TRACE(
"constructors");
292 initialiseConstructors();
294 g_pBootstrapInfo = &bsInf;
296#if DEBUGGER && TRACK_LOCKS
297 g_LocksCommand.setReady();
300 TRACE(
"Processor init");
310 TRACE(
"Machine init");
313 Machine& machine = Machine::instance();
316 machine.initialise();
318#if DEBUGGER && (!defined(PEDIGREE_HOSTED_DARWIN) || !PEDIGREE_HOSTED_DARWIN)
319 TRACE(
"Debugger init");
323 TRACE(
"Machine init2");
325 machine.initialise2();
332 TRACE(
"Processor init2");
338 TRACE(
"Machine init3");
340 machine.initialise3();
342 TRACE(
"KernelElf init");
346 panic(
"KernelElf::initialise() failed");
350 if (bsInf.isInitrdLoaded() ==
false)
351 panic(
"Initrd module not loaded!");
354 TRACE(
"kernel syscall init");
358 TRACE(
"initial init done, enabling interrupts");
362 TRACE(
"bootIO init");
369 str +=
"Pedigree - revision ";
370 str += g_pBuildRevision;
372 str +=
"\n=======================\n";
375 str +=
"\r\n=======================\r\n";
377 bootIO.
write(str, BootIO::White, BootIO::Black);
385 str += g_pBuildMachine;
392 bootIO.
write(str, BootIO::LightGrey, BootIO::Black);
395 str +=
"Build flags: ";
396 str += g_pBuildFlags;
403 bootIO.
write(str, BootIO::LightGrey, BootIO::Black);
406 str +=
"Processor information: ";
415 bootIO.
write(str, BootIO::LightGrey, BootIO::Black);
417 TRACE(
"creating graphics service");
426 ServiceManager::instance().
addService(
String(
"graphics"), pService, pFeatures);
429 TRACE(
"creating memory pressure handlers");
433 MemoryPressureManager::instance().
registerHandler(MemoryPressureManager::HighestPriority,
438 MemoryPressureManager::instance().
registerHandler(MemoryPressureManager::LowestPriority, &killer);
441 TRACE(
"InfoBlockManager init");
442 InfoBlockManager::instance().initialise();
445 TRACE(
"CacheManager init");
449 TRACE(
"InputManager init");
453 TRACE(
"ZombieQueue init");
460#if HOSTED && PEDIGREE_HOSTED_IRQ_CLOSURE_TESTS
461 runHostedIrqClosureRegressions();
463 TRACE(
"starting module load thread");
467 &loadModules,
static_cast<void*
>(&bsInf), 0);
468 pThread->setName(
"module load thread");
469 moduleLoadThread.adopt(pThread);
476 EMIT_IF(DEBUGGER_RUN_AT_START) {
480 TRACE(
"becoming idle");
488 while (!g_NeedsShutdown) {
497 if (!g_NeedsShutdown)
511 moduleLoadThread.
join();
512#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS && !PEDIGREE_HOSTED_IRQ_CLOSURE_TESTS
513 NOTICE(
"HOSTED-WAIT-TEST: PASS module-loader-shutdown-join");
517 NOTICE(
"Resetting...");
522 panic(
"Shutdown aborted: module quiesce failed");
526 if (!Machine::instance().prepareShutdown(g_ShutdownType)) {
527 panic(
"Shutdown aborted: firmware workers did not stop");
531 extern uintptr_t start_module_dtors;
532 extern uintptr_t end_module_dtors;
535 uintptr_t* iterator = &start_module_dtors;
536 while (iterator < &end_module_dtors) {
537 void (*fp)(void) =
reinterpret_cast<void (*)(
void)
>(*iterator);
548 ZombieQueue::instance().
destroy();
559 CacheManager::destroyInstance();
561 if (!CacheManager::instance().shutdown()) {
562 panic(
"Shutdown aborted: retained cache writeback failed");
564 NOTICE(
"CacheManager: terminal cache writeback complete");
570 if (!InfoBlockManager::instance().shutdown()) {
571 panic(
"Shutdown aborted: info block timer callback did not drain");
573#if PEDIGREE_CONCURRENCY_SMOKE_TESTS
574 NOTICE(
"QEMU-CONCURRENCY-TEST: PASS infoblock-timer-drain");
587 if (!Machine::instance().stopAllOtherProcessors()) {
588 ERROR_NOLOCK(
"Shutdown aborted: not all other processors stopped");
595#if PEDIGREE_CONCURRENCY_SMOKE_TESTS
596 NOTICE(
"QEMU-CONCURRENCY-TEST: PASS shutdown-worker-drain-smp");
606 if (
const char* result = Machine::instance().finalShutdown(g_ShutdownType)) {
607 shutdownResult = result;
622 NOTICE(
"Module shutdown complete. Running destructors and terminating...");
623 runKernelDestructors();
628 NOTICE(
"Module shutdown complete. Retaining kernel static storage and terminating...");
629#if PEDIGREE_CONCURRENCY_SMOKE_TESTS
630 TRACE(
"QEMU-CONCURRENCY-TEST: PASS kernel-static-storage-retained");
635 TRACE(
"kernel main() terminating");
639 "Shutdown complete.\nIt's now safe to power off your computer.");
640 if (shutdownResult.length()) {
641 shutdownMessage +=
"\n\n";
642 shutdownMessage += shutdownResult;
654void EXPORTED_PUBLIC system_reset();
657 g_NeedsShutdown =
true;
660 scheduler->requestIdleThreadWakeup();
664void system_reboot(Machine::ShutdownType type) {
665 WARNING(
"System shutting down...");
668 Subsystem* currentSubsystem = currentProcess->getSubsystem();
669 if (!currentSubsystem) {
670 panic(
"System reboot requires a userspace shutdown coordinator");
674 if (!g_ShutdownCoordinator.compareAndSwap(
false,
true)) {
675 currentSubsystem->
exit(0);
676 panic(
"Concurrent shutdown caller returned from process exit");
681 g_ShutdownType = type;
686 currentSubsystem->
exit(0);
687 panic(
"Shutdown coordinator returned from process exit");
691 return "SLAM recovery; freeing unused slabs.";
695 return SlamAllocator::instance().recovery(5) != 0;
uintptr_t * getFile(size_t n)
char * getFileName(size_t n)
size_t getFileSize(size_t n)
EXPORTED_PUBLIC void write(T &str, Colour foreColour, Colour backColour)
static Debugger & instance()
static KernelCoreSyscallManager & instance()
void executeModules(bool silent=false, bool progress=true)
void waitForModulesToLoad()
void invokeInitModule()
Invokes the module named 'init'. When a module named init is discovered, rather than executing it in ...
static KernelElf & instance()
Module * loadModule(uint8_t *pModule, size_t len, bool silent=false)
static EXPORTED_PUBLIC Log & instance()
virtual void initialiseDeviceTree()
virtual void deinitialise()
static void setShutdownPhase(ShutdownPhase phase, const char *detail=nullptr)
void displayShutdownMessage(const char *message)
void registerHandler(size_t prio, MemoryPressureHandler *pHandler)
static bool getInterrupts()
static void initialise2(const BootstrapStruct_t &Info) INITIALISATION_ONLY
second/last stage in the initialisation of the processor-specific interface
static void initialise1(const BootstrapStruct_t &Info) INITIALISATION_ONLY
first stage in the initialisation of the processor-specific interface
static void initialisationDone()
static ProcessorInformation & information()
static void identify(HugeStaticString &str)
static void setInterrupts(bool bEnable)
static void deinitialise()
static void haltUntilInterrupt()
virtual void initialise()
static Scheduler & instance()
void addService(const String &serviceName, Service *s, ServiceFeatures *feats)
virtual const char * getMemoryPressureDescription()
virtual void exit(int code, ExitCause cause=ExitCause::Normal)=0
void EXPORTED_PUBLIC panic(const char *msg) NORETURN