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.
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>
15 #include <l4/sigma0/sigma0.h>
17 #include <l4/cxx/iostream>
18 #include <l4/cxx/l4iostream>
19 #include <l4/cxx/l4types.h>
22 #include "page_alloc.h"
25 #include "memmap_internal.h"
30 l4_kernel_info_t *l4_info;
31 l4_addr_t tbuf_status;
48 enum Memory_type { Ram, Io_mem, Io_mem_cached };
52 L4::cout << PROG_NAME": Dump of all resource maps\n"
53 << "RAM:------------------------\n";
54 Mem_man::ram()->dump();
55 L4::cout << "IOMEM:----------------------\n";
61 void map_kip(Answer *a)
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);
69 void new_client(l4_umword_t, Answer *a)
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);
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;
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);
87 void map_tbuf(Answer *a)
89 if (tbuf_status != 0x00000000 && tbuf_status != ~0UL)
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);
98 void map_free_page(unsigned size, l4_umword_t t, Answer *a)
101 addr = Mem_man::ram()->alloc_first(1UL << size, t);
105 a->snd_fpage(addr, size);
107 a->tag = l4_msgtag(0, 0, 1, 0);
109 if (t < root_taskno) /* sender == kernel? */
110 a->do_grant(); /* kernel wants page granted */
118 void map_mem(l4_fpage_t fp, Memory_type fn, l4_umword_t t, Answer *an)
135 unsigned long addr = m->alloc(Region::bs(fp.raw & ~((1UL << 12) - 1),
136 1UL << l4_fpage_size(fp), t));
141 /* the Fiasco kernel makes the page non-cachable if the frame
142 * address is greater than mem_high */
144 an->snd_fpage(addr, l4_fpage_size(fp), false, fn != Io_mem);
145 an->tag = l4_msgtag(0, 0, 1, 0);
150 /* handler for page fault fault requests */
153 handle_page_fault(l4_umword_t t, l4_utcb_t *utcb, Answer *answer)
155 unsigned long pfa = l4_utcb_mr_u(utcb)->mr[0] & ~3UL;
161 = Mem_man::ram()->alloc(Region::bs(l4_trunc_page(pfa), L4_PAGESIZE, t));
165 answer->snd_base(addr);
166 answer->snd_fpage(pfa, L4_LOG2_PAGESIZE);
167 answer->tag = l4_msgtag(0, 0, 1, 0);
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";
175 void handle_service_request(l4_umword_t t, l4_utcb_t *utcb, Answer *answer)
177 if ((long)l4_utcb_mr_u(utcb)->mr[0] != L4_PROTO_SIGMA0)
180 answer->tag = l4_msgtag(-L4_ENODEV, 0, 0, 0);
183 new_client(t, answer);
187 void handle_sigma0_request(l4_umword_t t, l4_utcb_t *utcb, Answer *answer)
189 if (!SIGMA0_IS_MAGIC_REQ(l4_utcb_mr_u(utcb)->mr[0]))
195 switch (l4_utcb_mr_u(utcb)->mr[0] & 0x0f0)
197 case SIGMA0_REQ_ID_DEBUG_DUMP:
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"
204 << alloc.total_objects() - alloc.free_objects()
205 << " of " << alloc.total_objects() << " objects\n"
207 << (alloc.total_objects() - alloc.free_objects())
209 << " of " << alloc.total_objects() * alloc.object_size
215 case SIGMA0_REQ_ID_TBUF:
218 case SIGMA0_REQ_ID_FPAGE_RAM:
219 map_mem((l4_fpage_t&)l4_utcb_mr_u(utcb)->mr[1], Ram, t, answer);
221 case SIGMA0_REQ_ID_FPAGE_IOMEM:
222 map_mem((l4_fpage_t&)l4_utcb_mr_u(utcb)->mr[1], Io_mem, t, answer);
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);
227 case SIGMA0_REQ_ID_KIP:
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);
233 case SIGMA0_REQ_ID_NEW_CLIENT:
234 new_client(t, answer);
245 public L4::Kobject_t<Sigma0, L4::Factory, L4_PROTO_SIGMA0>
250 /* PAGER dispatch loop */
257 l4_utcb_t *utcb = l4_utcb();
258 l4_msg_regs_t *mr = l4_utcb_mr_u(utcb);
261 /* now start serving the subtasks */
264 tag = l4_ipc_wait(utcb, &t, L4_IPC_NEVER);
266 L4::cout << "w: res=" << L4::MsgDope(result)
267 << " tag=" << L4::dec << l4_msgtag_label(tag) << '\n';
269 //L4::cout << PROG_NAME << ": rcv: " << tag << "\n";
270 while (!l4_msgtag_has_error(tag))
272 l4_umword_t pfa = mr->mr[0];
274 /* we received a paging request here */
275 /* handle the sigma0 protocol */
278 L4::cout << PROG_NAME": received " << tag << " d1=" << L4::hex << mr->mr[0]
279 << " d2=" << mr->mr[1] << L4::dec << " from thread=" << t << '\n';
281 answer.tag = l4_msgtag(0,0,0,0);
285 case L4_PROTO_SIGMA0:
286 handle_sigma0_request(t, utcb, &answer);
288 case L4::Meta::Protocol:
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);
295 case L4::Factory::Protocol:
296 handle_service_request(t, utcb, &answer);
298 case L4_PROTO_PAGE_FAULT:
299 handle_page_fault(t, utcb, &answer);
301 case L4_PROTO_IO_PAGE_FAULT:
302 handle_io_page_fault(t, utcb, &answer);
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();
322 if (tag.is_exception())
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';
332 /* send reply and wait for next message */
333 tag = l4_ipc_reply_and_wait(utcb, answer.tag, &t, L4_IPC_SEND_TIMEOUT_0);
335 L4::cout << "rplw: res=" << L4::MsgDope(result)
336 << " tag=" << L4::dec << l4_msgtag_label(tag) << '\n';