1// vi:set ft=cpp: -*- Mode: C++ -*- 2/* 3 * (c) 2008-2009 Alexander Warg <warg@os.inf.tu-dresden.de> 4 * economic rights: Technische Universität Dresden (Germany) 5 * This file is part of TUD:OS and distributed under the terms of the 6 * GNU Lesser General Public License 2.1. 7 * Please see the COPYING-LGPL-2.1 file for details. 8 */ 9 10#pragma once 11 12#include <l4/re/env> 13#include <l4/re/error_helper> 14#include <l4/sys/task> 15#include <l4/sys/thread> 16#include <l4/sys/scheduler> 17#include <l4/sys/factory> 18 19namespace Ldr { 20 21struct Remote_app_std_caps 22{ 23 enum Base_cap 24 { 25 Task_cap = 1, 26 Factory_cap = 2, 27 Rm_thread_cap = 3, 28 Log_cap = 5, 29 Scheduler_cap = 7, 30 // skip base caps 31 External_rm_cap = 0x10, 32 Allocator_cap, 33 Names_cap, 34 Parent_cap, 35 Kip_cap, 36 First_free, 37 }; 38}; 39 40struct Remote_app_std_prios 41{ 42 enum Prio 43 { 44 Default_thread_prio = 2 45 }; 46}; 47 48template< typename Base, typename STD_CAPS = Remote_app_std_caps, 49 typename PRIOS = Remote_app_std_prios > 50class Remote_app_model : public Base, protected STD_CAPS, protected PRIOS 51{ 52public: 53 typedef STD_CAPS Caps; 54 typedef PRIOS Prios; 55 56 virtual ~Remote_app_model() throw() {} 57 58 template< typename A1, typename A2, typename A3 > 59 Remote_app_model(A1 const &a1, A2 const &a2, A3 const & a3) 60 : Base(a1, a2, a3) {} 61 62 template< typename A1, typename A2 > 63 Remote_app_model(A1 const &a1, A2 const &a2) : Base(a1, a2) {} 64 65 template< typename A1 > 66 explicit Remote_app_model(A1 const &a1) : Base(a1) {} 67 68 Remote_app_model() : Base() {} 69 70 L4Re::Env *add_env() 71 { 72 // the terminator 73 this->_stack.push(l4re_env_cap_entry_t()); 74 75 l4_cap_idx_t first_free 76 = this->push_initial_caps(Caps::First_free << L4_CAP_SHIFT); 77 78 l4re_env_cap_entry_t *caps 79 = reinterpret_cast<l4re_env_cap_entry_t*>(this->_stack.ptr()); 80 81 L4Re::Env *env = this->_stack.push(L4Re::Env()); 82 83 env->mem_alloc(L4::Cap<L4Re::Mem_alloc>(Caps::Allocator_cap << L4_CAP_SHIFT)); 84 env->parent(L4::Cap<L4Re::Parent>(Caps::Parent_cap << L4_CAP_SHIFT)); 85 env->scheduler(L4::Cap<L4::Scheduler>(Caps::Scheduler_cap << L4_CAP_SHIFT)); 86 env->rm(L4::Cap<L4Re::Rm>(Caps::External_rm_cap << L4_CAP_SHIFT)); 87 env->log(L4::Cap<L4Re::Log>(Caps::Log_cap << L4_CAP_SHIFT)); 88 env->main_thread(L4::Cap<L4::Thread>(Caps::Rm_thread_cap << L4_CAP_SHIFT)); 89 env->factory(L4::Cap<L4::Factory>(Caps::Factory_cap << L4_CAP_SHIFT)); 90 env->first_free_cap(first_free >> L4_CAP_SHIFT); 91 env->utcb_area(l4_fpage(this->_info.utcbs_start, this->_info.utcbs_log2size, 0)); 92 env->first_free_utcb(this->_info.utcbs_start + L4_UTCB_OFFSET); 93 env->initial_caps(this->_stack.relocate(caps)); 94 return env; 95 } 96 97 L4::Cap<void> prog_kip_ds() const 98 { return L4::Cap<void>(Caps::Kip_cap << L4_CAP_SHIFT); } 99 100 void const *generate_l4aux(char const *name) 101 { 102 this->_stack.push(l4_umword_t(this->prog_info()->ldr_flags)); 103 this->_stack.push(l4_umword_t(this->prog_info()->l4re_dbg)); 104 this->_stack.push(l4_umword_t(prog_kip_ds().cap())); 105 return this->_stack.push_local_ptr(name); 106 } 107 108 void prog_reserve_utcb_area() 109 { 110 this->prog_attach_ds(this->prog_info()->utcbs_start, 111 1UL << this->prog_info()->utcbs_log2size, 112 this->reserved_area(), 0, L4Re::Rm::F::RW, 113 "attaching utcb area"); 114 } 115 116 void prog_attach_kip() 117 { 118 this->prog_attach_ds(this->prog_info()->kip, L4_PAGESIZE, 119 this->local_kip_ds(), 0, 120 L4Re::Rm::F::RX, 121 "attaching KIP segment"); 122 } 123 124 void prog_attach_stack(typename Base::Dataspace app_stack) 125 { 126 this->prog_attach_ds(this->_stack.target_addr(), this->_stack.stack_size(), 127 app_stack, 0, L4Re::Rm::F::RW, 128 "attaching stack segment"); 129 } 130 131 void start_prog(L4Re::Env const *env) 132 { 133 using L4Re::chksys; 134 using L4::Cap; 135 136 L4::Cap<L4::Task> ntask; 137 L4::Cap<L4::Thread> nthread; 138 L4::Cap<L4::Factory> factory; 139 140 this->get_task_caps(&factory, &ntask, &nthread); 141 142 chksys(factory->create_task(ntask, env->utcb_area())); 143 chksys(factory->create(nthread)); 144 145 chksys(ntask->map(L4Re::This_task, ntask.fpage(), 146 Cap<L4::Task>(L4Re::This_task).snd_base())); 147 chksys(ntask->map(L4Re::This_task, this->_info.factory, 148 env->factory().snd_base())); 149 chksys(ntask->map(L4Re::This_task, nthread.fpage(), 150 env->main_thread().snd_base())); 151 chksys(ntask->map(L4Re::This_task, this->_info.scheduler, 152 env->scheduler().snd_base())); 153 chksys(ntask->map(L4Re::This_task, this->_info.parent, 154 env->parent().snd_base())); 155 chksys(ntask->map(L4Re::This_task, this->_info.log, 156 env->log().snd_base())); 157 chksys(ntask->map(L4Re::This_task, this->_info.rm, 158 env->rm().snd_base())); 159 chksys(ntask->map(L4Re::This_task, this->_info.mem_alloc, 160 env->mem_alloc().snd_base())); 161 chksys(ntask->map(L4Re::This_task, this->local_kip_cap().fpage(), 162 prog_kip_ds().snd_base())); 163 164 this->map_initial_caps(ntask, Caps::First_free << L4_CAP_SHIFT); 165 166 L4::Thread::Attr th_attr; 167 th_attr.pager(env->rm()); 168 th_attr.exc_handler(env->rm()); 169 th_attr.bind((l4_utcb_t*)this->_info.utcbs_start, ntask); 170 chksys(nthread->control(th_attr)); 171 172 chksys(this->run_thread(nthread, 173 l4_sched_param(Prios::Default_thread_prio))); 174 175 nthread->ex_regs(this->_info.entry, this->_stack.target_ptr(), 0); 176 } 177 178 179}; 180 181} 182