]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/sigma0/server/src/memmap.cc
7e60fc49b62474ced9f4c9a0f630c539742dd8bc
[l4.git] / l4 / pkg / sigma0 / server / src / memmap.cc
1 /*
2  * (c) 2008-2009 Technische Universität Dresden
3  * This file is part of TUD:OS and distributed under the terms of the
4  * GNU General Public License 2.
5  * Please see the COPYING-GPL-2 file for details.
6  */
7 #include <l4/sys/types.h>
8 #include <l4/sys/ipc.h>
9 #include <l4/sys/kdebug.h>
10 #include <l4/sys/factory.h>
11 #include <l4/sys/capability>
12 #include <l4/sys/typeinfo_svr>
13 #include <l4/sys/factory>
14
15 #include <l4/sigma0/sigma0.h>
16
17 #include <l4/cxx/iostream>
18 #include <l4/cxx/l4iostream>
19 #include <l4/cxx/l4types.h>
20
21 #include "globals.h"
22 #include "page_alloc.h"
23 #include "mem_man.h"
24 #include "memmap.h"
25 #include "memmap_internal.h"
26 #include "ioports.h"
27
28
29 l4_addr_t        mem_high;
30 l4_kernel_info_t *l4_info;
31 l4_addr_t        tbuf_status;
32
33 Mem_man iomem;
34
35
36 enum Requests
37 {
38   None,
39   Map_free_page,
40   Map_kip,
41   Map_tbuf,
42   Map_ram,
43   Map_iomem,
44   Map_iomem_cached,
45   Debug_dump,
46 };
47
48 enum Memory_type { Ram, Io_mem, Io_mem_cached };
49
50 void dump_all()
51 {
52   L4::cout << PROG_NAME": Dump of all resource maps\n"
53            << "RAM:------------------------\n";
54   Mem_man::ram()->dump();
55   L4::cout << "IOMEM:----------------------\n";
56   iomem.dump();
57   dump_io_ports();
58 }
59
60 static
61 void map_kip(Answer *a)
62 {
63   a->snd_fpage((l4_umword_t) l4_info, L4_LOG2_PAGESIZE, true);
64   a->snd_base((l4_umword_t) l4_info);
65   a->tag = l4_msgtag(0, 0, 1, 0);
66 }
67
68 static
69 void new_client(l4_umword_t, Answer *a)
70 {
71   static l4_cap_idx_t _next_gate = 10 << L4_CAP_SHIFT;
72   l4_factory_create_gate_u(L4_BASE_FACTORY_CAP, _next_gate,
73                            L4_BASE_THREAD_CAP, (_next_gate >> L4_CAP_SHIFT) << 4, a->utcb);
74   a->snd_base(0);
75   a->snd_fpage(l4_obj_fpage(_next_gate, 0, L4_FPAGE_RWX));
76   a->tag = l4_msgtag(0,0,1,0);
77   _next_gate += L4_CAP_SIZE;
78   return;
79 #if 0
80   a->snd_fpage((l4_umword_t) l4_info, L4_LOG2_PAGESIZE, true);
81   a->snd_base((l4_umword_t) l4_info);
82   a->tag = l4_msgtag(0, 0, 1, 0);
83 #endif
84 }
85
86 static
87 void map_tbuf(Answer *a)
88 {
89   if (tbuf_status != 0x00000000 && tbuf_status != ~0UL)
90     {
91       a->snd_fpage(tbuf_status, L4_LOG2_PAGESIZE, false);
92       a->snd_base(tbuf_status);
93       a->tag = l4_msgtag(0, 0, 1, 0);
94     }
95 }
96
97 static
98 void map_free_page(unsigned size, l4_umword_t t, Answer *a)
99 {
100   unsigned long addr;
101   addr = Mem_man::ram()->alloc_first(1UL << size, t);
102   if (addr != ~0UL)
103     {
104       a->snd_base(addr);
105       a->snd_fpage(addr, size);
106
107       a->tag = l4_msgtag(0, 0, 1, 0);
108
109       if (t < root_taskno) /* sender == kernel? */
110         a->do_grant(); /* kernel wants page granted */
111     }
112   else
113     a->clear();
114 }
115
116
117 static
118 void map_mem(l4_fpage_t fp, Memory_type fn, l4_umword_t t, Answer *an)
119 {
120   an->clear();
121   Mem_man *m;
122   switch (fn)
123     {
124     case Ram:
125       m = Mem_man::ram();
126       break;
127     case Io_mem:
128     case Io_mem_cached:
129       m = &iomem;
130       break;
131     default:
132       return;
133     }
134
135   unsigned long addr = m->alloc(Region::bs(fp.raw & ~((1UL << 12) - 1),
136         1UL << l4_fpage_size(fp), t));
137
138   if (addr == ~0UL)
139     return;
140
141   /* the Fiasco kernel makes the page non-cachable if the frame
142    * address is greater than mem_high */
143   an->snd_base(addr);
144   an->snd_fpage(addr, l4_fpage_size(fp), false, fn != Io_mem);
145   an->tag = l4_msgtag(0, 0, 1, 0);
146
147   return;
148 }
149
150 /* handler for page fault fault requests */
151 static
152 void
153 handle_page_fault(l4_umword_t t, l4_utcb_t *utcb, Answer *answer)
154 {
155   unsigned long pfa = l4_utcb_mr_u(utcb)->mr[0] & ~3UL;
156
157
158   answer->clear();
159
160   unsigned long addr
161     = Mem_man::ram()->alloc(Region::bs(l4_trunc_page(pfa), L4_PAGESIZE, t));
162
163   if (addr != ~0UL)
164     {
165       answer->snd_base(addr);
166       answer->snd_fpage(pfa, L4_LOG2_PAGESIZE);
167       answer->tag = l4_msgtag(0, 0, 1, 0);
168     }
169   else if (debug_warnings)
170     L4::cout << PROG_NAME": Page fault, did not find page at "
171              << L4::hex << pfa << " for " << L4::dec << t << "\n";
172 }
173
174 static
175 void handle_service_request(l4_umword_t t, l4_utcb_t *utcb, Answer *answer)
176 {
177   if ((long)l4_utcb_mr_u(utcb)->mr[0] != L4_PROTO_SIGMA0)
178     {
179       answer->clear();
180       answer->tag = l4_msgtag(-L4_ENODEV, 0, 0, 0);
181       return;
182     }
183   new_client(t, answer);
184 }
185
186 static
187 void handle_sigma0_request(l4_umword_t t, l4_utcb_t *utcb, Answer *answer)
188 {
189   if (!SIGMA0_IS_MAGIC_REQ(l4_utcb_mr_u(utcb)->mr[0]))
190     {
191       answer->clear();
192       return;
193     }
194
195   switch (l4_utcb_mr_u(utcb)->mr[0] & 0x0f0)
196     {
197     case SIGMA0_REQ_ID_DEBUG_DUMP:
198         {
199           Mem_man::Tree::Node_allocator alloc;
200           L4::cout << PROG_NAME": Memory usage: a total of "
201             << Page_alloc_base::total()
202             << " byte are in the memory pool\n"
203             << "  allocated "
204             << alloc.total_objects() - alloc.free_objects()
205             << " of " << alloc.total_objects() << " objects\n"
206             << "  this are "
207             << (alloc.total_objects() - alloc.free_objects())
208             * alloc.object_size
209             << " of " << alloc.total_objects() * alloc.object_size
210             << " byte\n";
211           dump_all();
212           answer->clear();
213         }
214       break;
215     case SIGMA0_REQ_ID_TBUF:
216       map_tbuf(answer);
217       break;
218     case SIGMA0_REQ_ID_FPAGE_RAM:
219       map_mem((l4_fpage_t&)l4_utcb_mr_u(utcb)->mr[1], Ram, t, answer);
220       break;
221     case SIGMA0_REQ_ID_FPAGE_IOMEM:
222       map_mem((l4_fpage_t&)l4_utcb_mr_u(utcb)->mr[1], Io_mem, t, answer);
223       break;
224     case SIGMA0_REQ_ID_FPAGE_IOMEM_CACHED:
225       map_mem((l4_fpage_t&)l4_utcb_mr_u(utcb)->mr[1], Io_mem_cached, t, answer);
226       break;
227     case SIGMA0_REQ_ID_KIP:
228       map_kip(answer);
229       break;
230     case SIGMA0_REQ_ID_FPAGE_ANY:
231       map_free_page(l4_fpage_size(*(l4_fpage_t*)(&l4_utcb_mr_u(utcb)->mr[1])), t, answer);
232       break;
233     case SIGMA0_REQ_ID_NEW_CLIENT:
234       new_client(t, answer);
235       break;
236     default:
237       answer->clear();
238       break;
239     }
240 }
241
242 namespace {
243
244 class Sigma0 :
245   public L4::Kobject_t<Sigma0, L4::Factory, L4_PROTO_SIGMA0>
246 {};
247
248 }
249
250 /* PAGER dispatch loop */
251 void
252 pager(void)
253 {
254   l4_umword_t t;
255   l4_msgtag_t tag;
256
257   l4_utcb_t *utcb = l4_utcb();
258   l4_msg_regs_t *mr = l4_utcb_mr_u(utcb);
259   Answer answer(utcb);
260
261   /* now start serving the subtasks */
262   for (;;)
263     {
264       tag = l4_ipc_wait(utcb, &t, L4_IPC_NEVER);
265 #if 0
266           L4::cout << "w: res=" << L4::MsgDope(result)
267                    << " tag=" << L4::dec << l4_msgtag_label(tag) << '\n';
268 #endif
269       //L4::cout << PROG_NAME << ": rcv: " << tag << "\n";
270       while (!l4_msgtag_has_error(tag))
271         {
272           l4_umword_t pfa = mr->mr[0];
273           t >>= 4;
274           /* we received a paging request here */
275           /* handle the sigma0 protocol */
276
277           if (debug_ipc)
278             L4::cout << PROG_NAME": received " << tag << " d1=" << L4::hex << mr->mr[0]
279               << " d2=" << mr->mr[1] << L4::dec << " from thread=" << t << '\n';
280
281           answer.tag = l4_msgtag(0,0,0,0);
282
283           switch(tag.label())
284             {
285             case L4_PROTO_SIGMA0:
286               handle_sigma0_request(t, utcb, &answer);
287               break;
288             case L4::Meta::Protocol:
289                 {
290                   L4::Ipc::Iostream ios(utcb);
291                   ios.Istream::tag() = tag;
292                   answer.tag = l4_msgtag(L4::Util::handle_meta_request<Sigma0>(ios), 0, 0, 0);
293                 }
294               break;
295             case L4::Factory::Protocol:
296               handle_service_request(t, utcb, &answer);
297               break;
298             case L4_PROTO_PAGE_FAULT:
299               handle_page_fault(t, utcb, &answer);
300               break;
301             case L4_PROTO_IO_PAGE_FAULT:
302               handle_io_page_fault(t, utcb, &answer);
303               break;
304             default:
305               answer.clear();
306               break;
307             }
308
309           if (answer.failed())
310             {
311               if (debug_warnings)
312                 {
313                   L4::cout << PROG_NAME": can't handle label=" << L4::dec
314                            << l4_msgtag_label(tag)
315                            << " d1=" << L4::hex << pfa
316                            << " d2=" << mr->mr[1]
317                            << " from thread=" << L4::dec << t << '\n';
318                   if (tag.is_page_fault())
319                     Mem_man::ram()->dump();
320                 }
321
322               if (tag.is_exception())
323                 enter_kdebug("s1");
324             }
325
326           if (debug_ipc)
327             L4::cout << PROG_NAME": sending d1=" << L4::hex << mr->mr[0]
328               << " d2=" << mr->mr[1]
329               << " msg=" << answer.tag << L4::dec
330               << " to thread=" << t << '\n';
331
332           /* send reply and wait for next message */
333           tag = l4_ipc_reply_and_wait(utcb, answer.tag, &t, L4_IPC_SEND_TIMEOUT_0);
334 #if 0
335           L4::cout << "rplw: res=" << L4::MsgDope(result)
336                    << " tag=" << L4::dec << l4_msgtag_label(tag) << '\n';
337 #endif
338
339         }
340     }
341 }
342