]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/plr/server/src/app_loading.cc
48f4adbf34bc927ee55cb6304f023135dbed3065
[l4.git] / l4 / pkg / plr / server / src / app_loading.cc
1 #include "app_loading"
2 #include "locking.h"
3
4 /*
5  * app_loading.cc --
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 #define MSG() DEBUGf(Romain::Log::Loader)
18
19 Romain::App_model::Const_dataspace Romain::App_model::open_file(char const *name)
20 {
21         MSG() << name;
22
23         int err = open(name, O_RDONLY);
24         MSG() << "fopen: " << err;
25         if (err < 0) {
26                 ERROR() << "Could not open binary file '" << name << "'";
27                 enter_kdebug("file not found");
28         }
29
30         cxx::Ref_ptr<L4Re::Vfs::File> fp = L4Re::Vfs::vfs_ops->get_file(err);
31         MSG() << "file ptr @ " << fp;
32
33         Romain::App_model::Dataspace ds_cap = fp->data_space();
34         MSG() << "ds @ 0x" << std::hex << ds_cap.cap();
35
36         return ds_cap;
37 }
38
39 l4_addr_t Romain::App_model::local_attach_ds(Romain::App_model::Const_dataspace ds,
40                                              unsigned long size,
41                                              unsigned long offset) const
42 {
43         Romain::Rm_guard r(rm(), 0); // we always init stuff for instance 0,
44         // rest is paged in lazily
45         // XXX: duplicate, remove
46 #if 0
47         MSG() << std::hex << ds.cap() << " "
48               << size << " "
49               << offset << " "
50               << l4_round_page(offset);
51 #endif
52         unsigned flags = L4Re::Rm::Search_addr;
53
54         /* This function is called during startup for attaching the
55          * binary DS read-only to read ELF info. However, in this case
56          * we don't have any flags indicating this and writing the DS will
57          * fail. Therefore, this hacky check adds an RO flag so that the
58          * memory manager performs the right thing.
59          */
60         if (ds == binary()) {
61                 flags |= L4Re::Rm::Read_only;
62         }
63         Romain::Region_handler handler(ds, L4_INVALID_CAP, offset, 0,
64                                     Romain::Region(0, 0));
65         l4_addr_t ret = (l4_addr_t)rm()->attach_locally((void*)0xdeadbeef,
66                                                         size, &handler, flags);
67         return ret;
68 }
69
70
71 void Romain::App_model::local_detach_ds(l4_addr_t addr, unsigned long /*size*/) const
72 {
73 #if 0
74         MSG() << (void*)addr;
75 #endif
76
77         long r = L4Re::Env::env()->rm()->detach(addr, 0);
78         _check(r != 0, "detach error");
79 }
80
81
82 int Romain::App_model::prog_reserve_area(l4_addr_t *start, unsigned long size,
83                                       unsigned flags, unsigned char align)
84 {
85         MSG() << (void*)start << " "
86               << size << " "
87               << flags << " "
88               << align;
89         _check(1, "prog_reserve_area unimplemented");
90         return -1;
91 }
92
93
94 Romain::App_model::Dataspace Romain::App_model::alloc_app_stack()
95 {
96 #if 0
97         MSG() << __func__ << " " << _stack.stack_size() << " "
98               << std::hex << (void*)_stack.ptr();
99 #endif
100         Romain::App_model::Dataspace ds = this->alloc_ds(_stack.stack_size());
101         char *addr = reinterpret_cast<char*>(this->local_attach_ds(ds, _stack.stack_size(), 0));
102         MSG() << "attached app stack: " << (void*)addr;
103         _local_stack_address = l4_addr_t(addr);
104
105         //_stack.ptr(addr);
106         _stack.set_local_top(addr + _stack.stack_size());
107         MSG() << "stack local : " << std::hex << (void*)_stack.ptr();
108         MSG() << "stack remote: " << std::hex << (void*)_stack.relocate(_stack.ptr());
109
110         /*
111          * Place UTCB area pointer at the very top of the stack.
112          * This way we know exactly what to put into the FS segment
113          * descriptor.
114          */
115         _stack.push(prog_info()->utcbs_start);
116
117         return ds;
118 }
119
120
121 void Romain::App_model::prog_attach_kip()
122 {
123         MSG() << "ATTACHING KIP: " << (void*)this->prog_info()->kip;
124         this->prog_attach_ds(this->prog_info()->kip, L4_PAGESIZE,
125                              this->local_kip_ds(), 0,
126                              L4Re::Rm::Read_only, "attaching KIP segment",
127                              (l4_addr_t)l4re_kip());
128         //enter_kdebug("kip");
129 }
130
131
132 void*
133 Romain::App_model::prog_attach_ds(l4_addr_t addr, unsigned long size,
134                                   Romain::App_model::Const_dataspace ds, unsigned long offset,
135                                   unsigned flags, char const *what, l4_addr_t local_start,
136                                   bool sharedFlag)
137 {
138         (void)what;
139         Romain::Rm_guard r(rm(), 0); // we always init stuff for instance 0,
140                                   // rest is paged in lazily
141 #if 0
142         MSG() << std::hex << (void*)addr << " "
143               << size << " "
144               << ds.cap() << " "
145               << offset << " "
146               << flags << " "
147               << local_start << " "
148               << what;
149 #endif
150
151         /*
152          * This is where we remember the initial segments.
153          */
154         void* target = rm()->attach((void*)addr, size,
155                                     Romain::Region_handler(
156                                         ds, L4_INVALID_CAP, offset, flags,
157                                         Romain::Region(local_start, local_start + size - 1)),
158                                         flags, L4_PAGESHIFT, sharedFlag);
159 #if 1
160         MSG() << std::hex << (void*)target;
161 #endif
162
163         _check(((target == 0) || (target == (void*)~0UL)), "error attaching segment");
164         return target;
165 }
166
167
168 L4Re::Env*
169 Romain::App_model::add_env()
170 {
171         _stack.push(l4re_env_cap_entry_t());
172         push_initial_caps();
173         L4Re::Env::Cap_entry *remote_cap_ptr =
174                 reinterpret_cast<L4Re::Env::Cap_entry*>(_stack.relocate(_stack.ptr()));
175         MSG() << "remote cap entries @ " << (void*)remote_cap_ptr;
176
177         L4Re::Env *env = _stack.push(L4Re::Env());
178         memcpy(env, L4Re::Env::env(), sizeof(L4Re::Env));
179         MSG() << "my first cap " << std::hex << env->first_free_cap();
180         env->initial_caps(remote_cap_ptr);
181         env->main_thread(L4::Cap<L4::Thread>(Romain::FIRST_REPLICA_CAP << L4_CAP_SHIFT));
182         env->first_free_cap(Romain::FIRST_REPLICA_CAP + 1); // First free + 1, because the first
183                                                             // free slot is used for the main thread's
184                                                             // GateAgent
185         env->utcb_area(l4_fpage(this->prog_info()->utcbs_start, this->prog_info()->utcbs_log2size, 0));
186         env->first_free_utcb(this->prog_info()->utcbs_start + L4_UTCB_OFFSET);
187
188         return env;
189 }
190
191
192 Romain::App_model::Dataspace Romain::App_model::alloc_ds(unsigned long size) const
193 {
194         Dataspace ds;
195         Romain::Region_map::allocate_ds(&ds, size);
196         return ds;
197 }
198
199 void Romain::App_model::copy_ds(Romain::App_model::Dataspace dst, unsigned long dst_offs,
200                                 Const_dataspace src, unsigned long src_offs,
201                                 unsigned long size)
202 {
203 #if 0
204         MSG() << std::hex << dst.cap() << " "
205               << dst_offs << " "
206               << src.cap() << " "
207               << src_offs << " "
208               << size;
209 #endif
210         dst->copy_in(dst_offs, src, src_offs, size);
211 #if 0
212         MSG() << "...done";
213 #endif
214 }
215
216
217 void Romain::App_model::prog_attach_stack(Romain::App_model::Dataspace app_stack)
218 {
219 #if 0
220         MSG() << __func__ << std::hex
221               << " " << app_stack.cap()
222               << " " << (void*)_stack.target_addr()
223               << " " << (void*)_stack.target_top();
224 #endif
225         this->prog_attach_ds(this->_stack.target_addr(),
226                              this->_stack.stack_size(),
227                              app_stack,
228                              0, 0, "stack segment", _local_stack_address);
229         prog_info()->stack_addr = _stack.target_addr() + _stack.stack_size();
230 #if 0
231         MSG() << std::hex << (void*)_stack.ptr() << " <-> "
232               << (void*)_stack.relocate(_stack.ptr());
233 #endif
234 }
235
236
237 void Romain::App_model::prog_reserve_utcb_area()
238 {
239         _utcb_area = this->alloc_ds(1 << prog_info()->utcbs_log2size);
240 #if 0
241         MSG() << __func__ << " " << std::hex
242               << (void*)this->prog_info()->utcbs_start;
243 #endif
244         this->prog_attach_ds(this->prog_info()->utcbs_start,
245                              1 << this->prog_info()->utcbs_log2size,
246                              _utcb_area, 0, 0, "utcb area",
247                              0);
248 }
249
250
251 void const *Romain::App_model::generate_l4aux(char const *name)
252 {
253         this->_stack.push(l4_umword_t(this->prog_info()->ldr_flags));
254         this->_stack.push(l4_umword_t(this->prog_info()->l4re_dbg));
255         this->_stack.push(l4_umword_t(local_kip_ds().cap()));
256         return this->_stack.push_local_ptr(name);
257 }