]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/test/unit/map_util_t.cpp
7f03fe2320d80ed783d656be20408ebf13bd0a44
[l4.git] / kernel / fiasco / src / test / unit / map_util_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 "map_util.h"
11 #include "space.h"
12 #include "globals.h"
13 #include "config.h"
14
15 #include "boot_info.h"
16 #include "cpu.h"
17 #include "config.h"
18 #include "kip_init.h"
19 #include "kmem.h"
20 #include "kmem_alloc.h"
21 #include "per_cpu_data_alloc.h"
22 #include "pic.h"
23 #include "static_init.h"
24 #include "usermode.h"
25 #include "vmem_alloc.h"
26 #include "mem_space_sigma0.h"
27
28 IMPLEMENTATION:
29
30 typedef L4_fpage Test_fpage;
31
32 class Test_space : public Space
33 {
34 public:
35   Test_space (Ram_quota *rq)
36     : Space (Space::Default_factory(), rq, L4_fpage::mem(0x1200000, Config::PAGE_SHIFT))
37   {}
38
39   void* operator new (size_t s)
40   { return malloc (s); }
41
42   void operator delete (void *p)
43   { ::free (p); }
44 };
45
46 class Timeout;
47
48 DEFINE_PER_CPU Per_cpu<Timeout *> timeslice_timeout;
49 STATIC_INITIALIZER_P(init, STARTUP_INIT_PRIO);
50 STATIC_INITIALIZER_P(init2, POST_CPU_LOCAL_INIT_PRIO);
51
52 static void init()
53 {
54   Usermode::init(0);
55   Boot_info::init();
56   Kip_init::setup_ux();
57   Kmem_alloc::base_init();
58   Kip_init::init();
59   Kmem_alloc::init();
60
61   // Initialize cpu-local data management and run constructors for CPU 0
62   Per_cpu_data::init_ctors();
63   Per_cpu_data_alloc::alloc(0);
64   Per_cpu_data::run_ctors(0);
65
66 }
67
68 static void init2()
69 {
70   Cpu::init_global_features();
71   Config::init();
72   Kmem::init_mmu(*Cpu::boot_cpu());
73   Vmem_alloc::init();
74   Pic::init();
75 }
76
77 static Ram_quota rq;
78
79 struct Sigma0_space_factory
80 {
81   static void create(Mem_space *v, Ram_quota *q)
82   { new (v) Mem_space_sigma0(q); }
83
84   template< typename S >
85   static void create(S *v)
86   { new (v) S(); }
87
88 };
89
90 int main()
91 {
92   // 
93   // Create tasks
94   // 
95   Space *sigma0 = new Space (Sigma0_space_factory(), &rq, L4_fpage::mem(0x1200000, Config::PAGE_SHIFT));
96
97   init_mapdb_mem(sigma0);
98
99   Test_space *server = new Test_space (&rq);
100   assert (server);
101   Test_space *client = new Test_space (&rq);
102   assert (client);
103   Test_space *client2 = new Test_space (&rq);
104   assert (client2);
105
106   // 
107   // Manipulate mappings.
108   // 
109   Mapdb* mapdb = mapdb_instance();
110
111   Mem_space::Phys_addr phys;
112   Virt_size size;
113   unsigned page_attribs;
114   Mapping *m;
115   Mapdb::Frame frame;
116   
117   // 
118   // s0 [0x10000] -> server [0x1000]
119   // 
120   assert (server->mem_space()->v_lookup (Virt_addr(0x1000), &phys, &size, &page_attribs) 
121           == false);
122   Reap_list reap;
123   fpage_map (sigma0, 
124              Test_fpage::mem(0x10000, Config::PAGE_SHIFT, L4_fpage::RWX),
125              server,
126              L4_fpage::all_spaces(),
127              0x1000, &reap);
128
129   assert (server->mem_space()->v_lookup (Virt_addr(0x1000), &phys, &size, &page_attribs)
130           == true);
131   assert (size == Virt_size(Config::PAGE_SIZE));
132   assert (phys == Virt_addr(0x10000));
133   assert (page_attribs == (Mem_space::Page_writable 
134                            | Mem_space::Page_user_accessible));
135
136   assert (mapdb->lookup (sigma0, Virt_addr(0x10000), Virt_addr(0x10000), &m, &frame));
137   print_node (m, frame);
138   mapdb->free (frame);
139
140   // 
141   // s0 [0/superpage] -> server [0] -> should map many 4K pages and
142   // overmap previous mapping
143   // 
144   assert (server->mem_space()->v_lookup (Virt_addr(0), &phys, &size, &page_attribs)
145           == false);
146
147   fpage_map (sigma0, 
148              L4_fpage::mem(0, Config::SUPERPAGE_SHIFT, L4_fpage::RX),
149              server,
150              L4_fpage::all_spaces(),
151              0, &reap);
152
153   assert (server->mem_space()->v_lookup (Virt_addr(0), &phys, &size, &page_attribs)
154           == true);
155   assert (size == Virt_size(Config::PAGE_SIZE));        // and not SUPERPAGE_SIZE!
156   assert (phys == Virt_addr(0));
157   assert (page_attribs == Mem_space::Page_user_accessible);
158
159   assert (mapdb->lookup (sigma0, Virt_addr(0), Virt_addr(0), &m, &frame));
160   print_node (m, frame);
161   mapdb->free (frame);
162
163   // previous mapping still there?
164
165   assert (server->mem_space()->v_lookup (Virt_addr(0x1000), &phys, &size, &page_attribs)
166           == true);
167   assert (size == Virt_size(Config::PAGE_SIZE));
168   // Previously, overmapping did not work and was ignored, so the
169   // lookup yielded the previously established mapping:
170   //   assert (phys == 0x10000);
171   //   assert (page_attribs == (Mem_space::Page_writable | Mem_space::Page_user_accessible));
172   // Now, the previous mapping should have been overwritten:
173   assert (phys == Virt_addr(0x1000));
174   assert (page_attribs == Mem_space::Page_user_accessible);
175
176   // mapdb entry -- tree should now contain another mapping 
177   // s0 [0x10000] -> server [0x10000]
178   assert (mapdb->lookup (sigma0, Virt_addr(0x10000), Virt_addr(0x10000), &m, &frame));
179   print_node (m, frame, 0x10000, 0x11000);
180   mapdb->free (frame);
181
182   // 
183   // Partially unmap superpage s0 [0/superpage]
184   // 
185   assert (server->mem_space()->v_lookup (Virt_addr(0x101000), &phys, &size, &page_attribs)
186           == true);
187   assert (size == Virt_size(Config::PAGE_SIZE));
188   assert (phys == Virt_addr(0x101000));
189   assert (page_attribs == Mem_space::Page_user_accessible);
190
191   fpage_unmap (sigma0, 
192                Test_fpage::mem(0x100000, Config::SUPERPAGE_SHIFT - 2, L4_fpage::RWX),
193                L4_map_mask(0) /*full unmap, not me too)*/, reap.list());
194   
195   assert (mapdb->lookup (sigma0, Virt_addr(0x0), Virt_addr(0x0), &m, &frame));
196   print_node (m, frame);
197   mapdb->free (frame);
198   
199   assert (! server->mem_space()->v_lookup (Virt_addr(0x101000), &phys, &size, 
200                                            &page_attribs)
201           == true);
202
203   // 
204   // s0 [4M/superpage] -> server [8M]
205   // 
206   assert (server->mem_space()->v_lookup (Virt_addr(0x800000), &phys, &size, &page_attribs)
207           == false);
208
209   fpage_map (sigma0,
210              Test_fpage::mem(0x400000, Config::SUPERPAGE_SHIFT, L4_fpage::RWX),
211              server,
212              L4_fpage::mem(0x800000, Config::SUPERPAGE_SHIFT),
213              0, &reap);
214
215   assert (server->mem_space()->v_lookup (Virt_addr(0x800000), &phys, &size, &page_attribs)
216           == true);
217   assert (size == Virt_size(Config::SUPERPAGE_SIZE));
218   assert (phys == Virt_addr(0x400000));
219   assert (page_attribs == (Mem_space::Page_writable 
220                            | Mem_space::Page_user_accessible));
221
222   assert (mapdb->lookup (sigma0, Virt_addr(0x400000), Virt_addr(0x400000), &m, &frame));
223   print_node (m, frame);
224   mapdb->free (frame);
225
226   // 
227   // server [8M+4K] -> client [8K]
228   // 
229   assert (client->mem_space()->v_lookup (Virt_addr(0x8000), &phys, &size, &page_attribs)
230           == false);
231
232   fpage_map (server, 
233              Test_fpage::mem(0x801000, Config::PAGE_SHIFT, L4_fpage::RWX),
234              client,
235              L4_fpage::mem(0, L4_fpage::Whole_space),
236              0x8000, &reap);
237
238   assert (client->mem_space()->v_lookup (Virt_addr(0x8000), &phys, &size, &page_attribs)
239           == true);
240   assert (size == Virt_size(Config::PAGE_SIZE));
241   assert (phys == Virt_addr(0x401000));
242   assert (page_attribs == (Mem_space::Page_writable 
243                            | Mem_space::Page_user_accessible));
244
245   // Previously, the 4K submapping is attached to the Sigma0 parent.
246   // Not any more.
247
248   assert (mapdb->lookup (sigma0, Virt_addr(0x400000), Virt_addr(0x400000), &m, &frame));
249   print_node (m, frame);
250   mapdb->free (frame);
251
252   //
253   // Overmap a read-only page.  The writable attribute should not be
254   // flushed.
255   //
256   fpage_map (server,
257              Test_fpage::mem(0x801000, Config::PAGE_SHIFT, L4_fpage::RX),
258              client,
259              L4_fpage::mem(0, L4_fpage::Whole_space),
260              0x8000, &reap);
261
262   assert (client->mem_space()->v_lookup (Virt_addr(0x8000), &phys, &size, &page_attribs)
263           == true);
264   assert (size == Virt_size(Config::PAGE_SIZE));
265   assert (phys == Virt_addr(0x401000));
266   assert (page_attribs == (Mem_space::Page_writable 
267                            | Mem_space::Page_user_accessible));  
268
269 #if 0 // no selective unmap anymore
270   // 
271   // Try selective unmap
272   //
273   fpage_map (server,
274              Test_fpage::mem(0x801000, Config::PAGE_SHIFT, L4_fpage::RWX),
275              client2,
276              L4_fpage::all_spaces(),
277              0x1000, &reap);
278
279   assert (client2->mem_space()->v_lookup (0x1000, &phys, &size, &page_attribs)
280           == true);
281   assert (size == Config::PAGE_SIZE);
282   assert (phys == 0x401000);
283   assert (page_attribs == (Mem_space::Page_writable 
284                            | Mem_space::Page_user_accessible));  
285
286   assert (mapdb->lookup (sigma0, 0x400000, 0x400000, &m, &frame));
287   print_node (m, frame);
288   mapdb->free (frame);
289
290   fpage_unmap (server,
291                Test_fpage (false, true, Config::PAGE_SHIFT, 0x801000),
292                mask(false, client2->id(), true, false, false));
293
294   // Page should have vanished in client2's space, but should still be
295   // present in client's space.
296   assert (client2->mem_space()->v_lookup (0x1000, &phys, &size, &page_attribs)
297           == false);
298   assert (client->mem_space()->v_lookup (0x8000, &phys, &size, &page_attribs)
299           == true);
300   assert (size == Config::PAGE_SIZE);
301   assert (phys == 0x401000);
302   assert (page_attribs == (Mem_space::Page_writable 
303                            | Mem_space::Page_user_accessible));  
304
305   assert (mapdb->lookup (sigma0->id(), 0x400000, 0x400000, &m, &frame));
306   print_node (m, frame);
307   mapdb->free (frame);
308 #endif
309   cerr << "... ";
310
311
312   // 
313   // Try some Accessed / Dirty flag unmaps
314   // 
315   
316   // touch page in client
317   assert (client->mem_space()->v_insert (Virt_addr(0x401000), Virt_addr(0x8000), Virt_size(Config::PAGE_SIZE), 
318                             Mem_space::Page_dirty | Mem_space::Page_referenced)
319           == Mem_space::Insert_warn_attrib_upgrade);
320
321   assert (client->mem_space()->v_lookup (Virt_addr(0x8000), &phys, &size, &page_attribs)
322           == true);
323   assert (size == Virt_size(Config::PAGE_SIZE));
324   assert (phys == Virt_addr(0x401000));
325   assert (page_attribs == (Mem_space::Page_writable
326                            | Mem_space::Page_user_accessible
327                            | Mem_space::Page_dirty | Mem_space::Page_referenced));
328   // reset dirty from server
329   assert (fpage_unmap (server,
330                        Test_fpage::mem(0x801000, Config::PAGE_SHIFT),
331                        L4_map_mask(0), reap.list()
332                        /*no_unmap + reset_refs*/)
333           == Mem_space::Page_referenced | Mem_space::Page_dirty);
334
335   assert (client->mem_space()->v_lookup (Virt_addr(0x8000), &phys, &size, &page_attribs)
336           == true);
337   assert (size == Virt_size(Config::PAGE_SIZE));
338   assert (phys == Virt_addr(0x401000));
339   assert (page_attribs == (Mem_space::Page_writable 
340                            | Mem_space::Page_user_accessible)); // Page_dirty | Page_referecned is gone...
341
342   assert (server->mem_space()->v_lookup (Virt_addr(0x801000), &phys, &size, &page_attribs)
343           == true);
344   assert (size == Virt_size(Config::SUPERPAGE_SIZE));
345   assert (phys == Virt_addr(0x400000));
346   assert (page_attribs == (Mem_space::Page_writable 
347                            | Mem_space::Page_user_accessible
348                            | Mem_space::Page_dirty | Mem_space::Page_referenced)); // ...and went here
349
350   // flush dirty and accessed from server
351   assert (fpage_unmap (server, 
352                        Test_fpage::mem(0x800000, Config::SUPERPAGE_SHIFT),
353                        L4_map_mask(0x80000000), reap.list())
354           == Mem_space::Page_dirty | Mem_space::Page_referenced);
355
356   assert (client->mem_space()->v_lookup (Virt_addr(0x8000), &phys, &size, &page_attribs)
357           == true);
358   assert (size == Virt_size(Config::PAGE_SIZE));
359   assert (phys == Virt_addr(0x401000));
360   assert (page_attribs == (Mem_space::Page_writable 
361                            | Mem_space::Page_user_accessible)); // dirty/ref gone
362
363   assert (server->mem_space()->v_lookup (Virt_addr(0x800000), &phys, &size, &page_attribs)
364           == true);
365   assert (size == Virt_size(Config::SUPERPAGE_SIZE));
366   assert (phys == Virt_addr(0x400000));
367   assert (page_attribs == (Mem_space::Page_writable 
368                            | Mem_space::Page_user_accessible)); // dirty/ref gone
369
370   assert (sigma0->mem_space()->v_lookup (Virt_addr(0x400000), &phys, &size, &page_attribs)
371           == true);
372   assert (size == Virt_size(Config::SUPERPAGE_SIZE));
373   assert (phys == Virt_addr(0x400000));
374   // Be a bit more lax in checking Sigma0's address space:  It does
375   // not contain Page_writable / Page_user_accessible flags unless
376   // they are faulted in.
377   assert (page_attribs & (Mem_space::Page_dirty | Mem_space::Page_referenced));
378
379
380   // 
381   // Delete tasks
382   // 
383 #if 0
384   // do not do this because the mapping database would crash if 
385   // they has mappings without spaces
386   delete server;
387   delete client;
388   delete client2;
389   delete sigma0;
390 #endif
391
392   cerr << "OK" << endl;
393
394   return 0;
395 }
396
397 static void print_node(Mapping* node, const Mapdb::Frame& frame,
398                        Address va_begin = 0, Address va_end = ~0UL)
399 {
400   assert (node);
401
402   size_t size = Mapdb::shift(frame, node);
403
404   for (Mapdb::Iterator i (frame, node, Virt_addr(va_begin), Virt_addr(va_end)); node;)
405     {
406       for (int d = node->depth(); d != 0; d--)
407         cout << ' ';
408
409       cout << setbase(16)
410            << "space=0x"  << (unsigned long) (node->space())
411            << " vaddr=0x" << node->page() << size
412            << " size=0x" << size;
413
414       if (Mapping* p = node->parent())
415         {
416           cout << " parent=0x" << (unsigned long)p->space()
417                << " p.vaddr=0x" << p->page().value() << size;
418         }
419
420       cout << endl;
421
422       node = i;
423       if (node)
424         {
425           size = i.shift();
426           ++i;
427         }
428     }
429   cout << endl;
430 }
431