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(unsigned long size) const;
80 static void copy_ds(Dataspace dst, unsigned long dst_offs,
81 Const_dataspace src, unsigned long src_offs,
84 void * prog_attach_ds(l4_addr_t addr, unsigned long size,
85 Const_dataspace ds, unsigned long offset,
86 unsigned flags, char const *what, l4_addr_t local_start = 0,
88 l4_addr_t local_attach_ds(Const_dataspace ds, unsigned long size,
89 unsigned long offset) const;
90 void local_detach_ds(l4_addr_t addr, unsigned long /*size*/) const;
91 int prog_reserve_area(l4_addr_t *start, unsigned long size,
92 unsigned flags, unsigned char 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();
129 for ( ; c->flags != ~0UL; ++c, ++count) {
135 void start_prog(L4Re::Env const *) { }
138 void push_argv_strings()
140 for (unsigned i = 0; i < _argc; ++i) {
141 _remote_argv[i] = _stack.push_str(_argv[i], strlen(_argv[i]));
145 void push_trampoline()
148 for (unsigned 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() { /* nothing */ }
168 for (unsigned i = _argc; i > 0; --i) {
169 _stack.push_local_ptr(_remote_argv[i-1]);
175 /****************************************************************************
176 * Local App_model functionality *
177 ****************************************************************************/
180 Const_dataspace _binary_ds;
181 Romain::Region_map *_rm;
184 char const *_remote_argv[32]; // XXX
185 Dataspace _utcb_area; // XXX: this is per thread!
188 * We keep a trampoline of TRAMPOLINE_SIZE bytes in the replica's
189 * thread area that we can use as scratch data.
191 l4_addr_t _trampoline_local;
192 l4_addr_t _trampoline_remote;
195 * Store lock info page for pthread determinism enforcer. See
196 * fault_handlers/lock_observer.*
198 l4_addr_t _lockinfo_local;
199 l4_addr_t _lockinfo_remote;
202 App_model(char const *filename, unsigned argc, char const **argv)
203 : _binary_ds(Romain::App_model::open_file(filename)),
204 _argc(argc), _argv(argv),
205 _trampoline_local(0), _trampoline_remote(0),
206 _lockinfo_local(0), _lockinfo_remote(0)
208 _rm = new Romain::Region_map();
210 prog_info()->utcbs_start = Utcb_area_start;
211 prog_info()->utcbs_log2size = L4_PAGESHIFT;
212 // poison this pointer -- the real address should come
213 // from the ELF binary
214 prog_info()->kip = 0xdeadbeef;
216 memset(_remote_argv, 0, sizeof(_remote_argv));
219 Const_dataspace binary() const { return _binary_ds; }
220 Romain::Region_map *rm() const { return _rm; }
221 Dataspace utcb_area() const { return _utcb_area; }
224 * Get the trampoline's address within the master.
226 l4_addr_t trampoline_local() const { return _trampoline_local; }
228 * Remote trampoline address
230 l4_addr_t trampoline_remote() const { return _trampoline_remote; }
232 * Determine if the address is within the remote trampoline.
234 bool in_trampoline(l4_addr_t a) const
236 return ((a >= _trampoline_remote) && (a < (_trampoline_remote + Romain::TRAMPOLINE_SIZE)));
240 l4_addr_t lockinfo_local() const { return _lockinfo_local; }
241 l4_addr_t lockinfo_remote() const { return _lockinfo_remote; }
242 void lockinfo_local(l4_addr_t a) { _lockinfo_local = a; }
243 void lockinfo_remote(l4_addr_t a) { _lockinfo_remote = a; }
247 class AppModelAddressTranslator : public Romain::AddressTranslator
249 Romain::App_model *am;
250 Romain::App_instance *inst;
252 AppModelAddressTranslator(Romain::App_model* a, Romain::App_instance *i)
256 virtual ~AppModelAddressTranslator() { }
258 virtual l4_addr_t translate(l4_addr_t orig) const
259 { return am->rm()->remote_to_local(orig, inst->id()); }
264 * ELF Loader wrapper class.
267 : public Ldr::Elf_loader<Romain::App_model, Romain::Dbg>
269 Romain::App_model *_appModel;
272 typedef Ldr::Elf_loader<Romain::App_model, Romain::Dbg> Base;
274 Elf_Ldr(Romain::App_model *am)
281 INFO() << "loading...";
282 Base::load(_appModel, _appModel->binary(), Romain::Dbg());
288 Base::launch(_appModel, _appModel->binary(), Romain::Dbg());