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 _current_kip = l4sigma0_map_kip(Sigma0_cap, 0, L4_WHOLE_ADDRESS_SPACE);
78 Err(Err::Fatal).printf("could not map KIP\n");
83 boot.printf("KIP @%p\n",kip());
90 l4util_mb_info_t const *_mbi_ = (l4util_mb_info_t const *)kip()->user_ptr;
91 boot.printf("mbi @%p\n", _mbi_);
92 l4util_mb_mod_t const *modules = (l4util_mb_mod_t const *)_mbi_->mods_addr;
93 unsigned num_modules = _mbi_->mods_count;
96 for (unsigned mod = 0; mod < num_modules; ++mod)
98 if (strstr((char const *)modules[mod].cmdline, PROG))
100 cmdline = (char *)modules[mod].cmdline;
106 cmdline = (char *)_mbi_->cmdline;
108 static char default_cmdline[] = "";
112 Dbg(Dbg::Warn).printf("no command line found, use default!\n");
113 cmdline = default_cmdline;
121 static void find_memory()
123 using Moe::Pages::pages;
125 l4_addr_t min_addr = ~0UL;
126 l4_addr_t max_addr = 0;
128 for (unsigned order = 30 /*1G*/; order >= L4_LOG2_PAGESIZE; --order)
130 while (!l4sigma0_map_anypage(Sigma0_cap, 0, L4_WHOLE_ADDRESS_SPACE,
133 unsigned long size = 1UL << order;
143 if (addr < min_addr) min_addr = addr;
144 if (addr + size > max_addr) max_addr = addr + size;
146 Single_page_alloc_base::_free((void*)addr, size, true);
150 info.printf("found %ld KByte free memory\n",
151 Single_page_alloc_base::_avail() / 1024);
153 // adjust min_addr and max_addr to also contain boot modules
154 L4::Kip::Mem_desc const *md = L4::Kip::Mem_desc::first(kip());
155 L4::Kip::Mem_desc const *end = md + L4::Kip::Mem_desc::count(kip());
157 for (; md < end; ++md)
159 if (md->is_virtual())
162 L4::Kip::Mem_desc::Mem_type type = md->type();
163 unsigned long end = l4_round_page(md->end());
164 unsigned long start = l4_trunc_page(md->start());
167 case L4::Kip::Mem_desc::Bootloader:
168 if (start < min_addr)
173 case L4::Kip::Mem_desc::Conventional:
174 case L4::Kip::Mem_desc::Reserved:
175 case L4::Kip::Mem_desc::Dedicated:
176 case L4::Kip::Mem_desc::Arch:
177 case L4::Kip::Mem_desc::Shared:
183 assert(max_addr > min_addr);
184 l4_addr_t total_pages = (max_addr - min_addr) >> L4_PAGESHIFT;
188 pages = (typeof(pages))Single_page_alloc_base::_alloc(sizeof(*pages) * total_pages);
192 Err(Err::Fatal).printf("could not allocate page array, halt\n");
196 memset(pages, 0, sizeof(*pages) * total_pages);
198 Moe::Pages::base_addr = min_addr;
199 Moe::Pages::max_addr = max_addr;
201 info.printf("found RAM from %lx to %lx\n",
203 info.printf("allocated %ld KByte for the page array @%p\n",
204 sizeof(*pages) * total_pages / 1024, pages);
207 l4_addr_t Moe::Virt_limit::start;
208 l4_addr_t Moe::Virt_limit::end;
213 L4::Kip::Mem_desc *md = L4::Kip::Mem_desc::first(const_cast<l4_kernel_info_t*>(kip()));
214 unsigned long cnt = L4::Kip::Mem_desc::count(const_cast<l4_kernel_info_t*>(kip()));
216 for (L4::Kip::Mem_desc *m = md; m < md + cnt; ++m)
218 if (m->type() != L4::Kip::Mem_desc::Conventional || !m->is_virtual())
221 Moe::Virt_limit::start = m->start();
222 Moe::Virt_limit::end = m->end();
225 info.printf("virtual user address space [%lx-%lx]\n",
226 Moe::Virt_limit::start,
227 Moe::Virt_limit::end);
233 l4_utcb_t *u = l4_utcb();
234 boot.printf("UTCB @%p\n", u);
242 kip_ds = new Moe::Dataspace_static(const_cast<l4_kernel_info_t*>(kip()), L4_PAGESIZE, 0);
245 Err(Err::Fatal).printf("could not allocate dataspace for KIP!\n");
249 object_pool.cap_alloc()->alloc(kip_ds);
253 static void GC_CALLBACK finalization_notifier()
256 l4_msg_regs_t *mr = l4_utcb_mr();
258 memcpy(&b, mr->mr, sizeof(l4_msg_regs_t));
259 GC_invoke_finalizers();
260 memcpy(mr->mr, &b, sizeof(l4_msg_regs_t));
264 public L4::Ipc_svr::Ignore_errors,
265 public L4::Ipc_svr::Default_timeout,
266 public L4::Ipc_svr::Compound_reply
269 static void setup_wait(L4::Ipc_istream &istr, L4::Ipc_svr::Reply_mode)
271 GC_collect_a_little();
273 istr << L4::Small_buf(Rcv_cap << L4_CAP_SHIFT, L4_RCV_ITEM_LOCAL_ID);
274 l4_utcb_br_u(istr.utcb())->bdr = 0;
278 template< typename Reg >
285 int dispatch(l4_umword_t obj, L4::Ipc_iostream &ios)
289 typename Reg::Value *o = 0;
293 l4_utcb_t *u = l4_utcb();
294 L4::cout << L4::hex << "UTCB: " << u->values[0]
295 << "(" << op << "):" << u->values[1]
296 << "(" << obj << ")\n";
299 Dbg dbg(Dbg::Server);
301 dbg.printf("tag=%lx (proto=%lx) obj=%lx", tag.raw,
304 if (tag.is_exception())
307 Dbg(Dbg::Exceptions).printf("unhandled exception...\n");
312 // L4::cout << "ROOT: CALL(" << (void*)obj<< "): " << op << "...\n";
313 o = r.find(obj & ~3UL);
315 // L4::cout << "ROOT: obj=" << o << "\n";
317 // enter_kdebug("a");
321 dbg.cprintf(": invalid object\n");
325 dbg.cprintf(": object is a %s\n", typeid(*o).name());
328 int res = o->dispatch(obj, ios);
329 dbg.printf("reply = %d\n", res);
332 catch (L4::Runtime_error &e)
334 int res = e.err_no();
335 dbg.printf("reply(excption) = %d\n", res);
340 Dbg(Dbg::Warn).printf("Invalid message (tag.label=%ld)\n", tag.label());
346 static cxx::String _init_prog = "rom/ned";
351 void (*hdl)(cxx::String const &);
354 struct Dbg_bits { char const *tag; unsigned long bits; };
355 static Dbg_bits const dbb[] =
356 {{"info", Dbg::Info},
360 {"server", Dbg::Server},
361 {"svr", Dbg::Server},
362 {"exceptions", Dbg::Exceptions},
363 {"exc", Dbg::Exceptions},
366 {"loader", Dbg::Loader},
367 {"ldr", Dbg::Loader},
368 {"ns", Dbg::Name_space},
372 static Dbg_bits const ldr_flag_bits[] =
373 {{"pre_alloc", L4RE_AUX_LDR_FLAG_EAGER_MAP},
374 {"eager_map", L4RE_AUX_LDR_FLAG_EAGER_MAP},
375 {"all_segs_cow", L4RE_AUX_LDR_FLAG_ALL_SEGS_COW},
376 {"pinned_segs", L4RE_AUX_LDR_FLAG_PINNED_SEGS},
380 static unsigned long parse_flags(cxx::String const &_args, Dbg_bits const *dbb,
381 cxx::String const &opt)
383 cxx::String args = _args;
384 unsigned long lvl = 0;
387 cxx::String::Index c = args.find(",|+");
388 cxx::String a = args.head(c);
393 args = args.substr(c+1);
396 for (b = &dbb[0]; b->tag; ++b)
407 warn.printf("ignore unkown argument for %.*s: '%.*s'\n",
408 opt.len(), opt.start(), a.len(), a.start());
415 static void hdl_debug(cxx::String const &args)
417 unsigned long lvl = parse_flags(args, dbb, "--debug");
421 static void hdl_init(cxx::String const &args)
426 static void hdl_l4re_dbg(cxx::String const &args)
428 unsigned long lvl = parse_flags(args, dbb, "--l4re-dbg");
432 static void hdl_ldr_flags(cxx::String const &args)
434 unsigned long lvl = parse_flags(args, ldr_flag_bits, "--ldr-flags");
435 Moe::ldr_flags = lvl;
440 static Get_opt const _options[] = {
441 {"--debug=", hdl_debug },
442 {"--init=", hdl_init },
443 {"--l4re-dbg=", hdl_l4re_dbg },
444 {"--ldr-flags=", hdl_ldr_flags },
449 parse_long_option(cxx::String const &o)
452 for (Get_opt const *opt = _options; opt->tag; ++opt)
454 if (o.starts_with(opt->tag))
456 opt->hdl(o.substr(strlen(opt->tag)));
461 warn.printf("unknown command-line option '%.*s'\n", o.len(), o.start());
465 parse_option(cxx::String const &o)
469 warn.printf("empty command-line option '%.*s'\n", o.len(), o.start());
475 parse_long_option(o);
479 for (cxx::String::Index s = o.start() + 1; !o.eof(s); ++s)
484 warn.printf("unkown command-line option '%c'\n", o[s]);
492 static Elf_loader elf_loader;
494 static L4::Server<Loop_hooks> server(l4_utcb());
497 static void init_env()
499 // setup log capability in the global env, so that the libc backend can use
500 // L4::Env::env()->log() to send logoutput to
501 l4re_global_env = reinterpret_cast<l4re_env_t*>(&my_env);
502 my_env.factory(L4_BASE_FACTORY_CAP);
503 my_env.log(L4_BASE_LOG_CAP);
504 my_env.scheduler(L4_BASE_SCHEDULER_CAP);
507 static __attribute__((used,section(".preinit_array")))
508 const void *pre_init_env = (void *)init_env;
510 int main(int argc, char**argv)
512 (void)argc; (void)argv;
513 Dbg::set_level(Dbg::Info | Dbg::Warn);
514 //Dbg::level |= Dbg::Boot;
516 info.printf("Hello world\n");
520 Env::env()->scheduler()->run_thread(L4::Cap<L4::Thread>(L4_BASE_THREAD_CAP), l4_sched_param(0xff));
523 #if 0 // map RO stuff RO, we'll see write pagefaults if someone write to our
524 // RO segments later on
525 extern char _stext[];
526 extern char _etext[];
528 for (unsigned long i = (unsigned long)_stext; i < (unsigned long)_etext; i+= L4_PAGESIZE)
530 l4_task_unmap(l4_utcb(), L4_BASE_TASK_CAP, l4_fpage(i, L4_PAGESHIFT, L4_FPAGE_W), L4_FP_ALL_SPACES);
538 Moe::Boot_fs::init_stage1();
542 extern unsigned page_alloc_debug;
543 page_alloc_debug = 1;
545 GC_set_dont_expand(1);
546 GC_set_finalizer_notifier(finalization_notifier);
547 GC_set_finalize_on_demand(1);
549 Moe::Boot_fs::init_stage2();
550 init_vesa_fb((l4util_mb_info_t*)kip()->user_ptr);
552 root_name_space_obj = object_pool.cap_alloc()->alloc(root_name_space());
556 object_pool.cap_alloc()->alloc(Allocator::root_allocator());
558 l4_debugger_set_object_name(L4_BASE_TASK_CAP, "moe");
559 l4_debugger_set_object_name(L4_BASE_THREAD_CAP, "moe");
560 l4_debugger_set_object_name(L4_BASE_PAGER_CAP, "moe->s0");
562 root_name_space()->register_obj("log", Obj(Obj::F_rw, L4_BASE_LOG_CAP));
563 root_name_space()->register_obj("icu", Obj(Obj::F_rw, L4_BASE_ICU_CAP));
564 root_name_space()->register_obj("sigma0", Obj(Obj::F_trusted | Obj::F_rw, L4_BASE_PAGER_CAP));
565 root_name_space()->register_obj("mem", Obj(Obj::F_trusted | Obj::F_rw, Allocator::root_allocator()));
567 char *cmdline = my_cmdline();
569 info.printf("cmdline: %s\n", cmdline);
571 bool skip_argv0 = true;
572 cxx::Pair<cxx::String, cxx::String> a;
573 for (a = next_arg(cmdline); !a.first.empty(); a = next_arg(a.second))
581 if (a.first[0] != '-') // not an option start init
583 elf_loader.start(_init_prog, cxx::String(a.first.start(), a.second.end()));
589 elf_loader.start(_init_prog, a.second);
593 parse_option(a.first);
597 elf_loader.start(_init_prog, cxx::String(""));
599 // dump name space information
600 if (boot.is_active())
602 boot.printf("dump of root name space:\n");
603 root_name_space()->dump(1);
606 // we handle our exceptions ourselves
607 server.loop_noexc(My_dispatcher<L4::Basic_registry>());
609 catch (L4::Out_of_memory const &e)
611 Err(Err::Fatal).printf("Memory exhausted and not handled\n");
612 L4::cerr << "FATAL exception in MOE:\n"
613 << e << "... terminated\n";
615 catch (L4::Runtime_error const &e)
617 L4::cerr << "FATAL exception in MOE:\n"
618 << e << "... terminated\n";