]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/jdb/jdb_mapdb.cpp
update
[l4.git] / kernel / fiasco / src / jdb / jdb_mapdb.cpp
1 IMPLEMENTATION:
2
3 #include <cstdio>
4
5 #include "jdb.h"
6 #include "jdb_input.h"
7 #include "jdb_screen.h"
8 #include "kernel_console.h"
9 #include "kobject.h"
10 #include "keycodes.h"
11 #include "mapdb.h"
12 #include "mapdb_i.h"
13 #include "map_util.h"
14 #include "simpleio.h"
15 #include "static_init.h"
16 #include "task.h"
17 #include "jdb_kobject.h"
18 #include "jdb_kobject_names.h"
19
20 class Jdb_mapdb : public Jdb_module
21 {
22   friend class Jdb_kobject_mapdb_hdl;
23 public:
24   Jdb_mapdb() FIASCO_INIT;
25 private:
26   static Mword pagenum;
27   static char  subcmd;
28 };
29
30 char  Jdb_mapdb::subcmd;
31 Mword Jdb_mapdb::pagenum;
32
33 static
34 const char*
35 size_str (Mword size)
36 {
37   static char scratchbuf[6];
38   unsigned mult = 0;
39   while (size >= 1024)
40     {
41       size >>= 10;
42       mult++;
43     }
44   snprintf (scratchbuf, 6, "%u%c", unsigned(size), "BKMGTPX"[mult]);
45   return scratchbuf;
46 }
47
48 static
49 unsigned long long
50 Jdb_mapdb::val(Mdb_types::Pfn p, Mdb_types::Order base_size)
51 {
52   return cxx::int_value<Mdb_types::Pfn>(p << base_size);
53 }
54
55
56 static
57 bool
58 Jdb_mapdb::show_tree(Treemap* pages, Mapping::Pcnt offset, Mdb_types::Order base_size,
59                      unsigned &screenline, unsigned indent = 1)
60 {
61   typedef Treemap::Page Page;
62
63   Page       page = pages->trunc_to_page(offset);
64   Physframe*    f = pages->frame(page);
65   Mapping_tree* t = f->tree.get();
66   unsigned      i;
67   int           c;
68
69   if (! t)
70     {
71       printf(" no mapping tree registered for frame number 0x%lx\033[K\n",
72              cxx::int_value<Mapping::Page>(page));
73       screenline++;
74       return true;
75     }
76
77   printf(" mapping tree for %s-page %012llx of task %lx - header at "
78          L4_PTR_FMT "\033[K\n",
79          size_str(1ULL << cxx::int_value<Mdb_types::Order>(pages->_page_shift + base_size)),
80          val(pages->vaddr(t->mappings()), base_size),
81          Kobject_dbg::pointer_to_id(t->mappings()[0].space()),
82          (Address)t);
83 #ifdef NDEBUG
84   // If NDEBUG is active, t->_empty_count is undefined
85   printf(" header info: "
86          "entries used: %u  free: --  total: %u  lock=%u\033[K\n",
87          t->_count, t->number_of_entries(),
88          f->lock.test());
89
90   if (t->_count > t->number_of_entries())
91     {
92       printf("\033[K\n"
93              "\033[K\n"
94              "  seems to be a wrong tree ! ...exiting");
95       // clear rest of page
96       for (i=6; i<Jdb_screen::height(); i++)
97         printf("\033[K\n");
98       return false;
99     }
100 #else
101   printf(" header info: "
102          "entries used: %u  free: %u  total: %u  lock=%u\033[K\n",
103          t->_count, t->_empty_count, t->number_of_entries(),
104          f->lock.test());
105
106   if (unsigned (t->_count) + t->_empty_count > t->number_of_entries())
107     {
108       printf("\033[K\n"
109              "\033[K\n"
110              "  seems to be a wrong tree ! ...exiting");
111       // clear rest of page
112       for (i=6; i<Jdb_screen::height(); i++)
113         printf("\033[K\n");
114       return false;
115     }
116 #endif
117
118   Mapping* m = t->mappings();
119
120   screenline += 2;
121
122   for (i=0; i < t->_count; i++, m++)
123     {
124       Kconsole::console()->getchar_chance();
125
126       if (m->depth() == Mapping::Depth_submap)
127         printf("%*u: %lx  subtree@" L4_PTR_FMT,
128                indent + m->parent()->depth() > 10
129                  ? 0 : indent + m->parent()->depth(),
130                i+1, (Address) m->data(), (Mword) m->submap());
131       else
132         {
133           printf("%*u: %lx  va=%012llx  task=%lx  depth=",
134                  indent + m->depth() > 10 ? 0 : indent + m->depth(),
135                  i+1, (Address) m->data(),
136                  val(pages->vaddr(m), base_size),
137                  Kobject_dbg::pointer_to_id(m->space()));
138
139           if (m->depth() == Mapping::Depth_root)
140             printf("root");
141           else if (m->depth() == Mapping::Depth_empty)
142             printf("empty");
143           else if (m->depth() == Mapping::Depth_end)
144             printf("end");
145           else
146             printf("%lu", static_cast<unsigned long>(m->depth()));
147         }
148
149       puts("\033[K");
150       screenline++;
151
152       if (screenline >= (m->depth() == Mapping::Depth_submap
153                          ? Jdb_screen::height() - 3
154                          : Jdb_screen::height()))
155         {
156           printf(" any key for next page or <ESC>");
157           Jdb::cursor(screenline, 33);
158           c = Jdb_core::getchar();
159           printf("\r\033[K");
160           if (c == KEY_ESC)
161             return false;
162           screenline = 3;
163           Jdb::cursor(3, 1);
164         }
165
166       if (m->depth() == Mapping::Depth_submap)
167         {
168           if (! Jdb_mapdb::show_tree(m->submap(),
169                                      cxx::get_lsb(offset, pages->_page_shift),
170                                      base_size,
171                                      screenline, indent + m->parent()->depth()))
172             return false;
173         }
174     }
175
176   return true;
177 }
178
179 static
180 Address
181 Jdb_mapdb::end_address (Mapdb* mapdb)
182 {
183   return cxx::int_value<Mdb_types::Pfn>(mapdb->_treemap->end_addr());
184 }
185
186 static
187 void
188 Jdb_mapdb::show(Mapping::Pfn page, char which_mapdb)
189 {
190   unsigned     j;
191   int          c;
192
193   Jdb::clear_screen();
194   typedef Mdb_types::Order Order;
195
196   for (;;)
197     {
198       Mapdb* mapdb;
199       const char* type;
200       Mapping::Pcnt super_inc;
201       Mdb_types::Order super_shift;
202       Order base_size = Order(0);
203
204       switch (which_mapdb)
205         {
206         case 'm':
207           type = "Phys frame";
208           mapdb = mapdb_mem.get();
209           base_size = Order(Config::PAGE_SHIFT);
210           super_shift = Mdb_types::Order(Config::SUPERPAGE_SHIFT - Config::PAGE_SHIFT);
211           break;
212 #ifdef CONFIG_PF_PC
213         case 'i':
214           type = "I/O port";
215           mapdb = mapdb_io.get();
216           base_size = Order(0);
217           super_shift = Mdb_types::Order(8);
218           break;
219 #endif
220         default:
221           return;
222         }
223
224       super_inc = Mapping::Pcnt(1) << super_shift;
225
226       if (! mapdb->valid_address(page))
227         page = Mapping::Pfn(0);
228
229       Jdb::cursor();
230       printf("%s %012llx\033[K\n\033[K\n", type, val(page, base_size));
231
232       j = 3;
233
234       if (! Jdb_mapdb::show_tree(mapdb->_treemap, page - Mapping::Pfn(0), base_size, j))
235         return;
236
237       for (; j<Jdb_screen::height(); j++)
238         puts("\033[K");
239
240       static char prompt[] = "mapdb[m]";
241       prompt[6] = which_mapdb;
242
243       Jdb::printf_statline(prompt,
244                            "n=next p=previous N=nextsuper P=prevsuper", "_");
245
246       for (bool redraw=false; !redraw; )
247         {
248           Jdb::cursor(Jdb_screen::height(), 10);
249           switch (c = Jdb_core::getchar())
250             {
251             case 'n':
252             case KEY_CURSOR_DOWN:
253               if (! mapdb->valid_address(++page))
254                 page = Mapping::Pfn(0);
255               redraw = true;
256               break;
257             case 'p':
258             case KEY_CURSOR_UP:
259               if (! mapdb->valid_address(--page))
260                 page = Mapping::Pfn(end_address(mapdb) - 1);
261               redraw = true;
262               break;
263             case 'N':
264             case KEY_PAGE_DOWN:
265               page = cxx::mask_lsb(page + super_inc, super_shift);
266               if (! mapdb->valid_address(page))
267                 page = Mapping::Pfn(0);
268               redraw = true;
269               break;
270             case 'P':
271             case KEY_PAGE_UP:
272               page = cxx::mask_lsb(page - super_inc, super_shift);
273               if (! mapdb->valid_address(page))
274                 page = Mapping::Pfn(end_address(mapdb) - 1);
275               redraw = true;
276               break;
277             case ' ':
278               if (which_mapdb == 'm')
279 #ifdef CONFIG_PF_PC
280                 which_mapdb = 'i';
281               else if (which_mapdb == 'i')
282 #endif
283                 which_mapdb = 'm';
284               redraw = true;
285               break;
286             case KEY_ESC:
287               Jdb::abort_command();
288               return;
289             default:
290               if (Jdb::is_toplevel_cmd(c))
291                 return;
292             }
293         }
294     }
295 }
296
297 PUBLIC
298 Jdb_module::Action_code
299 Jdb_mapdb::action(int cmd, void *&args, char const *&fmt, int &next_char)
300 {
301   static char which_mapdb = 'm';
302
303   if (cmd == 1)
304     {
305       dump_all_cap_trees();
306       return NOTHING;
307     }
308
309   if (cmd != 0)
310     return NOTHING;
311
312   if (args == (void*) &subcmd)
313     {
314       switch (subcmd)
315         {
316         default:
317           return NOTHING;
318
319         case '\r':
320         case ' ':
321           goto doit;
322
323         case '0' ... '9':
324         case 'a' ... 'f':
325         case 'A' ... 'F':
326           which_mapdb = 'm';
327           fmt = " frame: " L4_FRAME_INPUT_FMT;
328           args = &pagenum;
329           next_char = subcmd;
330           return EXTRA_INPUT_WITH_NEXTCHAR;
331
332         case 'm':
333           fmt = " frame: " L4_FRAME_INPUT_FMT;
334           break;
335
336 #ifdef CONFIG_PF_PC
337         case 'i':
338           fmt = " port: " L4_FRAME_INPUT_FMT;
339           break;
340 #endif
341         }
342
343       which_mapdb = subcmd;
344       args = &pagenum;
345       return EXTRA_INPUT;
346     }
347
348   else if (args != (void*) &pagenum)
349     return NOTHING;
350
351  doit:
352   show(Mapping::Pfn(pagenum), which_mapdb);
353   return NOTHING;
354 }
355
356 PUBLIC
357 Jdb_module::Cmd const *
358 Jdb_mapdb::cmds() const
359 {
360   static Cmd cs[] =
361     {
362         { 0, "m", "mapdb", "%c",
363           "m[i]<addr>\tshow [I/O] mapping database starting at address",
364           &subcmd },
365         { 1, "", "dumpmapdbobjs", "",
366           "dumpmapdbobjs\tDump complete object mapping database", 0 },
367     };
368   return cs;
369 }
370
371 PUBLIC
372 int
373 Jdb_mapdb::num_cmds() const
374 {
375   return 2;
376 }
377
378 IMPLEMENT
379 Jdb_mapdb::Jdb_mapdb()
380   : Jdb_module("INFO")
381 {}
382
383 static Jdb_mapdb jdb_mapdb INIT_PRIORITY(JDB_MODULE_INIT_PRIO);
384
385 // --------------------------------------------------------------------------
386 // Handler for kobject list
387
388 class Jdb_kobject_mapdb_hdl : public Jdb_kobject_handler
389 {
390 public:
391   Jdb_kobject_mapdb_hdl() : Jdb_kobject_handler(0) {}
392   virtual bool show_kobject(Kobject_common *, int) { return true; }
393   virtual ~Jdb_kobject_mapdb_hdl() {}
394 };
395
396 PUBLIC static FIASCO_INIT
397 void
398 Jdb_kobject_mapdb_hdl::init()
399 {
400   static Jdb_kobject_mapdb_hdl hdl;
401   Jdb_kobject::module()->register_handler(&hdl);
402 }
403
404 PUBLIC
405 bool
406 Jdb_kobject_mapdb_hdl::handle_key(Kobject_common *o, int keycode)
407 {
408   if (keycode == 'm')
409     {
410       Jdb_mapdb::show_simple_tree(o);
411       Jdb::getchar();
412       return true;
413     }
414   else
415     return false;
416 }
417
418
419
420 STATIC_INITIALIZE(Jdb_kobject_mapdb_hdl);
421
422 #if 0 // keep this for reanimation
423 static
424 void
425 Jdb_mapdb::dump_all_cap_trees()
426 {
427   printf("========= OBJECT DUMP BEGIN ===================\n");
428   Kobject *f = static_cast<Kobject*>(Kobject::_jdb_head.get_unused());
429   for (; f; f = static_cast<Kobject*>(f->_next))
430     {
431       char s[130];
432
433       Jdb_kobject::obj_description(s, sizeof(s), true, f);
434       s[sizeof(s) - 1] = 0;
435       printf("%s", s);
436
437       Mapping_tree *t = f->tree.get();
438
439       if (!t)
440         {
441           printf("\n");
442           continue;
443         }
444
445       Mapping *m = t->mappings();
446
447       printf(" intask=");
448       for (int i = 0; i < t->_count; i++, m++)
449         {
450           if (m->depth() == Mapping::Depth_submap)
451             printf("%s[subtree]", i ? "," : "");
452           else
453             printf("%s[%lx:%d]",
454                    i ? "," : "", Kobject::pointer_to_id(m->space()),
455                    m->depth());
456         }
457       printf("\n");
458
459       if (m->depth() == Mapping::Depth_submap)
460         {
461           printf("not good, submap in simple mapping tree\n");
462         }
463     }
464   printf("========= OBJECT DUMP END ===================\n");
465 }
466 #endif
467
468 // --------------------------------------------------------------------------
469 IMPLEMENTATION:
470
471 #include "dbg_page_info.h"
472
473 static
474 bool
475 Jdb_mapdb::show_simple_tree(Kobject_common *f, unsigned indent = 1)
476 {
477   (void)indent;
478   (void)f;
479
480   unsigned      screenline = 0;
481   int           c;
482
483   puts(Jdb_screen::Line);
484   if (!f || f->map_root()->_root.empty())
485     {
486       printf(" no mapping tree registered for frame number 0x%lx\033[K\n",
487              (unsigned long) f);
488       screenline++;
489       puts(Jdb_screen::Line);
490       return true;
491     }
492
493   printf(" mapping tree for object D:%lx (%p) ref_cnt=%ld\n",
494          f->dbg_info()->dbg_id(), f, f->map_root()->_cnt);
495
496   screenline += 2;
497
498   for (Obj::Mapping::List::Iterator m = f->map_root()->_root.begin();
499        m != f->map_root()->_root.end(); ++m)
500     {
501       Kconsole::console()->getchar_chance();
502
503       Obj::Entry *e = static_cast<Obj::Entry*>(*m);
504       Dbg_page_info *pi = Dbg_page_info::table()[Virt_addr(e)];
505
506       Mword space_id = ~0UL;
507       Address cap_idx = ((Address)e % Config::PAGE_SIZE) / sizeof(Obj::Entry);
508
509       if (pi)
510         {
511           space_id = static_cast<Task*>(pi->info<Obj::Cap_page_dbg_info>()->s)->dbg_info()->dbg_id();
512           cap_idx += pi->info<Obj::Cap_page_dbg_info>()->offset;
513         }
514
515       printf("  " L4_PTR_FMT "[C:%lx]: space=D:%lx rights=%x flags=%lx obj=%p",
516              (Address)*m, cap_idx, space_id,
517              (unsigned)cxx::int_value<Obj::Attr>(e->rights()), e->_flags,
518              e->obj());
519
520       puts("\033[K");
521       screenline++;
522
523       if (screenline >= Jdb_screen::height())
524         {
525           printf(" any key for next page or <ESC>");
526           Jdb::cursor(screenline, 33);
527           c = Jdb_core::getchar();
528           printf("\r\033[K");
529           if (c == KEY_ESC)
530             return false;
531           screenline = 3;
532           Jdb::cursor(3, 1);
533         }
534     }
535
536   puts(Jdb_screen::Line);
537   return true;
538 }
539
540 static
541 void
542 Jdb_mapdb::dump_all_cap_trees()
543 {
544   printf("========= OBJECT DUMP BEGIN ===================\n");
545   printf("========= OBJECT DUMP END ===================\n");
546 }
547
548