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