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.
17 #define MSG() DEBUGf(Romain::Log::Loader)
19 Romain::App_model::Const_dataspace Romain::App_model::open_file(char const *name)
23 int err = open(name, O_RDONLY);
24 MSG() << "fopen: " << err;
26 ERROR() << "Could not open binary file '" << name << "'";
27 enter_kdebug("file not found");
30 cxx::Ref_ptr<L4Re::Vfs::File> fp = L4Re::Vfs::vfs_ops->get_file(err);
31 MSG() << "file ptr @ " << fp;
33 Romain::App_model::Dataspace ds_cap = fp->data_space();
34 MSG() << "ds @ 0x" << std::hex << ds_cap.cap();
39 l4_addr_t Romain::App_model::local_attach_ds(Romain::App_model::Const_dataspace ds,
42 l4_umword_t address_hint) const
44 Romain::Rm_guard r(rm(), 0); // we always init stuff for instance 0,
45 // rest is paged in lazily
46 // XXX: duplicate, remove
48 MSG() << std::hex << ds.cap() << " "
51 << l4_round_page(offset);
53 unsigned flags = L4Re::Rm::Search_addr;
55 /* This function is called during startup for attaching the
56 * binary DS read-only to read ELF info. However, in this case
57 * we don't have any flags indicating this and writing the DS will
58 * fail. Therefore, this hacky check adds an RO flag so that the
59 * memory manager performs the right thing.
62 flags |= L4Re::Rm::Read_only;
64 Romain::Region_handler handler(ds, L4_INVALID_CAP, offset, 0,
65 Romain::Region(0, 0));
66 if (address_hint != 0) {
67 handler.alignToAddressAndSize(address_hint, size);
69 l4_addr_t ret = (l4_addr_t)rm()->attach_locally((void*)0, size, &handler, flags);
74 void Romain::App_model::local_detach_ds(l4_addr_t addr, unsigned long /*size*/) const
80 long r = L4Re::Env::env()->rm()->detach(addr, 0);
81 _check(r != 0, "detach error");
85 int Romain::App_model::prog_reserve_area(l4_addr_t *start, unsigned long size,
86 unsigned flags, unsigned char align)
88 MSG() << (void*)start << " "
92 _check(1, "prog_reserve_area unimplemented");
97 Romain::App_model::Dataspace Romain::App_model::alloc_app_stack()
100 MSG() << __func__ << " " << _stack.stack_size() << " "
101 << std::hex << (void*)_stack.ptr();
103 Romain::App_model::Dataspace ds = this->alloc_ds(_stack.stack_size());
104 char *addr = reinterpret_cast<char*>(this->local_attach_ds(ds, _stack.stack_size(),
105 0, _stack.target_addr()));
106 MSG() << "attached app stack: " << (void*)addr;
107 _local_stack_address = l4_addr_t(addr);
110 _stack.set_local_top(addr + _stack.stack_size());
111 MSG() << "stack local : " << std::hex << (void*)_stack.ptr();
112 MSG() << "stack remote: " << std::hex << (void*)_stack.relocate(_stack.ptr());
115 * Place UTCB area pointer at the very top of the stack.
116 * This way we know exactly what to put into the FS segment
119 _stack.push(prog_info()->utcbs_start);
125 void Romain::App_model::prog_attach_kip()
127 MSG() << "ATTACHING KIP: " << (void*)this->prog_info()->kip;
128 this->prog_attach_ds(this->prog_info()->kip, L4_PAGESIZE,
129 this->local_kip_ds(), 0,
130 L4Re::Rm::Read_only, "attaching KIP segment",
131 (l4_addr_t)l4re_kip());
132 //enter_kdebug("kip");
137 Romain::App_model::prog_attach_ds(l4_addr_t addr, unsigned long size,
138 Romain::App_model::Const_dataspace ds, unsigned long offset,
139 unsigned flags, char const *what, l4_addr_t local_start,
143 Romain::Rm_guard r(rm(), 0); // we always init stuff for instance 0,
144 // rest is paged in lazily
146 MSG() << std::hex << (void*)addr << " "
151 << local_start << " "
156 * This is where we remember the initial segments.
158 void* target = rm()->attach((void*)addr, size,
159 Romain::Region_handler(
160 ds, L4_INVALID_CAP, offset, flags,
161 Romain::Region(local_start, local_start + size - 1)),
162 flags, L4_PAGESHIFT, sharedFlag);
164 MSG() << std::hex << (void*)target;
167 _check(((target == 0) || (target == (void*)~0UL)), "error attaching segment");
173 Romain::App_model::add_env()
175 _stack.push(l4re_env_cap_entry_t());
177 L4Re::Env::Cap_entry *remote_cap_ptr =
178 reinterpret_cast<L4Re::Env::Cap_entry*>(_stack.relocate(_stack.ptr()));
179 MSG() << "remote cap entries @ " << (void*)remote_cap_ptr;
181 L4Re::Env *env = _stack.push(L4Re::Env());
182 memcpy(env, L4Re::Env::env(), sizeof(L4Re::Env));
183 MSG() << "my first cap " << std::hex << env->first_free_cap();
184 env->initial_caps(remote_cap_ptr);
185 env->main_thread(L4::Cap<L4::Thread>(Romain::FIRST_REPLICA_CAP << L4_CAP_SHIFT));
186 env->first_free_cap(Romain::FIRST_REPLICA_CAP + 1); // First free + 1, because the first
187 // free slot is used for the main thread's
189 env->utcb_area(l4_fpage(this->prog_info()->utcbs_start, this->prog_info()->utcbs_log2size, 0));
190 env->first_free_utcb(this->prog_info()->utcbs_start + L4_UTCB_OFFSET);
196 Romain::App_model::Dataspace Romain::App_model::alloc_ds(unsigned long size) const
199 Romain::Region_map::allocate_ds(&ds, size);
203 void Romain::App_model::copy_ds(Romain::App_model::Dataspace dst, unsigned long dst_offs,
204 Const_dataspace src, unsigned long src_offs,
208 MSG() << std::hex << dst.cap() << " "
214 dst->copy_in(dst_offs, src, src_offs, size);
221 void Romain::App_model::prog_attach_stack(Romain::App_model::Dataspace app_stack)
224 MSG() << __func__ << std::hex
225 << " " << app_stack.cap()
226 << " " << (void*)_stack.target_addr()
227 << " " << (void*)_stack.target_top();
229 this->prog_attach_ds(this->_stack.target_addr(),
230 this->_stack.stack_size(),
232 0, 0, "stack segment", _local_stack_address);
233 prog_info()->stack_addr = _stack.target_addr() + _stack.stack_size();
235 MSG() << std::hex << (void*)_stack.ptr() << " <-> "
236 << (void*)_stack.relocate(_stack.ptr());
241 void Romain::App_model::prog_reserve_utcb_area()
243 _utcb_area = this->alloc_ds(1 << prog_info()->utcbs_log2size);
245 MSG() << __func__ << " " << std::hex
246 << (void*)this->prog_info()->utcbs_start;
248 this->prog_attach_ds(this->prog_info()->utcbs_start,
249 1 << this->prog_info()->utcbs_log2size,
250 _utcb_area, 0, 0, "utcb area",
255 void const *Romain::App_model::generate_l4aux(char const *name)
257 this->_stack.push(l4_umword_t(this->prog_info()->ldr_flags));
258 this->_stack.push(l4_umword_t(this->prog_info()->l4re_dbg));
259 this->_stack.push(l4_umword_t(local_kip_ds().cap()));
260 return this->_stack.push_local_ptr(name);