2 * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
3 * Alexander Warg <warg@os.inf.tu-dresden.de>
4 * economic rights: Technische Universität Dresden (Germany)
6 * This file is part of TUD:OS and distributed under the terms of the
7 * GNU General Public License 2.
8 * Please see the COPYING-GPL-2 file for details.
11 #include <l4/crtn/crt0.h>
12 #include <l4/util/util.h>
13 #include <l4/sigma0/sigma0.h>
16 #include <l4/sys/utcb.h>
17 #include <l4/sys/debugger.h>
18 #include <l4/sys/scheduler>
19 #include <l4/sys/thread>
21 #include <l4/cxx/exceptions>
22 #include <l4/cxx/ipc_stream>
24 #include <l4/cxx/iostream>
25 #include <l4/cxx/l4iostream>
27 #include <l4/util/mb_info.h>
35 #include "exception.h"
37 #include "loader_elf.h"
39 #include "name_space.h"
40 #include "page_alloc.h"
43 #include "dataspace_static.h"
50 using L4Re::Util::Names::Obj;
52 static L4Re::Env my_env;
55 extern "C" void _exit(int status);
57 void _exit(int status)
59 L4::cout << "MOE: is terminating with " << status << ", very bad......\n";
63 unsigned Moe::l4re_dbg = Dbg::Warn;
64 unsigned Moe::ldr_flags;
67 static Dbg info(Dbg::Info);
68 static Dbg boot(Dbg::Boot);
69 static Dbg warn(Dbg::Warn);
72 l4_kernel_info_t const *map_kip()
74 // map the KIP 1:1, because moe hast all memory 1:1 and the kip would
75 // possibly overlap with 1:1 memory if we have lots of RAM.
76 _current_kip = l4sigma0_map_kip(Sigma0_cap, 0, L4_WHOLE_ADDRESS_SPACE);
80 Err(Err::Fatal).printf("could not map KIP\n");
84 boot.printf("KIP @%p\n", kip());
91 l4util_mb_info_t const *_mbi_ = (l4util_mb_info_t const *)(unsigned long)kip()->user_ptr;
92 boot.printf("mbi @%p\n", _mbi_);
93 l4util_mb_mod_t const *modules = (l4util_mb_mod_t const *)(unsigned long)_mbi_->mods_addr;
94 unsigned num_modules = _mbi_->mods_count;
97 for (unsigned mod = 0; mod < num_modules; ++mod)
98 if (strstr((char const *)(unsigned long)modules[mod].cmdline, PROG))
100 cmdline = (char *)(unsigned long)modules[mod].cmdline;
105 cmdline = (char *)(unsigned long)_mbi_->cmdline;
107 static char default_cmdline[] = "";
111 Dbg(Dbg::Warn).printf("No command line found, using default!\n");
112 cmdline = default_cmdline;
120 static void find_memory()
122 using Moe::Pages::pages;
124 l4_addr_t min_addr = ~0UL;
125 l4_addr_t max_addr = 0;
127 for (unsigned order = 30 /*1G*/; order >= L4_LOG2_PAGESIZE; --order)
129 while (!l4sigma0_map_anypage(Sigma0_cap, 0, L4_WHOLE_ADDRESS_SPACE,
132 unsigned long size = 1UL << order;
142 if (addr < min_addr) min_addr = addr;
143 if (addr + size > max_addr) max_addr = addr + size;
145 Single_page_alloc_base::_free((void*)addr, size, true);
149 info.printf("found %ld KByte free memory\n",
150 Single_page_alloc_base::_avail() / 1024);
152 // adjust min_addr and max_addr to also contain boot modules
153 L4::Kip::Mem_desc const *md = L4::Kip::Mem_desc::first(kip());
154 L4::Kip::Mem_desc const *end = md + L4::Kip::Mem_desc::count(kip());
156 for (; md < end; ++md)
158 if (md->is_virtual())
161 L4::Kip::Mem_desc::Mem_type type = md->type();
162 unsigned long end = l4_round_page(md->end());
163 unsigned long start = l4_trunc_page(md->start());
166 case L4::Kip::Mem_desc::Bootloader:
167 if (start < min_addr)
172 case L4::Kip::Mem_desc::Conventional:
173 case L4::Kip::Mem_desc::Reserved:
174 case L4::Kip::Mem_desc::Dedicated:
175 case L4::Kip::Mem_desc::Arch:
176 case L4::Kip::Mem_desc::Shared:
182 assert(max_addr > min_addr);
183 l4_addr_t total_pages = (max_addr - min_addr) >> L4_PAGESHIFT;
187 pages = (typeof(pages))Single_page_alloc_base::_alloc(sizeof(*pages) * total_pages);
191 Err(Err::Fatal).printf("could not allocate page array, halt\n");
195 memset(pages, 0, sizeof(*pages) * total_pages);
197 Moe::Pages::base_addr = min_addr;
198 Moe::Pages::max_addr = max_addr;
200 info.printf("found RAM from %lx to %lx\n",
202 info.printf("allocated %ld KByte for the page array @%p\n",
203 sizeof(*pages) * total_pages / 1024, pages);
206 l4_addr_t Moe::Virt_limit::start;
207 l4_addr_t Moe::Virt_limit::end;
212 L4::Kip::Mem_desc *md = L4::Kip::Mem_desc::first(const_cast<l4_kernel_info_t*>(kip()));
213 unsigned long cnt = L4::Kip::Mem_desc::count(const_cast<l4_kernel_info_t*>(kip()));
215 for (L4::Kip::Mem_desc *m = md; m < md + cnt; ++m)
217 if (m->type() != L4::Kip::Mem_desc::Conventional || !m->is_virtual())
220 Moe::Virt_limit::start = m->start();
221 Moe::Virt_limit::end = m->end();
224 info.printf("virtual user address space [%lx-%lx]\n",
225 Moe::Virt_limit::start,
226 Moe::Virt_limit::end);
232 l4_utcb_t *u = l4_utcb();
233 boot.printf("UTCB @%p\n", u);
241 kip_ds = new Moe::Dataspace_static(const_cast<l4_kernel_info_t*>(kip()), L4_PAGESIZE, 0);
244 Err(Err::Fatal).printf("could not allocate dataspace for KIP!\n");
248 object_pool.cap_alloc()->alloc(kip_ds);
252 static void GC_CALLBACK finalization_notifier()
255 l4_msg_regs_t *mr = l4_utcb_mr();
257 memcpy(&b, mr->mr, sizeof(l4_msg_regs_t));
258 GC_invoke_finalizers();
259 memcpy(mr->mr, &b, sizeof(l4_msg_regs_t));
263 public L4::Ipc_svr::Ignore_errors,
264 public L4::Ipc_svr::Default_timeout,
265 public L4::Ipc_svr::Compound_reply
268 static void setup_wait(L4::Ipc::Istream &istr, L4::Ipc_svr::Reply_mode)
270 GC_collect_a_little();
272 istr << L4::Ipc::Small_buf(Rcv_cap << L4_CAP_SHIFT, L4_RCV_ITEM_LOCAL_ID);
273 l4_utcb_br_u(istr.utcb())->bdr = 0;
277 template< typename Reg >
284 int dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios)
288 typename Reg::Value *o = 0;
292 l4_utcb_t *u = l4_utcb();
293 L4::cout << L4::hex << "UTCB: " << u->values[0]
294 << "(" << op << "):" << u->values[1]
295 << "(" << obj << ")\n";
298 Dbg dbg(Dbg::Server);
300 dbg.printf("tag=%lx (proto=%lx) obj=%lx", tag.raw,
303 if (tag.is_exception())
306 Dbg(Dbg::Exceptions).printf("unhandled exception...\n");
311 // L4::cout << "ROOT: CALL(" << (void*)obj<< "): " << op << "...\n";
312 o = r.find(obj & ~3UL);
314 // L4::cout << "ROOT: obj=" << o << "\n";
316 // enter_kdebug("a");
320 dbg.cprintf(": invalid object\n");
324 dbg.cprintf(": object is a %s\n", typeid(*o).name());
327 int res = o->dispatch(obj, ios);
328 dbg.printf("reply = %d\n", res);
331 catch (L4::Runtime_error &e)
333 int res = e.err_no();
334 dbg.printf("reply(excption) = %d\n", res);
339 Dbg(Dbg::Warn).printf("Invalid message (tag.label=%ld)\n", tag.label());
345 static cxx::String _init_prog = "rom/ned";
350 void (*hdl)(cxx::String const &);
353 struct Dbg_bits { char const *tag; unsigned long bits; };
354 static Dbg_bits const dbb[] =
355 {{"info", Dbg::Info},
359 {"server", Dbg::Server},
360 {"svr", Dbg::Server},
361 {"exceptions", Dbg::Exceptions},
362 {"exc", Dbg::Exceptions},
365 {"loader", Dbg::Loader},
366 {"ldr", Dbg::Loader},
367 {"ns", Dbg::Name_space},
371 static Dbg_bits const ldr_flag_bits[] =
372 {{"pre_alloc", L4RE_AUX_LDR_FLAG_EAGER_MAP},
373 {"eager_map", L4RE_AUX_LDR_FLAG_EAGER_MAP},
374 {"all_segs_cow", L4RE_AUX_LDR_FLAG_ALL_SEGS_COW},
375 {"pinned_segs", L4RE_AUX_LDR_FLAG_PINNED_SEGS},
379 static unsigned long parse_flags(cxx::String const &_args, Dbg_bits const *dbb,
380 cxx::String const &opt)
382 cxx::String args = _args;
383 unsigned long lvl = 0;
386 cxx::String::Index c = args.find(",|+");
387 cxx::String a = args.head(c);
392 args = args.substr(c+1);
395 for (b = &dbb[0]; b->tag; ++b)
406 warn.printf("ignore unkown argument for %.*s: '%.*s'\n",
407 opt.len(), opt.start(), a.len(), a.start());
414 static void hdl_debug(cxx::String const &args)
416 unsigned long lvl = parse_flags(args, dbb, "--debug");
420 static void hdl_init(cxx::String const &args)
425 static void hdl_l4re_dbg(cxx::String const &args)
427 unsigned long lvl = parse_flags(args, dbb, "--l4re-dbg");
431 static void hdl_ldr_flags(cxx::String const &args)
433 unsigned long lvl = parse_flags(args, ldr_flag_bits, "--ldr-flags");
434 Moe::ldr_flags = lvl;
439 static Get_opt const _options[] = {
440 {"--debug=", hdl_debug },
441 {"--init=", hdl_init },
442 {"--l4re-dbg=", hdl_l4re_dbg },
443 {"--ldr-flags=", hdl_ldr_flags },
448 parse_long_option(cxx::String const &o)
451 for (Get_opt const *opt = _options; opt->tag; ++opt)
453 if (o.starts_with(opt->tag))
455 opt->hdl(o.substr(strlen(opt->tag)));
460 warn.printf("unknown command-line option '%.*s'\n", o.len(), o.start());
464 parse_option(cxx::String const &o)
468 warn.printf("empty command-line option '%.*s'\n", o.len(), o.start());
474 parse_long_option(o);
478 for (cxx::String::Index s = o.start() + 1; !o.eof(s); ++s)
483 warn.printf("unkown command-line option '%c'\n", o[s]);
491 static Elf_loader elf_loader;
493 static L4::Server<Loop_hooks> server(l4_utcb());
496 static void init_env()
498 // setup log capability in the global env, so that the libc backend can use
499 // L4::Env::env()->log() to send logoutput to
500 l4re_global_env = reinterpret_cast<l4re_env_t*>(&my_env);
501 my_env.factory(L4_BASE_FACTORY_CAP);
502 my_env.log(L4_BASE_LOG_CAP);
503 my_env.scheduler(L4_BASE_SCHEDULER_CAP);
506 static __attribute__((used,section(".preinit_array")))
507 const void *pre_init_env = (void *)init_env;
509 int main(int argc, char**argv)
511 (void)argc; (void)argv;
512 Dbg::set_level(Dbg::Info | Dbg::Warn);
513 //Dbg::level |= Dbg::Boot;
515 info.printf("Hello world\n");
519 Env::env()->scheduler()->run_thread(L4::Cap<L4::Thread>(L4_BASE_THREAD_CAP), l4_sched_param(0xff));
522 #if 0 // map RO stuff RO, we'll see write pagefaults if someone write to our
523 // RO segments later on
524 extern char _stext[];
525 extern char _etext[];
527 for (unsigned long i = (unsigned long)_stext; i < (unsigned long)_etext; i+= L4_PAGESIZE)
529 l4_task_unmap(l4_utcb(), L4_BASE_TASK_CAP, l4_fpage(i, L4_PAGESHIFT, L4_FPAGE_W), L4_FP_ALL_SPACES);
537 Moe::Boot_fs::init_stage1();
541 extern unsigned page_alloc_debug;
542 page_alloc_debug = 1;
544 GC_set_dont_expand(1);
545 GC_set_finalizer_notifier(finalization_notifier);
546 GC_set_finalize_on_demand(1);
548 Moe::Boot_fs::init_stage2();
549 init_vesa_fb((l4util_mb_info_t*)kip()->user_ptr);
551 root_name_space_obj = object_pool.cap_alloc()->alloc(root_name_space());
555 object_pool.cap_alloc()->alloc(Allocator::root_allocator());
557 l4_debugger_set_object_name(L4_BASE_TASK_CAP, "moe");
558 l4_debugger_set_object_name(L4_BASE_THREAD_CAP, "moe");
559 l4_debugger_set_object_name(L4_BASE_PAGER_CAP, "moe->s0");
561 root_name_space()->register_obj("log", Obj(Obj::F_rw, L4_BASE_LOG_CAP));
562 root_name_space()->register_obj("icu", Obj(Obj::F_rw, L4_BASE_ICU_CAP));
563 root_name_space()->register_obj("sigma0", Obj(Obj::F_trusted | Obj::F_rw, L4_BASE_PAGER_CAP));
564 root_name_space()->register_obj("mem", Obj(Obj::F_trusted | Obj::F_rw, Allocator::root_allocator()));
566 char *cmdline = my_cmdline();
568 info.printf("cmdline: %s\n", cmdline);
570 bool skip_argv0 = true;
571 cxx::Pair<cxx::String, cxx::String> a;
572 for (a = next_arg(cmdline); !a.first.empty(); a = next_arg(a.second))
580 if (a.first[0] != '-') // not an option start init
582 elf_loader.start(_init_prog, cxx::String(a.first.start(), a.second.end()));
588 elf_loader.start(_init_prog, a.second);
592 parse_option(a.first);
596 elf_loader.start(_init_prog, cxx::String(""));
598 // dump name space information
599 if (boot.is_active())
601 boot.printf("dump of root name space:\n");
602 root_name_space()->dump(1);
605 // we handle our exceptions ourselves
606 server.loop_noexc(My_dispatcher<L4::Basic_registry>());
608 catch (L4::Out_of_memory const &e)
610 Err(Err::Fatal).printf("Memory exhausted and not handled\n");
611 L4::cerr << "FATAL exception in MOE:\n"
612 << e << "... terminated\n";
614 catch (L4::Runtime_error const &e)
616 L4::cerr << "FATAL exception in MOE:\n"
617 << e << "... terminated\n";