7 * Implementation of application loading. Similar to the stuff
10 * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
11 * economic rights: Technische Universität Dresden (Germany)
12 * This file is part of TUD:OS and distributed under the terms of the
13 * GNU General Public License 2.
14 * Please see the COPYING-GPL-2 file for details.
18 #include <l4/sys/consts.h>
19 #include <l4/sys/capability>
22 #include <l4/re/dataspace>
23 #include <l4/re/util/cap_alloc>
24 #include <l4/libloader/elf>
25 #include <l4/libloader/remote_mem>
26 #include <l4/l4re_vfs/vfs.h>
27 #include <l4/l4re_vfs/backend>
29 #include <l4/sys/kdebug.h>
39 class App_stack : public Ldr::Remote_stack<>
46 * This model is used for two purposes:
48 * 1) It serves as the class implementing the policies required by Loader's
49 * app model (dataspace - data type, allocation, attachment).
50 * 2) It keeps track of the redundant instances of tasks kept by Romain
52 class App_model : public Ldr::Base_app_model<Romain::App_stack>
54 l4_addr_t _local_stack_address;
61 Utcb_area_start = 0xb3000000,
62 Kip_address = 0xa0000000,
65 /****************************************************************************
66 * Types needed by Ldr::* *
67 ****************************************************************************/
69 typedef L4::Cap<L4Re::Dataspace> const Const_dataspace;
70 typedef L4::Cap<L4Re::Dataspace> Dataspace;
73 /****************************************************************************
74 * Functions needed by Ldr::* *
75 ****************************************************************************/
77 static Const_dataspace open_file(char const *name);
79 Dataspace alloc_ds(l4_umword_t size) const;
80 static void copy_ds(Dataspace dst, l4_umword_t dst_offs,
81 Const_dataspace src, l4_umword_t src_offs,
84 void * prog_attach_ds(l4_addr_t addr, l4_umword_t size,
85 Const_dataspace ds, l4_umword_t offset,
86 l4_umword_t flags, char const *what, l4_addr_t local_start = 0,
88 l4_addr_t local_attach_ds(Const_dataspace ds, l4_umword_t size,
89 l4_umword_t offset, l4_umword_t address_hint = 0) const;
90 void local_detach_ds(l4_addr_t addr, l4_umword_t /*size*/) const;
91 l4_mword_t prog_reserve_area(l4_addr_t *start, l4_umword_t size,
92 l4_umword_t flags, l4_uint8_t align);
94 Dataspace alloc_app_stack();
95 void prog_attach_stack(Dataspace app_stack);
97 void prog_attach_kip();
99 void prog_reserve_utcb_area();
100 void const * generate_l4aux(char const *name);
103 static bool all_segs_cow() { return false; }
104 static Const_dataspace reserved_area() { return Const_dataspace(); }
113 static Dataspace local_kip_ds()
115 extern l4re_aux_t* l4re_aux;
116 return L4::Cap<L4Re::Dataspace>(l4re_aux->kip_ds);
120 L4::Cap<void> prog_kip_ds() const
122 return L4::Cap<void>(Kip_cap << L4_CAP_SHIFT);
125 void push_initial_caps()
127 L4Re::Env::Cap_entry const *c = L4Re::Env::env()->initial_caps();
128 l4_umword_t count = 0;
129 for ( ; c->flags != ~0UL; ++c, ++count) {
135 void start_prog(L4Re::Env const *) { }
138 void push_argv_strings()
140 for (l4_umword_t i = 0; i < _argc; ++i) {
141 _remote_argv[i] = _stack.push_str(_argv[i], strlen(_argv[i]));
145 void push_trampoline()
148 for (l4_umword_t i = 0; i < Romain::TRAMPOLINE_SIZE / sizeof(v); ++i)
150 INFO() << "trampoline ptr " << (void*)_stack.ptr()
151 << " " << (void*)_stack.relocate(_stack.ptr());
152 _trampoline_local = (l4_addr_t)_stack.ptr();
153 _trampoline_remote = (l4_addr_t)_stack.relocate(_stack.ptr());
156 void push_env_strings()
160 printf("ENV: %s\n", *p);
161 _remote_env[_env_count++] = _stack.push_str(*p, strlen(*p));
170 for (l4_umword_t i = 0; i < _env_count; ++i) {
171 _stack.push_local_ptr(_remote_env[i]);
179 for (l4_umword_t i = _argc; i > 0; --i) {
180 _stack.push_local_ptr(_remote_argv[i-1]);
186 /****************************************************************************
187 * Local App_model functionality *
188 ****************************************************************************/
191 Const_dataspace _binary_ds; // dataspace containing the original ELF binary
192 Romain::Region_map *_rm; // our region map
193 l4_umword_t _argc; // app argc
194 char const **_argv; // app argv
195 char const *_remote_argv[32]; // XXX
196 char const *_remote_env[32]; // XXX
197 l4_umword_t _env_count; //
198 Dataspace _utcb_area; // XXX: this is per thread!
201 * We keep a trampoline of TRAMPOLINE_SIZE bytes in the replica's
202 * thread area that we can use as scratch data.
204 l4_addr_t _trampoline_local;
205 l4_addr_t _trampoline_remote;
208 * Store lock info page for pthread determinism enforcer. See
209 * fault_handlers/lock_observer.*
211 l4_addr_t _lockinfo_local;
212 l4_addr_t _lockinfo_remote;
215 App_model(char const *filename, l4_umword_t argc, char const **argv)
216 : _binary_ds(Romain::App_model::open_file(filename)),
217 _argc(argc), _argv(argv), _env_count(0),
218 _trampoline_local(0), _trampoline_remote(0),
219 _lockinfo_local(0), _lockinfo_remote(0)
221 _rm = new Romain::Region_map();
223 prog_info()->utcbs_start = Utcb_area_start;
224 prog_info()->utcbs_log2size = L4_PAGESHIFT;
225 // poison this pointer -- the real address should come
226 // from the ELF binary
227 prog_info()->kip = 0xdeadbeef;
229 memset(_remote_argv, 0, sizeof(_remote_argv));
230 memset(_remote_env, 0, sizeof(_remote_env));
233 Const_dataspace binary() const { return _binary_ds; }
234 Romain::Region_map *rm() const { return _rm; }
235 Dataspace utcb_area() const { return _utcb_area; }
238 * Get the trampoline's address within the master.
240 l4_addr_t trampoline_local() const { return _trampoline_local; }
242 * Remote trampoline address
244 l4_addr_t trampoline_remote() const { return _trampoline_remote; }
246 * Determine if the address is within the remote trampoline.
248 bool in_trampoline(l4_addr_t a) const
250 return ((a >= _trampoline_remote) && (a < (_trampoline_remote + Romain::TRAMPOLINE_SIZE)));
254 l4_addr_t lockinfo_local() const { return _lockinfo_local; }
255 l4_addr_t lockinfo_remote() const { return _lockinfo_remote; }
256 void lockinfo_local(l4_addr_t a) { _lockinfo_local = a; }
257 void lockinfo_remote(l4_addr_t a) { _lockinfo_remote = a; }
261 struct AppModelAddressTranslator : public Romain::AddressTranslator
263 Romain::App_model *am;
264 Romain::App_instance *inst;
266 AppModelAddressTranslator(Romain::App_model* a, Romain::App_instance *i)
270 virtual ~AppModelAddressTranslator() { }
272 virtual l4_addr_t translate(l4_addr_t orig) const
273 { return am->rm()->remote_to_local(orig, inst->id()); }
278 * ELF Loader wrapper class.
281 : public Ldr::Elf_loader<Romain::App_model, Romain::Dbg>
283 Romain::App_model *_appModel;
286 typedef Ldr::Elf_loader<Romain::App_model, Romain::Dbg> Base;
288 Elf_Ldr(Romain::App_model *am)
295 INFO() << "loading...";
296 Base::load(_appModel, _appModel->binary(), Romain::Dbg());
302 Base::launch(_appModel, _appModel->binary(), Romain::Dbg());