1 /*
2 * (c) 2010 Alexander Warg <warg@os.inf.tu-dresden.de>
3 * economic rights: Technische Universität Dresden (Germany)
4 *
5 * This file is part of TUD:OS and distributed under the terms of the
6 * GNU General Public License 2.
7 * Please see the COPYING-GPL-2 file for details.
8 */
9
10 #include "app_model.h"
11
12 #include <l4/re/error_helper>
13 #include <l4/re/util/env_ns>
14
15 using L4Re::chksys;
16 using L4Re::chkcap;
17
18 App_model::Dataspace
alloc_ds(unsigned long size) const19 App_model::alloc_ds(unsigned long size) const
20 {
21 Dataspace mem = chkcap(L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>(),
22 "allocate capability");
23 L4::Cap<L4Re::Mem_alloc> _ma(prog_info()->mem_alloc.raw & L4_FPAGE_ADDR_MASK);
24 chksys(_ma->alloc(size, mem.get()), "allocate writable program segment");
25 return mem;
26 }
27
28 App_model::Const_dataspace
open_file(char const * name)29 App_model::open_file(char const *name)
30 {
31 L4Re::Util::Env_ns ens;
32 return L4Re::chkcap(ens.query<L4Re::Dataspace>(name), name, 0);
33 }
34
35 void
prog_attach_ds(l4_addr_t addr,unsigned long size,Const_dataspace ds,unsigned long offset,L4Re::Rm::Flags flags,char const * what)36 App_model::prog_attach_ds(l4_addr_t addr, unsigned long size,
37 Const_dataspace ds, unsigned long offset,
38 L4Re::Rm::Flags flags, char const *what)
39 {
40 auto rh_flags = flags;
41
42 if (0)
43 printf("%s:%s: from ds:%lx+%lx... @%lx+%lx\n",
44 __func__, what, ds.cap(), offset, addr, size);
45
46 if (!ds.is_valid())
47 rh_flags |= L4Re::Rm::F::Reserved;
48
49 l4_addr_t _addr = addr;
50 L4Re::chksys(_task->rm()->attach(&_addr, size, rh_flags,
51 L4::Ipc::make_cap(ds.get(), flags.cap_rights()),
52 offset, 0), what);
53 }
54
55 int
prog_reserve_area(l4_addr_t * start,unsigned long size,L4Re::Rm::Flags flags,unsigned char align)56 App_model::prog_reserve_area(l4_addr_t *start, unsigned long size,
57 L4Re::Rm::Flags flags, unsigned char align)
58 {
59 return _task->rm()->reserve_area(start, size, flags, align);
60 }
61
62
63 void
copy_ds(Dataspace dst,unsigned long dst_offs,Const_dataspace src,unsigned long src_offs,unsigned long size)64 App_model::copy_ds(Dataspace dst, unsigned long dst_offs,
65 Const_dataspace src, unsigned long src_offs,
66 unsigned long size)
67 {
68 L4Re::chksys(dst->copy_in(dst_offs, src.get(), src_offs, size),
69 "Ned program launch: copy failed");
70 }
71
72
73 l4_addr_t
local_attach_ds(Const_dataspace ds,unsigned long size,unsigned long offset) const74 App_model::local_attach_ds(Const_dataspace ds, unsigned long size,
75 unsigned long offset) const
76 {
77 L4::Cap<L4Re::Rm> rm = L4Re::Env::env()->rm();
78 l4_addr_t pg_offset = l4_trunc_page(offset);
79 l4_addr_t in_pg_offset = offset - pg_offset;
80 unsigned long pg_size = l4_round_page(size + in_pg_offset);
81 l4_addr_t vaddr = 0;
82 chksys(rm->attach(&vaddr, pg_size,
83 L4Re::Rm::F::Search_addr | L4Re::Rm::F::R,
84 ds.get(), pg_offset),
85 "attach temporary VMA");
86 return vaddr + in_pg_offset;
87 }
88
89 void
local_detach_ds(l4_addr_t addr,unsigned long) const90 App_model::local_detach_ds(l4_addr_t addr, unsigned long /*size*/) const
91 {
92 L4::Cap<L4Re::Rm> rm = L4Re::Env::env()->rm();
93 l4_addr_t pg_addr = l4_trunc_page(addr);
94 chksys(rm->detach(pg_addr, 0), "detach temporary VMA");
95 }
96
97
App_model()98 App_model::App_model()
99 : _task(0)
100 {
101 // set default values for utcb area, values may be changed by loader
102 _info.utcbs_start = Utcb_area_start;
103 _info.utcbs_log2size = L4_PAGESHIFT;
104
105 // set default values for the application stack
106 extern char __L4_KIP_ADDR__[];
107 _info.kip = (l4_addr_t)__L4_KIP_ADDR__;
108 }
109
110
111 App_model::Dataspace
alloc_app_stack()112 App_model::alloc_app_stack()
113 {
114 L4Re::Util::Ref_cap<L4Re::Dataspace>::Cap stack
115 = chkcap(L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>(),
116 "allocate stack capability");
117 L4::Cap<L4Re::Mem_alloc> ma(prog_info()->mem_alloc.raw & L4_FPAGE_ADDR_MASK);
118 chksys(ma->alloc(_stack.stack_size(), stack.get()),
119 "allocate stack");
120
121 _stack.set_stack(stack, _stack.stack_size());
122
123 return stack.release();
124 }
125
126 void
init_prog()127 App_model::init_prog()
128 {
129
130 push_argv_strings();
131 push_env_strings();
132 Dbg info(Dbg::Info);
133 #if 0
134 _info.mem_alloc = _ma.fpage();
135 _info.names = _ns.fpage();
136 _info.log = _log.fpage();
137 _info.factory = _factory.fpage();
138 _info.scheduler = _sched.fpage();
139 _info.l4re_dbg = ~0;
140 #endif
141 #if 0
142 _info.ldr_flags = parser.ldr_flags.data;
143 _info.l4re_dbg = parser.l4re_dbg.data;
144
145 if (parser.cpu_affinity.data != ~0UL || parser.base_prio.data != Default_base_prio
146 || parser.max_prio.data != Default_max_prio)
147 {
148 info.printf(" base_prio = 0x%x max_prio = 0x%x\n",
149 parser.base_prio.data, parser.max_prio.data);
150 _task->_sched.set_prio(parser.base_prio.data, parser.max_prio.data);
151 _task->_sched.restrict_cpus(parser.cpu_affinity.data);
152 Gate_alloc::alloc(&_task->_sched);
153 _info.scheduler = _task->_sched.obj_cap().fpage();
154 scheduler_if = &_task->_sched;
155 }
156 #endif
157 info.printf("loading '%s'\n", argv.a0);
158 }
159
160 void
get_task_caps(L4::Cap<L4::Factory> * factory,L4::Cap<L4::Task> * task,L4::Cap<L4::Thread> * thread)161 App_model::get_task_caps(L4::Cap<L4::Factory> *factory,
162 L4::Cap<L4::Task> *task,
163 L4::Cap<L4::Thread> *thread)
164 {
165 prog_info()->rm = _task->rm().fpage();
166 prog_info()->parent = _task->obj_cap().fpage();
167 Dbg(Dbg::Info).printf("parent cap is %lx\n", prog_info()->parent.raw);
168 *task = _task->task_cap();
169 *thread = _task->thread_cap();
170 *factory = L4::Cap<L4::Factory>(prog_info()->factory.raw & L4_FPAGE_ADDR_MASK);
171 }
172
173