]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/plr/server/src/app_loading
update
[l4.git] / l4 / pkg / plr / server / src / app_loading
1 // vim: ft=cpp
2 #pragma once
3
4 /*
5  * app_loading --
6  *
7  *    Implementation of application loading. Similar to the stuff
8  *    moe and ned do.
9  *
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.
15  */
16
17 #include <fcntl.h>
18 #include <l4/sys/consts.h>
19 #include <l4/sys/capability>
20 #include <l4/re/env>
21 #include <l4/re/rm>
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>
28
29 #include <l4/sys/kdebug.h>
30
31 #include "app"
32 #include "log"
33 #include "memory"
34 #include "emulation"
35 #include "locking.h"
36
37 namespace Romain {
38
39 class App_stack : public Ldr::Remote_stack<>
40 { };
41
42
43 /*
44  * Application model
45  *
46  * This model is used for two purposes:
47  *
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
51  */
52 class App_model : public Ldr::Base_app_model<Romain::App_stack>
53 {
54         l4_addr_t _local_stack_address;
55
56         public:
57                 enum
58                 {
59                         Kip_cap                = 0xB,
60                         First_free_cap         = 0xD,
61                         Utcb_area_start        = 0xb3000000,
62                         Kip_address            = 0xa0000000,
63                 };
64
65                 /****************************************************************************
66                  *                         Types needed by Ldr::*                           *
67                  ****************************************************************************/
68
69                 typedef L4::Cap<L4Re::Dataspace> const Const_dataspace;
70                 typedef L4::Cap<L4Re::Dataspace> Dataspace;
71
72
73                 /****************************************************************************
74                  *                       Functions needed by Ldr::*                         *
75                  ****************************************************************************/
76
77                 static Const_dataspace open_file(char const *name);
78
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,
82                                      l4_umword_t size);
83
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,
87                                             bool shared = false);
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);
93
94                 Dataspace    alloc_app_stack();
95                 void         prog_attach_stack(Dataspace app_stack);
96
97                 void         prog_attach_kip();
98                 L4Re::Env*   add_env();
99                 void         prog_reserve_utcb_area();
100                 void const * generate_l4aux(char const *name);
101
102
103                 static bool            all_segs_cow()  { return false; }
104                 static Const_dataspace reserved_area() { return Const_dataspace(); }
105
106                 void init_prog()
107                 {
108                         push_trampoline();
109                         push_env_strings();
110                         push_argv_strings();
111                 }
112
113                 static Dataspace local_kip_ds()
114                 {
115                         extern l4re_aux_t* l4re_aux;
116                         return L4::Cap<L4Re::Dataspace>(l4re_aux->kip_ds);
117                 }
118
119
120                 L4::Cap<void> prog_kip_ds() const
121                 {
122                         return L4::Cap<void>(Kip_cap << L4_CAP_SHIFT);
123                 }
124
125                 void push_initial_caps()
126                 {
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) {
130                                 _stack.push(*c);
131                         }
132                 }
133
134
135                 void start_prog(L4Re::Env const *) { }
136
137
138                 void push_argv_strings()
139                 {
140                         for (l4_umword_t i = 0; i < _argc; ++i) {
141                                 _remote_argv[i] = _stack.push_str(_argv[i], strlen(_argv[i]));
142                         }
143                 }
144
145                 void push_trampoline()
146                 {
147                         l4_umword_t v = 0;
148                         for (l4_umword_t i = 0; i < Romain::TRAMPOLINE_SIZE / sizeof(v); ++i)
149                                 _stack.push(v);
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());
154                 }
155
156                 void push_env_strings()
157                 {
158                         char **p = environ;
159                         while (*p) {
160                                 printf("ENV: %s\n", *p);
161                                 _remote_env[_env_count++] = _stack.push_str(*p, strlen(*p));
162                                 p++;
163                         }
164                 }
165
166
167                 void push_envp()
168                 {
169                         _stack.push(0UL);
170                         for (l4_umword_t i = 0; i < _env_count; ++i) {
171                                 _stack.push_local_ptr(_remote_env[i]);
172                         }
173                 }
174
175
176                 void push_argv()
177                 {
178                         _stack.push(0UL);
179                         for (l4_umword_t i = _argc; i > 0; --i) {
180                                 _stack.push_local_ptr(_remote_argv[i-1]);
181                         }
182                         _stack.push(_argc);
183                 }
184
185
186                 /****************************************************************************
187                  *                   Local App_model functionality                          *
188                  ****************************************************************************/
189
190         private:
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!
199
200                 /*
201                  * We keep a trampoline of TRAMPOLINE_SIZE bytes in the replica's
202                  * thread area that we can use as scratch data.
203                  */
204                 l4_addr_t        _trampoline_local;
205                 l4_addr_t        _trampoline_remote;
206
207                 /*
208                  * Store lock info page for pthread determinism enforcer. See
209                  * fault_handlers/lock_observer.*
210                  */
211                 l4_addr_t        _lockinfo_local;
212                 l4_addr_t        _lockinfo_remote;
213
214         public:
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)
220                 {
221                     _rm = new Romain::Region_map();
222
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;
228
229                         memset(_remote_argv, 0, sizeof(_remote_argv));
230                         memset(_remote_env, 0, sizeof(_remote_env));
231                 }
232
233                 Const_dataspace binary()      const { return _binary_ds; }
234                 Romain::Region_map *rm()      const { return _rm; }
235                 Dataspace utcb_area()         const { return _utcb_area; }
236
237                 /*
238                  * Get the trampoline's address within the master.
239                  */
240                 l4_addr_t trampoline_local()  const { return _trampoline_local; }
241                 /*
242                  * Remote trampoline address
243                  */
244                 l4_addr_t trampoline_remote() const { return _trampoline_remote; }
245                 /*
246                  * Determine if the address is within the remote trampoline.
247                  */
248                 bool in_trampoline(l4_addr_t a) const
249                 {
250                         return ((a >= _trampoline_remote) && (a < (_trampoline_remote + Romain::TRAMPOLINE_SIZE)));
251                 }
252
253
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; }
258 };
259
260
261 struct AppModelAddressTranslator : public Romain::AddressTranslator
262 {
263         Romain::App_model *am;
264         Romain::App_instance *inst;
265         public:
266                 AppModelAddressTranslator(Romain::App_model* a, Romain::App_instance *i)
267                         : am(a), inst(i)
268                 { }
269
270                 virtual ~AppModelAddressTranslator() { }
271
272                 virtual l4_addr_t translate(l4_addr_t orig) const
273                 { return am->rm()->remote_to_local(orig, inst->id()); }
274 };
275
276
277 /*
278  * ELF Loader wrapper class.
279  */
280 class Elf_Ldr
281 : public Ldr::Elf_loader<Romain::App_model, Romain::Dbg>
282 {
283         Romain::App_model *_appModel;
284
285         public:
286         typedef Ldr::Elf_loader<Romain::App_model, Romain::Dbg> Base;
287
288         Elf_Ldr(Romain::App_model *am)
289                 : _appModel(am)
290         {
291         }
292
293         void load()
294         {
295                 INFO() << "loading...";
296                 Base::load(_appModel, _appModel->binary(), Romain::Dbg());
297         }
298
299         void launch()
300         {
301                 INFO() << __func__ ;
302                 Base::launch(_appModel, _appModel->binary(), Romain::Dbg());
303         }
304 };
305
306 } // ns Romain