190 lines
3.9 KiB
C++
Executable File
190 lines
3.9 KiB
C++
Executable File
/*
|
|
* \brief Kernel initialization
|
|
* \author Martin Stein
|
|
* \date 2010-07-22
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2010-2013 Genode Labs GmbH
|
|
*
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
* under the terms of the GNU General Public License version 2.
|
|
*/
|
|
|
|
#include <platform/platform.h>
|
|
#include <generic/scheduler.h>
|
|
#include "include/thread.h"
|
|
#include <generic/printf.h>
|
|
#include <generic/verbose.h>
|
|
#include <generic/blocking.h>
|
|
#include <kernel/config.h>
|
|
#include <kernel/syscalls.h>
|
|
#include <cpu/prints.h>
|
|
#include <util/array.h>
|
|
|
|
using namespace Cpu;
|
|
using namespace Kernel;
|
|
|
|
enum { KERNEL__VERBOSE = 0,
|
|
KERNEL__WARNING = 1,
|
|
KERNEL__ERROR = 1 };
|
|
|
|
|
|
/* Can be defined via compiler options */
|
|
extern "C" void ROOTTASK_ENTRY();
|
|
|
|
extern Kernel::Exec_context* _userland_context;
|
|
extern Utcb* _main_utcb_addr;
|
|
|
|
extern int _exit_kernel;
|
|
|
|
|
|
Kernel::Thread_factory* Kernel::thread_factory()
|
|
{
|
|
static Thread_factory _tf;
|
|
return &_tf;
|
|
}
|
|
|
|
|
|
namespace Kernel {
|
|
|
|
static Utcb _roottask_utcb, _idle_utcb;
|
|
|
|
void _roottask_thread__verbose__creation(addr_t vip, addr_t vsp, Utcb* vutcb)
|
|
{
|
|
if (!KERNEL__VERBOSE) return;
|
|
printf("Kernel::roottask_thread, roottask thread created, "
|
|
"printing constraints\n");
|
|
printf(" vip=0x%8X, vsp=0x%8X, vutcb=0x%8X\n",
|
|
(uint32_t)vip, (uint32_t)vsp, (uint32_t)vutcb);
|
|
}
|
|
|
|
|
|
void idle()
|
|
{
|
|
while(1);
|
|
}
|
|
|
|
|
|
Thread *idle_thread()
|
|
{
|
|
enum{
|
|
IDLE_STACK_WORD_SIZE=32,
|
|
IDLE_TID=1,
|
|
};
|
|
|
|
static word_t _it_stack[IDLE_STACK_WORD_SIZE];
|
|
static Thread *_it = thread_factory()->get(IDLE_TID);
|
|
|
|
if (!_it) {
|
|
|
|
Thread_factory::Create_argument itca;
|
|
|
|
itca.tid = (Thread_id)IDLE_TID;
|
|
itca.pid = (Protection_id)Roottask::PROTECTION_ID;
|
|
itca.utcb = &_idle_utcb;
|
|
itca.pager_tid = INVALID_THREAD_ID;
|
|
itca.vsp = (addr_t)&LAST_ARRAY_ELEM(_it_stack);
|
|
itca.vip = (addr_t)&idle;
|
|
itca.is_privileged = true;
|
|
|
|
_it = thread_factory()->create(&itca, true);
|
|
}
|
|
return _it;
|
|
}
|
|
|
|
|
|
Thread *roottask_thread()
|
|
{
|
|
static word_t _rt_stack[Roottask::MAIN_STACK_SIZE/WORD_SIZE];
|
|
static Thread *_rt = thread_factory()->get(Roottask::MAIN_THREAD_ID);
|
|
|
|
if (!_rt) {
|
|
|
|
Thread_factory::Create_argument rtca;
|
|
|
|
rtca.tid = (Thread_id)Roottask::MAIN_THREAD_ID;
|
|
rtca.pid = (Protection_id)Roottask::PROTECTION_ID;
|
|
rtca.utcb = &_roottask_utcb;
|
|
rtca.pager_tid = INVALID_THREAD_ID;
|
|
rtca.vsp = (addr_t)&LAST_ARRAY_ELEM(_rt_stack);
|
|
rtca.vip = (addr_t)&ROOTTASK_ENTRY;
|
|
rtca.is_privileged = true;
|
|
_main_utcb_addr = rtca.utcb;
|
|
|
|
_rt = thread_factory()->create(&rtca, false);
|
|
if (_rt)
|
|
_roottask_thread__verbose__creation(
|
|
rtca.vip, rtca.vsp, rtca.utcb);
|
|
}
|
|
return _rt;
|
|
}
|
|
}
|
|
|
|
|
|
Platform *Kernel::platform() { static Platform _p; return &_p; }
|
|
|
|
|
|
Scheduler *Kernel::scheduler()
|
|
{
|
|
static bool _init_scheduler = false;
|
|
static Scheduler _s = Scheduler(platform(),
|
|
platform()->timer(),
|
|
idle_thread());
|
|
if(_init_scheduler){ return &_s; }
|
|
_s.add(roottask_thread());
|
|
_init_scheduler = true;
|
|
return &_s;
|
|
}
|
|
|
|
|
|
Tlb *Kernel::tlb() { return platform()->tlb(); }
|
|
|
|
|
|
Irq_controller * const Kernel::irq_controller()
|
|
{
|
|
return platform()->irq_controller();
|
|
}
|
|
|
|
|
|
Irq_allocator * const Kernel::irq_allocator()
|
|
{
|
|
static Irq_allocator _ia =
|
|
Irq_allocator(platform()->irq_controller());
|
|
return &_ia;
|
|
}
|
|
|
|
|
|
unsigned Kernel::word_width() { return Platform::WORD_WIDTH; }
|
|
|
|
|
|
void Kernel::halt() { platform()->halt(); }
|
|
|
|
|
|
Kernel::Kernel_entry *Kernel::kernel_entry_event()
|
|
{
|
|
static Kernel_entry _ke;
|
|
return &_ke;
|
|
}
|
|
|
|
|
|
Kernel::Kernel_exit *Kernel::kernel_exit_event()
|
|
{
|
|
static Kernel_exit _kx;
|
|
return &_kx;
|
|
}
|
|
|
|
|
|
/**
|
|
* Kernel main routine, gets called by crt0_kernel.s
|
|
*/
|
|
extern "C" void _kernel()
|
|
{
|
|
kernel_entry_event()->on_occurence();
|
|
|
|
scheduler()->run();
|
|
|
|
kernel_exit_event()->on_occurence();
|
|
}
|
|
|