]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/test/unit/mapdb_t.cpp
update
[l4.git] / kernel / fiasco / src / test / unit / mapdb_t.cpp
1 IMPLEMENTATION:
2
3 #include <iostream>
4 #include <iomanip>
5 #include <cassert>
6 #include <cstdlib>
7
8 using namespace std;
9
10 #include "mapdb.h"
11
12 IMPLEMENTATION:
13
14 #include "config.h"
15 #include "space.h"
16
17 static Space *s0;
18 static Space *other;
19 static Space *client;
20 static Space *father;
21 static Space *&grandfather = s0;
22 static Space *son;
23 static Space *daughter;
24 static Space *aunt;
25
26 typedef Virt_addr Phys_addr;
27
28 static size_t page_sizes[] =
29 { Config::SUPERPAGE_SHIFT - Config::PAGE_SHIFT, 0 };
30
31 static size_t page_sizes_max = 2;
32
33 class Fake_factory : public Ram_quota
34 {
35 };
36
37 class Fake_task : public Space
38 {
39 public:
40   Fake_task(Ram_quota *r, char const *name)
41   : Space(r, Caps::all()), name(name) {}
42
43   char const *name;
44 };
45
46
47 static void init_spaces()
48 {
49   static Fake_factory rq;
50 #define NEW_TASK(name) name = new Fake_task(&rq, #name)
51   NEW_TASK(s0);
52   NEW_TASK(other);
53   NEW_TASK(client);
54   NEW_TASK(father);
55   NEW_TASK(son);
56   NEW_TASK(daughter);
57   NEW_TASK(aunt);
58 #undef NEW_TASK
59 }
60
61 static
62 std::ostream &operator << (std::ostream &s, Mapdb::Pfn v)
63 {
64   s << cxx::int_value<Mapdb::Pfn>(v);
65   return s;
66 }
67
68 static
69 std::ostream &operator << (std::ostream &s, Mapping::Page v)
70 {
71   s << cxx::int_value<Mapping::Page>(v);
72   return s;
73 }
74
75 static
76 std::ostream &operator << (std::ostream &s, Space const &sp)
77 {
78   Fake_task const *t = static_cast<Fake_task const *>(&sp);
79   if (!t)
80     s << "<NULL>";
81   else
82     s << t->name;
83   return s;
84 }
85
86 static void print_node(Mapping* node, const Mapdb::Frame& frame)
87 {
88   assert (node);
89
90   for (Mapdb::Iterator i(frame, node, Mapdb::Pfn(0), Mapdb::Pfn(~0)); node;)
91     {
92       cout << "[UTEST] ";
93       for (int d = node->depth(); d != 0; d--)
94         cout << ' ';
95
96       auto shift = i.order();
97
98       cout << setbase(16)
99            << "space="  << *node->space()
100            << " vaddr=0x" << (node->page() << shift)
101            << " size=0x" << (Mapdb::Pfn(1) << shift);
102
103       if (Mapping* p = node->parent())
104         {
105           cout << " parent=" << *p->space()
106                << " p.vaddr=0x" << (p->page() << shift);
107         }
108
109       cout << endl;
110
111       node = i;
112       if (node)
113         ++i;
114     }
115   cout << "[UTEST] " << endl;
116 }
117
118 static
119 Mapdb::Pfn to_pfn(Address a)
120 { return Mem_space::to_pfn(Mem_space::V_pfn(Virt_addr(a))); }
121
122 static
123 Mapdb::Pcnt to_pcnt(unsigned order)
124 { return Mem_space::to_pcnt(Mem_space::Page_order(order)); }
125
126 void basic()
127 {
128   unsigned phys_bits = 32;
129   Mapdb m (s0, Mapping::Page(1U << (phys_bits - Config::PAGE_SHIFT - page_sizes[0])), page_sizes, page_sizes_max);
130
131   Mapping *node, *sub;
132   Mapdb::Frame frame;
133
134   typedef Mem_space SPACE;
135   typedef SPACE::V_pfn V_pfn;
136   typedef SPACE::V_pfc V_pfc;
137   typedef SPACE::Phys_addr Phys_addr;
138   typedef SPACE::Page_order Page_order;
139
140   assert (! m.lookup(other, to_pfn(Config::PAGE_SIZE),
141                      to_pfn(Config::PAGE_SIZE),
142                      &node, &frame));
143
144   cout << "[UTEST] Looking up 4M node at physaddr=0K" << endl;
145   assert (m.lookup (s0,  to_pfn(0),
146                     to_pfn(0),
147                     &node, &frame));
148   print_node (node, frame);
149
150   cout << "[UTEST] Inserting submapping" << endl;
151   sub = m.insert (frame, node, other,
152                   to_pfn(2*Config::PAGE_SIZE),
153                   to_pfn(Config::PAGE_SIZE),
154                   to_pcnt(Config::PAGE_SHIFT));
155   print_node (node, frame);
156
157   m.free (frame);
158
159   //////////////////////////////////////////////////////////////////////
160
161   cout << "[UTEST] Looking up 4M node at physaddr=8M" << endl;
162   assert (m.lookup (s0,
163                     to_pfn(2*Config::SUPERPAGE_SIZE),
164                     to_pfn(2*Config::SUPERPAGE_SIZE),
165                     &node, &frame));
166   print_node (node, frame);
167
168   // XXX broken mapdb: assert (node->size() == Config::SUPERPAGE_SIZE);
169
170   cout << "[UTEST] Inserting submapping" << endl;
171   sub = m.insert (frame, node, other,
172                   to_pfn(4*Config::SUPERPAGE_SIZE),
173                   to_pfn(2*Config::SUPERPAGE_SIZE),
174                   to_pcnt(Config::SUPERPAGE_SHIFT));
175   print_node (node, frame);
176
177   assert (m.shift(frame, sub) == Mapdb::Order(Config::SUPERPAGE_SHIFT - Config::PAGE_SHIFT));
178
179   // Before we can insert new mappings, we must free the tree.
180   m.free (frame);
181
182   cout << "[UTEST] Get that mapping again" << endl;
183   assert (m.lookup (other,
184                     to_pfn(4*Config::SUPERPAGE_SIZE),
185                     to_pfn(2*Config::SUPERPAGE_SIZE),
186                     &sub, &frame));
187   print_node (sub, frame);
188
189   node = sub->parent();
190
191   cout << "[UTEST] Inserting 4K submapping" << endl;
192   assert ( m.insert (frame, sub, client,
193                      to_pfn(15*Config::PAGE_SIZE),
194                      to_pfn(2*Config::SUPERPAGE_SIZE),
195                      to_pcnt(Config::PAGE_SHIFT)));
196   print_node (node, frame);
197
198   m.free (frame);
199 }
200
201 static void print_whole_tree(Mapping *node, const Mapdb::Frame& frame)
202 {
203   while(node->parent())
204     node = node->parent();
205   print_node (node, frame);
206 }
207
208
209 void maphole()
210 {
211   Mapdb m (s0, Mapping::Page(1U << (32 - Config::PAGE_SHIFT - page_sizes[0])),
212       page_sizes, page_sizes_max);
213
214   Mapping *gf_map, *f_map, *son_map, *daughter_map;
215   Mapdb::Frame frame;
216
217   cout << "[UTEST] Looking up 4K node at physaddr=0" << endl;
218   assert (m.lookup (grandfather, to_pfn(0),
219                     to_pfn(0), &gf_map, &frame));
220   print_whole_tree (gf_map, frame);
221
222   cout << "[UTEST] Inserting father mapping" << endl;
223   f_map = m.insert (frame, gf_map, father, to_pfn(0),
224                     to_pfn(0),
225                     to_pcnt(Config::PAGE_SHIFT));
226   print_whole_tree (gf_map, frame);
227   m.free(frame);
228
229
230   cout << "[UTEST] Looking up father at physaddr=0" << endl;
231   assert (m.lookup (father, to_pfn(0),
232                     to_pfn(0), &f_map, &frame));
233   print_whole_tree (f_map, frame);
234
235   cout << "[UTEST] Inserting son mapping" << endl;
236   son_map = m.insert (frame, f_map, son, to_pfn(0),
237                       to_pfn(0),
238                       to_pcnt(Config::PAGE_SHIFT));
239   print_whole_tree (f_map, frame);
240   m.free(frame);
241
242
243   cout << "[UTEST] Looking up father at physaddr=0" << endl;
244   assert (m.lookup (father, to_pfn(0),
245                     to_pfn(0), &f_map, &frame));
246   print_whole_tree (f_map, frame);
247
248   cout << "[UTEST] Inserting daughter mapping" << endl;
249   daughter_map = m.insert (frame, f_map, daughter, to_pfn(0),
250                            to_pfn(0),
251                            to_pcnt(Config::PAGE_SHIFT));
252   print_whole_tree (f_map, frame);
253   m.free(frame);
254
255
256   cout << "[UTEST] Looking up son at physaddr=0" << endl;
257   assert (m.lookup(son, to_pfn(0),
258                    to_pfn(0), &son_map, &frame));
259   f_map = son_map->parent();
260   print_whole_tree (son_map, frame);
261
262   cout << "[UTEST] Son has accident on return from disco" << endl;
263   m.flush(frame, son_map, L4_map_mask::full(),
264           to_pfn(0),
265           to_pfn(Config::PAGE_SIZE));
266   m.free(frame);
267
268   cout << "[UTEST] Lost aunt returns from holidays" << endl;
269   assert (m.lookup (grandfather, to_pfn(0),
270                     to_pfn(0), &gf_map, &frame));
271   print_whole_tree (gf_map, frame);
272
273   cout << "[UTEST] Inserting aunt mapping" << endl;
274   assert (m.insert (frame, gf_map, aunt, to_pfn(0),
275                     to_pfn(0),
276                     to_pcnt(Config::PAGE_SHIFT)));
277   print_whole_tree (gf_map, frame);
278   m.free(frame);
279
280   cout << "[UTEST] Looking up daughter at physaddr=0" << endl;
281   assert (m.lookup(daughter, to_pfn(0),
282                    to_pfn(0), &daughter_map, &frame));
283   print_whole_tree (daughter_map, frame);
284   f_map = daughter_map->parent();
285   cout << "[UTEST] Father of daugther is " << *f_map->space() << endl;
286
287   assert(f_map->space() == father);
288
289   m.free(frame);
290 }
291
292
293 void flushtest()
294 {
295   Mapdb m (s0, Mapping::Page(1U << (32 - Config::PAGE_SHIFT - page_sizes[0])),
296       page_sizes, page_sizes_max);
297
298   Mapping *gf_map, *f_map;
299   Mapdb::Frame frame;
300
301   cout << "[UTEST] Looking up 4K node at physaddr=0" << endl;
302   assert (m.lookup (grandfather, to_pfn(0), to_pfn(0), &gf_map, &frame));
303   print_whole_tree (gf_map, frame);
304
305   cout << "[UTEST] Inserting father mapping" << endl;
306   f_map = m.insert (frame, gf_map, father, to_pfn(0), to_pfn(0), to_pcnt(Config::PAGE_SHIFT));
307   print_whole_tree (gf_map, frame);
308   m.free(frame);
309
310
311   cout << "[UTEST] Looking up father at physaddr=0" << endl;
312   assert (m.lookup (father, to_pfn(0), to_pfn(0), &f_map, &frame));
313   print_whole_tree (f_map, frame);
314
315   cout << "[UTEST] Inserting son mapping" << endl;
316   assert (m.insert (frame, f_map, son, to_pfn(0), to_pfn(0), to_pcnt(Config::PAGE_SHIFT)));
317   print_whole_tree (f_map, frame);
318   m.free(frame);
319
320   cout << "[UTEST] Lost aunt returns from holidays" << endl;
321   assert (m.lookup (grandfather, to_pfn(0), to_pfn(0), &gf_map, &frame));
322   print_whole_tree (gf_map, frame);
323
324   cout << "[UTEST] Inserting aunt mapping" << endl;
325   assert (m.insert (frame, gf_map, aunt, to_pfn(0), to_pfn(0), to_pcnt(Config::PAGE_SHIFT)));
326   print_whole_tree (gf_map, frame);
327   m.free(frame);
328
329   cout << "[UTEST] Looking up father at physaddr=0" << endl;
330   assert (m.lookup(father, to_pfn(0), to_pfn(0), &f_map, &frame));
331   gf_map = f_map->parent();
332   print_whole_tree (gf_map, frame);
333
334   cout << "[UTEST] father is killed by his new love" << endl;
335   m.flush(frame, f_map, L4_map_mask::full(), to_pfn(0), to_pfn(Config::PAGE_SIZE));
336   print_whole_tree (gf_map, frame);
337   m.free(frame);
338
339   cout << "[UTEST] Try resurrecting the killed father again" << endl;
340   assert (! m.lookup(father, to_pfn(0), to_pfn(0), &f_map, &frame));
341
342   cout << "[UTEST] Resurrection is impossible, as it ought to be." << endl;
343 }
344
345 void multilevel ()
346 {
347   size_t page_sizes[] = { 30 - Config::PAGE_SHIFT,
348       22 - Config::PAGE_SHIFT,
349       0};
350   Mapdb m (s0, Mapping::Page(1U << (42 - Config::PAGE_SHIFT - page_sizes[0])),
351       page_sizes, sizeof(page_sizes) / sizeof(page_sizes[0]));
352
353   Mapping *node /* , *sub, *subsub */;
354   Mapdb::Frame frame;
355
356   cout << "[UTEST] Looking up 0xd2000000" << endl;
357   assert (m.lookup (s0, to_pfn(0xd2000000), to_pfn(0xd2000000), &node, &frame));
358
359   print_node (node, frame);
360 }
361
362 #include "boot_info.h"
363 #include "cpu.h"
364 #include "config.h"
365 #include "kip_init.h"
366 #include "kmem.h"
367 #include "kmem_alloc.h"
368 #include "per_cpu_data_alloc.h"
369 #include "static_init.h"
370 #include "usermode.h"
371
372 class Timeout;
373
374 DEFINE_PER_CPU Per_cpu<Timeout *> timeslice_timeout;
375 STATIC_INITIALIZER_P(init, STARTUP_INIT_PRIO);
376 STATIC_INITIALIZER_P(init2, POST_CPU_LOCAL_INIT_PRIO);
377
378 static void init()
379 {
380   Usermode::init(Cpu_number::boot_cpu());
381   Boot_info::init();
382   Kip_init::init();
383   Kmem_alloc::base_init();
384   Kmem_alloc::init();
385
386   // Initialize cpu-local data management and run constructors for CPU 0
387   Per_cpu_data::init_ctors();
388   Per_cpu_data_alloc::alloc(Cpu_number::boot_cpu());
389   Per_cpu_data::run_ctors(Cpu_number::boot_cpu());
390
391 }
392
393 static void init2()
394 {
395   Cpu::init_global_features();
396   Config::init();
397   Kmem::init_mmu(Cpu::cpus.cpu(Cpu_number::boot_cpu()));
398 }
399
400 int main()
401 {
402   init_spaces();
403   cout << "[UTEST] Basic test" << endl;
404   basic();
405   cout << "[UTEST] ########################################" << endl;
406
407   cout << "[UTEST] Hole test" << endl;
408   maphole();
409   cout << "[UTEST] ########################################" << endl;
410
411   cout << "[UTEST] Flush test" << endl;
412   flushtest();
413   cout << "[UTEST] ########################################" << endl;
414
415   cout << "Multilevel test" << endl;
416   multilevel();
417   cout << "[UTEST] ########################################" << endl;
418
419   cerr << "OK" << endl;
420   return(0);
421 }