The Pedigree Project  0.1
system/kernel/core/main.cc
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
96 #include "pedigree/kernel/Archive.h"
97 #include "pedigree/kernel/BootstrapInfo.h"
98 #include "pedigree/kernel/Log.h"
99 #include "pedigree/kernel/Version.h"
100 #include "pedigree/kernel/compiler.h"
101 #include "pedigree/kernel/core/BootIO.h"
102 #include "pedigree/kernel/core/SlamAllocator.h"
103 #include "pedigree/kernel/core/cppsupport.h"
104 
105 #include "pedigree/kernel/linker/KernelElf.h"
106 #include "pedigree/kernel/machine/InputManager.h"
107 #include "pedigree/kernel/machine/Machine.h"
108 #include "pedigree/kernel/machine/Trace.h"
109 #include "pedigree/kernel/panic.h"
110 #include "pedigree/kernel/process/InfoBlock.h"
111 #include "pedigree/kernel/process/MemoryPressureKiller.h"
112 #include "pedigree/kernel/process/MemoryPressureManager.h"
113 #include "pedigree/kernel/process/PerProcessorScheduler.h"
114 #include "pedigree/kernel/process/Scheduler.h"
115 #include "pedigree/kernel/process/Thread.h"
116 #include "pedigree/kernel/processor/KernelCoreSyscallManager.h"
117 #include "pedigree/kernel/processor/Processor.h"
118 #include "pedigree/kernel/processor/ProcessorInformation.h"
119 #include "pedigree/kernel/processor/types.h"
120 #include "pedigree/kernel/utilities/Cache.h"
121 #include "pedigree/kernel/utilities/StaticString.h"
122 #include "pedigree/kernel/utilities/String.h"
123 #include "pedigree/kernel/utilities/new"
124 
125 #ifdef DEBUGGER
126 #include "pedigree/kernel/debugger/Debugger.h"
127 #include "pedigree/kernel/debugger/commands/LocksCommand.h"
128 #endif
129 
130 #ifdef OPENFIRMWARE
131 #include "pedigree/kernel/machine/openfirmware/Device.h"
132 #endif
133 
134 #ifdef THREADS
135 #include "pedigree/kernel/utilities/ZombieQueue.h"
136 #endif
137 
138 #ifdef HOSTED
139 namespace __pedigree_hosted
140 {
141 }; // namespace __pedigree_hosted
142 using namespace __pedigree_hosted;
143 #include <stdio.h>
144 #endif
145 
147 EXPORTED_PUBLIC BootIO bootIO;
148 
150 BootstrapStruct_t *g_pBootstrapInfo;
151 
154 {
155  public:
156  virtual const String getMemoryPressureDescription();
157  virtual bool compact();
158 };
159 
160 #ifdef MULTIPROCESSOR
161 
163 void apMain()
164 {
165  NOTICE("Processor #" << Processor::id() << " started.");
166 
167 #ifdef THREADS
168  // Add us as the idle thread for this CPU.
169  Processor::information().getScheduler().setIdle(
170  Processor::information().getCurrentThread());
171 #endif
172 
174  for (;;)
175  {
177 
178 #ifdef THREADS
180 #endif
181  }
182 }
183 #endif
184 
185 #ifdef STATIC_DRIVERS
186 extern uintptr_t start_modinfo;
187 extern uintptr_t end_modinfo;
188 
189 extern uintptr_t start_module_ctors;
190 extern uintptr_t end_module_ctors;
191 #endif
192 
194 static int loadModules(void *inf)
195 {
196 #ifdef STATIC_DRIVERS
197  ModuleInfo *tags = reinterpret_cast<ModuleInfo *>(&start_modinfo);
198  ModuleInfo *lasttag = reinterpret_cast<ModuleInfo *>(&end_modinfo);
199 
200  // Call static constructors before we start. If we don't... there won't be
201  // any properly initialised ModuleInfo structures :)
202  uintptr_t *iterator = &start_module_ctors;
203  while (iterator < &end_module_ctors)
204  {
205  void (*fp)(void) = reinterpret_cast<void (*)(void)>(*iterator);
206  fp();
207  iterator++;
208  }
209 
210  // Run through all the modules
211  while (tags < lasttag)
212  {
213  if (tags->tag == MODULE_TAG)
214  {
216  }
217 
218  tags++;
219  }
220 
222 #else
223  BootstrapStruct_t bsInf = *static_cast<BootstrapStruct_t *>(inf);
224 
228  Archive initrd(bsInf.getInitrdAddress(), bsInf.getInitrdSize());
229 
230  size_t nFiles = initrd.getNumFiles();
231  g_BootProgressTotal =
232  nFiles * 2; // Each file has to be preloaded and executed.
233  for (size_t i = 0; i < nFiles; i++)
234  {
237  reinterpret_cast<uint8_t *>(initrd.getFile(i)),
238  initrd.getFileSize(i));
240  WARNING("A loaded module disabled interrupts.");
241  }
242 
243  // Start any modules we can run already.
245 
246  // Wait for all modules to finish loading before we continue.
248 
249  // The initialisation is done here, unmap/free the .init section and on
250  // x86/64 the identity mapping of 0-4MB NOTE: BootstrapStruct_t unusable
251  // after this point
253 
254 #endif
255 
256  if (KernelElf::instance().hasPendingModules())
257  {
258  FATAL("At least one module's dependencies were never met.");
259  }
260 
261 #ifdef HOSTED
262  fprintf(stderr, "Pedigree has started: all modules have been loaded.\n");
263 #endif
264 
265  return 0;
266 }
267 
269 extern "C" void _main(BootstrapStruct_t &bsInf) USED NORETURN;
270 extern "C" void _main(BootstrapStruct_t &bsInf)
271 {
272  TRACE("constructors");
273 
274  // Firstly call the constructors of all global objects.
275  initialiseConstructors();
276 
277  g_pBootstrapInfo = &bsInf;
278 
279 #ifdef TRACK_LOCKS
280  g_LocksCommand.setReady();
281 #endif
282 
283  TRACE("Processor init");
284 
285  // Initialise the processor-specific interface
286  Processor::initialise1(bsInf);
287 
288  TRACE("log init");
289 
290  // Initialise the kernel log
292 
293  TRACE("Machine init");
294 
295  // Initialise the machine-specific interface
296  Machine &machine = Machine::instance();
297  Machine::instance().initialiseDeviceTree();
298 
299  machine.initialise();
300 
301 #if defined(DEBUGGER)
302  TRACE("Debugger init");
304 #endif
305 
306  TRACE("Machine init2");
307 
308  machine.initialise2();
309 
310  TRACE("Log init2");
311 
312  // Initialise the kernel log's callbacks
314 
315  TRACE("Processor init2");
316 
317  // Initialise the processor-specific interface
318  // Bootup of the other Application Processors and related tasks
319  Processor::initialise2(bsInf);
320 
321  TRACE("Machine init3");
322 
323  machine.initialise3();
324 
325  TRACE("KernelElf init");
326 
327  // Initialise the Kernel Elf class
328  if (KernelElf::instance().initialise(bsInf) == false)
329  panic("KernelElf::initialise() failed");
330 
331 #ifndef STATIC_DRIVERS // initrd needed if drivers aren't statically linked.
332  if (bsInf.isInitrdLoaded() == false)
333  panic("Initrd module not loaded!");
334 #endif
335 
336  TRACE("kernel syscall init");
337 
338  KernelCoreSyscallManager::instance().initialise();
339 
340  TRACE("initial init done, enabling interrupts");
341 
343 
344  TRACE("bootIO init");
345 
346  // Initialise the boot output.
347  bootIO.initialise();
348 
349  // Spew out a starting string.
350  HugeStaticString str, ident;
351  str += "Pedigree - revision ";
352  str += g_pBuildRevision;
353 #ifndef DONT_LOG_TO_SERIAL
354  str += "\r\n=======================\r\n";
355 #else
356  str += "\n=======================\n";
357 #endif
358  bootIO.write(str, BootIO::White, BootIO::Black);
359 
360  str.clear();
361  str += "Built at ";
362  str += g_pBuildTime;
363  str += " by ";
364  str += g_pBuildUser;
365  str += " on ";
366  str += g_pBuildMachine;
367 #ifndef DONT_LOG_TO_SERIAL
368  str += "\r\n";
369 #else
370  str += "\n";
371 #endif
372  bootIO.write(str, BootIO::LightGrey, BootIO::Black);
373 
374  str.clear();
375  str += "Build flags: ";
376  str += g_pBuildFlags;
377 #ifndef DONT_LOG_TO_SERIAL
378  str += "\r\n";
379 #else
380  str += "\n";
381 #endif
382  bootIO.write(str, BootIO::LightGrey, BootIO::Black);
383 
384  str.clear();
385  str += "Processor information: ";
386  Processor::identify(ident);
387  str += ident;
388 #ifndef DONT_LOG_TO_SERIAL
389  str += "\r\n";
390 #else
391  str += "\n";
392 #endif
393  bootIO.write(str, BootIO::LightGrey, BootIO::Black);
394 
395  TRACE("creating graphics service");
396 
397 // Set up the graphics service for drivers to register with
398 #ifndef NOGFX
399  GraphicsService *pService = new GraphicsService;
400  ServiceFeatures *pFeatures = new ServiceFeatures;
401  pFeatures->add(ServiceFeatures::touch);
402  pFeatures->add(ServiceFeatures::probe);
403  ServiceManager::instance().addService(
404  String("graphics"), pService, pFeatures);
405 #endif
406 
407  TRACE("creating memory pressure handlers");
408 
409  // Set up SLAM recovery memory pressure handler.
410  SlamRecovery recovery;
411  MemoryPressureManager::instance().registerHandler(
412  MemoryPressureManager::HighestPriority, &recovery);
413 
414  // Set up the process killer memory pressure handler.
416  MemoryPressureManager::instance().registerHandler(
417  MemoryPressureManager::LowestPriority, &killer);
418 
419  // Set up the global info block manager.
420  TRACE("InfoBlockManager init");
421  InfoBlockManager::instance().initialise();
422 
423  // Bring up the cache subsystem.
424  TRACE("CacheManager init");
425  CacheManager::instance().initialise();
426 
427  // Initialise the input manager
428  TRACE("InputManager init");
430 
431 #ifdef THREADS
432  TRACE("ZombieQueue init");
433  ZombieQueue::instance().initialise();
434 #endif
435 
437 
438  TRACE("starting module load thread");
439 
440 #if defined(THREADS)
441  Thread *pThread = new Thread(
442  Processor::information().getCurrentThread()->getParent(), &loadModules,
443  static_cast<void *>(&bsInf), 0);
444  pThread->detach();
445 #else
446  loadModules(&bsInf);
447 #endif
448 
449 #ifdef DEBUGGER_RUN_AT_START
451 #endif
452 
453  TRACE("becoming idle");
454 
455 #ifdef THREADS
456  // Add us as the idle thread for this CPU.
457  Processor::information().getScheduler().setIdle(
458  Processor::information().getCurrentThread());
459 #endif
460 
461  // This will run when nothing else is available to run
462  for (;;)
463  {
464  // Always enable interrupts in the idle thread, and halt. There is no
465  // point yielding as if this code is running, no other thread is ready
466  // (and cannot be made ready without an interrupt).
469 
470  // Give up our timeslice (needed especially for no-tick scheduling)
472  }
473 }
474 
475 void EXPORTED_PUBLIC system_reset() NORETURN;
476 void system_reset()
477 {
478  NOTICE("Resetting...");
479 
480 #ifdef MULTIPROCESSOR
481  Machine::instance().stopAllOtherProcessors();
482 #endif
483 
484  // No need for user input anymore.
486 
487  // Clean up all loaded modules (unmounts filesystems and the like).
489 
490  NOTICE("All modules unloaded. Running destructors and terminating...");
491  runKernelDestructors();
492 
493  // Clean up the kernel's ELF references (e.g. symbol table).
495 
496  // Bring down the machine abstraction.
497  Machine::instance().deinitialise();
498 
499  // Shut down the various pieces created by Processor
501 
502  // Reset.
504  while (1)
505  ;
506 }
507 
508 const String SlamRecovery::getMemoryPressureDescription()
509 {
510  return String("SLAM recovery; freeing unused slabs.");
511 }
512 
514 {
515  return SlamAllocator::instance().recovery(5) != 0;
516 }
Bootstrap structure passed to the kernel entry point.
void initialise()
Definition: Debugger.cc:107
static bool getInterrupts()
void initialise2()
Definition: Log.cc:138
EXPORTED_PUBLIC void write(T &str, Colour foreColour, Colour backColour)
static void initialise2(const BootstrapStruct_t &Info) INITIALISATION_ONLY
second/last stage in the initialisation of the processor-specific interface
static Debugger & instance()
Definition: Debugger.h:48
Module * loadModule(uint8_t *pModule, size_t len, bool silent=false)
Definition: KernelElf.cc:432
static void initialisationDone()
void waitForModulesToLoad()
Definition: KernelElf.cc:1003
void unloadModules()
Definition: KernelElf.cc:773
Definition: String.h:49
static ProcessorInformation & information()
Definition: Processor.cc:45
virtual bool compact()
static void reset()
static KernelElf & instance()
Definition: KernelElf.h:129
#define WARNING(text)
Definition: Log.h:78
void initialise()
Begins the worker thread.
Definition: InputManager.cc:82
static void initialise1(const BootstrapStruct_t &Info) INITIALISATION_ONLY
first stage in the initialisation of the processor-specific interface
size_t getNumFiles()
Definition: Archive.cc:60
#define NOTICE(text)
Definition: Log.h:74
virtual void initialise2()
Called after debugger startup.
static Scheduler & instance()
Definition: Scheduler.h:48
static KernelCoreSyscallManager & instance()
static void haltUntilInterrupt()
void initialise()
Definition: Cache.cc:78
static void deinitialise()
static void setInterrupts(bool bEnable)
static void identify(HugeStaticString &str)
virtual void initialise3()
Called after processor startup - for thread creation etc.
static EXPORTED_PUBLIC Log & instance()
Definition: Log.cc:108
static void breakpoint()
void initialise1()
Definition: Log.cc:113
static InputManager & instance()
Singleton design.
Definition: InputManager.h:107
static ProcessorId id()
Definition: Processor.cc:40
Definition: Thread.h:54
virtual void initialise()
Definition: RequestQueue.cc:55
void addService(const String &serviceName, Service *s, ServiceFeatures *feats)
void yield()
Definition: Scheduler.cc:135
virtual void add(Type s)
bool detach()
Definition: Thread.cc:885
void shutdown()
Shuts down the worker thread, clears queues, and removes callbacks.
Definition: InputManager.cc:96
void EXPORTED_PUBLIC panic(const char *msg) NORETURN
Definition: panic.cc:121
Definition: BootIO.h:36
#define FATAL(text)
Definition: Log.h:89
void executeModules(bool silent=false, bool progress=true)
Definition: KernelElf.cc:569
virtual void initialise()=0
void initialise()
Definition: BootIO.cc:36
void registerHandler(size_t prio, MemoryPressureHandler *pHandler)
virtual ~KernelElf()
Definition: KernelElf.cc:417