2 * (c) 2008-2009 Technische Universität Dresden
3 * This file is part of TUD:OS and distributed under the terms of the
4 * GNU General Public License 2.
5 * Please see the COPYING-GPL-2 file for details.
8 #include <l4/crtn/crt0.h>
9 #include <l4/util/util.h>
10 #include <l4/sigma0/sigma0.h>
13 #include <l4/sys/utcb.h>
14 #include <l4/sys/debugger.h>
15 #include <l4/sys/scheduler>
16 #include <l4/sys/thread>
18 #include <l4/cxx/exceptions>
19 #include <l4/cxx/ipc_stream>
21 #include <l4/cxx/iostream>
22 #include <l4/cxx/l4iostream>
24 #include <l4/util/mb_info.h>
32 #include "exception.h"
34 #include "loader_elf.h"
36 #include "name_space.h"
37 #include "page_alloc.h"
40 #include "dataspace_static.h"
47 using L4Re::Util::Names::Obj;
49 static L4Re::Env my_env;
52 extern "C" void _exit(int status);
54 void _exit(int status)
56 L4::cout << "MOE: is terminating with " << status << ", very bad......\n";
60 unsigned Moe::l4re_dbg = Dbg::Warn;
61 unsigned Moe::ldr_flags;
64 static Dbg info(Dbg::Info);
65 static Dbg boot(Dbg::Boot);
66 static Dbg warn(Dbg::Warn);
69 l4_kernel_info_t const *map_kip()
71 _current_kip = l4sigma0_map_kip(Sigma0_cap, 0, L4_WHOLE_ADDRESS_SPACE);
75 Err(Err::Fatal).printf("could not map KIP\n");
80 boot.printf("KIP @%p\n",kip());
87 l4util_mb_info_t const *_mbi_ = (l4util_mb_info_t const *)kip()->user_ptr;
88 boot.printf("mbi @%p\n", _mbi_);
89 l4util_mb_mod_t const *modules = (l4util_mb_mod_t const *)_mbi_->mods_addr;
90 unsigned num_modules = _mbi_->mods_count;
93 for (unsigned mod = 0; mod < num_modules; ++mod)
95 if (strstr((char const *)modules[mod].cmdline, PROG))
97 cmdline = (char *)modules[mod].cmdline;
103 cmdline = (char *)_mbi_->cmdline;
105 static char default_cmdline[] = "";
109 Dbg(Dbg::Warn).printf("no command line found, use default!\n");
110 cmdline = default_cmdline;
118 static void find_memory()
120 using Moe::Pages::pages;
122 l4_addr_t min_addr = ~0UL;
123 l4_addr_t max_addr = 0;
125 for (unsigned order = 30 /*1G*/; order >= L4_LOG2_PAGESIZE; --order)
127 while (!l4sigma0_map_anypage(Sigma0_cap, 0, L4_WHOLE_ADDRESS_SPACE,
130 unsigned long size = 1UL << order;
140 if (addr < min_addr) min_addr = addr;
141 if (addr + size > max_addr) max_addr = addr + size;
143 Single_page_alloc_base::_free((void*)addr, size, true);
147 info.printf("found %ld KByte free memory\n",
148 Single_page_alloc_base::_avail() / 1024);
150 // adjust min_addr and max_addr to also contain boot modules
151 L4::Kip::Mem_desc const *md = L4::Kip::Mem_desc::first(kip());
152 L4::Kip::Mem_desc const *end = md + L4::Kip::Mem_desc::count(kip());
154 for (; md < end; ++md)
156 if (md->is_virtual())
159 L4::Kip::Mem_desc::Mem_type type = md->type();
160 unsigned long end = l4_round_page(md->end());
161 unsigned long start = l4_trunc_page(md->start());
164 case L4::Kip::Mem_desc::Bootloader:
165 if (start < min_addr)
170 case L4::Kip::Mem_desc::Conventional:
171 case L4::Kip::Mem_desc::Reserved:
172 case L4::Kip::Mem_desc::Dedicated:
173 case L4::Kip::Mem_desc::Arch:
174 case L4::Kip::Mem_desc::Shared:
180 assert(max_addr > min_addr);
181 l4_addr_t total_pages = (max_addr - min_addr) >> L4_PAGESHIFT;
185 pages = (typeof(pages))Single_page_alloc_base::_alloc(sizeof(*pages) * total_pages);
189 Err(Err::Fatal).printf("could not allocate page array, halt\n");
193 memset(pages, 0, sizeof(*pages) * total_pages);
195 Moe::Pages::base_addr = min_addr;
196 Moe::Pages::max_addr = max_addr;
198 info.printf("found RAM from %lx to %lx\n"
199 "allocated %ld KByte for the page array @%p\n",
201 sizeof(*pages) * total_pages / 1024, pages);
207 l4_utcb_t *u = l4_utcb();
208 boot.printf("UTCB @%p\n", u);
218 kip_ds = new Moe::Dataspace_static(const_cast<l4_kernel_info_t*>(kip()), L4_PAGESIZE, 0);
221 Err(Err::Fatal).printf("could not allocate dataspace for KIP!\n");
225 object_pool.cap_alloc()->alloc(kip_ds);
229 static void GC_CALLBACK finalization_notifier()
232 l4_msg_regs_t *mr = l4_utcb_mr();
234 memcpy(&b, mr->mr, sizeof(l4_msg_regs_t));
235 GC_invoke_finalizers();
236 memcpy(mr->mr, &b, sizeof(l4_msg_regs_t));
240 public L4::Ipc_svr::Ignore_errors,
241 public L4::Ipc_svr::Default_timeout,
242 public L4::Ipc_svr::Compound_reply
245 static void setup_wait(L4::Ipc_istream &istr, L4::Ipc_svr::Reply_mode)
247 GC_collect_a_little();
249 istr << L4::Small_buf(Rcv_cap << L4_CAP_SHIFT, L4_RCV_ITEM_LOCAL_ID);
250 l4_utcb_br_u(istr.utcb())->bdr = 0;
254 template< typename Reg >
261 int dispatch(l4_umword_t obj, L4::Ipc_iostream &ios)
265 typename Reg::Value *o = 0;
269 l4_utcb_t *u = l4_utcb();
270 L4::cout << L4::hex << "UTCB: " << u->values[0]
271 << "(" << op << "):" << u->values[1]
272 << "(" << obj << ")\n";
275 Dbg dbg(Dbg::Server);
277 dbg.printf("tag=%lx (proto=%lx) obj=%lx", tag.raw,
280 if (tag.is_exception())
283 Dbg(Dbg::Exceptions).printf("unhandled exception...\n");
288 // L4::cout << "ROOT: CALL(" << (void*)obj<< "): " << op << "...\n";
289 o = r.find(obj & ~3UL);
291 // L4::cout << "ROOT: obj=" << o << "\n";
293 // enter_kdebug("a");
297 dbg.cprintf(": invalid object\n");
301 dbg.cprintf(": object is a %s\n", typeid(*o).name());
304 int res = o->dispatch(obj, ios);
305 dbg.printf("reply = %d\n", res);
308 catch (L4::Runtime_error &e)
310 int res = e.err_no();
311 dbg.printf("reply(excption) = %d\n", res);
316 Dbg(Dbg::Warn).printf("Invalid message (tag.label=%ld)\n", tag.label());
322 static cxx::String _init_prog = "rom/ned";
327 void (*hdl)(cxx::String const &);
330 struct Dbg_bits { char const *tag; unsigned long bits; };
331 static Dbg_bits const dbb[] =
332 {{"info", Dbg::Info},
336 {"server", Dbg::Server},
337 {"svr", Dbg::Server},
338 {"exceptions", Dbg::Exceptions},
339 {"exc", Dbg::Exceptions},
342 {"loader", Dbg::Loader},
343 {"ldr", Dbg::Loader},
344 {"ns", Dbg::Name_space},
348 static Dbg_bits const ldr_flag_bits[] =
349 {{"pre_alloc", L4RE_AUX_LDR_FLAG_EAGER_MAP},
350 {"eager_map", L4RE_AUX_LDR_FLAG_EAGER_MAP},
351 {"all_segs_cow", L4RE_AUX_LDR_FLAG_ALL_SEGS_COW},
352 {"pinned_segs", L4RE_AUX_LDR_FLAG_PINNED_SEGS},
356 static unsigned long parse_flags(cxx::String const &_args, Dbg_bits const *dbb,
357 cxx::String const &opt)
359 cxx::String args = _args;
360 unsigned long lvl = 0;
363 cxx::String::Index c = args.find(",|+");
364 cxx::String a = args.head(c);
369 args = args.substr(c+1);
372 for (b = &dbb[0]; b->tag; ++b)
383 warn.printf("ignore unkown argument for %.*s: '%.*s'\n",
384 opt.len(), opt.start(), a.len(), a.start());
391 static void hdl_debug(cxx::String const &args)
393 unsigned long lvl = parse_flags(args, dbb, "--debug");
397 static void hdl_init(cxx::String const &args)
402 static void hdl_l4re_dbg(cxx::String const &args)
404 unsigned long lvl = parse_flags(args, dbb, "--l4re-dbg");
408 static void hdl_ldr_flags(cxx::String const &args)
410 unsigned long lvl = parse_flags(args, ldr_flag_bits, "--ldr-flags");
411 Moe::ldr_flags = lvl;
416 static Get_opt const _options[] = {
417 {"--debug=", hdl_debug },
418 {"--init=", hdl_init },
419 {"--l4re-dbg=", hdl_l4re_dbg },
420 {"--ldr-flags=", hdl_ldr_flags },
425 parse_long_option(cxx::String const &o)
428 for (Get_opt const *opt = _options; opt->tag; ++opt)
430 if (o.starts_with(opt->tag))
432 opt->hdl(o.substr(strlen(opt->tag)));
437 warn.printf("unknown command-line option '%.*s'\n", o.len(), o.start());
441 parse_option(cxx::String const &o)
445 warn.printf("empty command-line option '%.*s'\n", o.len(), o.start());
451 parse_long_option(o);
455 for (cxx::String::Index s = o.start() + 1; !o.eof(s); ++s)
460 warn.printf("unkown command-line option '%c'\n", o[s]);
468 static Elf_loader elf_loader;
470 static L4::Server<Loop_hooks> server(l4_utcb());
473 static void init_env()
475 // setup log capability in the global env, so that the libc backend can use
476 // L4::Env::env()->log() to send logoutput to
477 l4re_global_env = reinterpret_cast<l4re_env_t*>(&my_env);
478 my_env.factory(L4_BASE_FACTORY_CAP);
479 my_env.log(L4_BASE_LOG_CAP);
480 my_env.scheduler(L4_BASE_SCHEDULER_CAP);
483 static __attribute__((used,section(".preinit_array")))
484 const void *pre_init_env = (void *)init_env;
486 int main(int argc, char**argv)
488 (void)argc; (void)argv;
489 Dbg::set_level(Dbg::Info | Dbg::Warn);
490 //Dbg::level |= Dbg::Boot;
492 info.printf("Hello world\n");
496 Env::env()->scheduler()->run_thread(L4::Cap<L4::Thread>(L4_BASE_THREAD_CAP), l4_sched_param(0xff));
499 #if 0 // map RO stuff RO, we'll see write pagefaults if someone write to our
500 // RO segments later on
501 extern char _stext[];
502 extern char _etext[];
504 for (unsigned long i = (unsigned long)_stext; i < (unsigned long)_etext; i+= L4_PAGESIZE)
506 l4_task_unmap(l4_utcb(), L4_BASE_TASK_CAP, l4_fpage(i, L4_PAGESHIFT, L4_FPAGE_W), L4_FP_ALL_SPACES);
514 Moe::Boot_fs::init_stage1();
517 extern unsigned page_alloc_debug;
518 page_alloc_debug = 1;
520 GC_set_dont_expand(1);
521 GC_set_finalizer_notifier(finalization_notifier);
522 GC_set_finalize_on_demand(1);
524 Moe::Boot_fs::init_stage2();
525 init_vesa_fb((l4util_mb_info_t*)kip()->user_ptr);
527 root_name_space_obj = object_pool.cap_alloc()->alloc(root_name_space());
530 Region_map::init_limits();
532 object_pool.cap_alloc()->alloc(Allocator::root_allocator());
534 l4_debugger_set_object_name(L4_BASE_TASK_CAP, "moe");
535 l4_debugger_set_object_name(L4_BASE_THREAD_CAP, "moe");
536 l4_debugger_set_object_name(L4_BASE_PAGER_CAP, "moe->s0");
538 root_name_space()->register_obj("log", Obj(Obj::F_rw, L4_BASE_LOG_CAP));
539 root_name_space()->register_obj("icu", Obj(Obj::F_rw, L4_BASE_ICU_CAP));
540 root_name_space()->register_obj("sigma0", Obj(Obj::F_trusted | Obj::F_rw, L4_BASE_PAGER_CAP));
541 root_name_space()->register_obj("mem", Obj(Obj::F_trusted | Obj::F_rw, Allocator::root_allocator()));
543 char *cmdline = my_cmdline();
545 info.printf("cmdline: %s\n", cmdline);
547 bool skip_argv0 = true;
548 cxx::Pair<cxx::String, cxx::String> a;
549 for (a = next_arg(cmdline); !a.first.empty(); a = next_arg(a.second))
557 if (a.first[0] != '-') // not an option start init
559 elf_loader.start(_init_prog, cxx::String(a.first.start(), a.second.end()));
565 elf_loader.start(_init_prog, a.second);
569 parse_option(a.first);
573 elf_loader.start(_init_prog, cxx::String(""));
575 // dump name space information
576 if (boot.is_active())
578 boot.printf("dump of root name space:\n");
579 root_name_space()->dump(1);
582 // we handle our exceptions ourselves
583 server.loop_noexc(My_dispatcher<L4::Basic_registry>());
585 catch (L4::Out_of_memory const &e)
587 Err(Err::Fatal).printf("Memory exhausted and not handled\n");
588 L4::cerr << "FATAL exception in MOE:\n"
589 << e << "... terminated\n";
591 catch (L4::Runtime_error const &e)
593 L4::cerr << "FATAL exception in MOE:\n"
594 << e << "... terminated\n";