15 #include "boot_info.h"
20 #include "kmem_alloc.h"
21 #include "per_cpu_data_alloc.h"
23 #include "static_init.h"
25 #include "vmem_alloc.h"
26 #include "mem_space_sigma0.h"
30 typedef L4_fpage Test_fpage;
32 class Test_space : public Space
35 Test_space (Ram_quota *rq)
36 : Space (Space::Default_factory(), rq, L4_fpage::mem(0x1200000, Config::PAGE_SHIFT))
39 void* operator new (size_t s)
40 { return malloc (s); }
42 void operator delete (void *p)
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);
57 Kmem_alloc::base_init();
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);
70 Cpu::init_global_features();
72 Kmem::init_mmu(*Cpu::boot_cpu());
79 struct Sigma0_space_factory
81 static void create(Mem_space *v, Ram_quota *q)
82 { new (v) Mem_space_sigma0(q); }
84 template< typename S >
85 static void create(S *v)
95 Space *sigma0 = new Space (Sigma0_space_factory(), &rq, L4_fpage::mem(0x1200000, Config::PAGE_SHIFT));
97 init_mapdb_mem(sigma0);
99 Test_space *server = new Test_space (&rq);
101 Test_space *client = new Test_space (&rq);
103 Test_space *client2 = new Test_space (&rq);
107 // Manipulate mappings.
109 Mapdb* mapdb = mapdb_instance();
111 Mem_space::Phys_addr phys;
113 unsigned page_attribs;
118 // s0 [0x10000] -> server [0x1000]
120 assert (server->mem_space()->v_lookup (Virt_addr(0x1000), &phys, &size, &page_attribs)
124 Test_fpage::mem(0x10000, Config::PAGE_SHIFT, L4_fpage::RWX),
126 L4_fpage::all_spaces(),
129 assert (server->mem_space()->v_lookup (Virt_addr(0x1000), &phys, &size, &page_attribs)
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));
136 assert (mapdb->lookup (sigma0, Virt_addr(0x10000), Virt_addr(0x10000), &m, &frame));
137 print_node (m, frame);
141 // s0 [0/superpage] -> server [0] -> should map many 4K pages and
142 // overmap previous mapping
144 assert (server->mem_space()->v_lookup (Virt_addr(0), &phys, &size, &page_attribs)
148 L4_fpage::mem(0, Config::SUPERPAGE_SHIFT, L4_fpage::RX),
150 L4_fpage::all_spaces(),
153 assert (server->mem_space()->v_lookup (Virt_addr(0), &phys, &size, &page_attribs)
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);
159 assert (mapdb->lookup (sigma0, Virt_addr(0), Virt_addr(0), &m, &frame));
160 print_node (m, frame);
163 // previous mapping still there?
165 assert (server->mem_space()->v_lookup (Virt_addr(0x1000), &phys, &size, &page_attribs)
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);
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);
183 // Partially unmap superpage s0 [0/superpage]
185 assert (server->mem_space()->v_lookup (Virt_addr(0x101000), &phys, &size, &page_attribs)
187 assert (size == Virt_size(Config::PAGE_SIZE));
188 assert (phys == Virt_addr(0x101000));
189 assert (page_attribs == Mem_space::Page_user_accessible);
192 Test_fpage::mem(0x100000, Config::SUPERPAGE_SHIFT - 2, L4_fpage::RWX),
193 L4_map_mask(0) /*full unmap, not me too)*/, reap.list());
195 assert (mapdb->lookup (sigma0, Virt_addr(0x0), Virt_addr(0x0), &m, &frame));
196 print_node (m, frame);
199 assert (! server->mem_space()->v_lookup (Virt_addr(0x101000), &phys, &size,
204 // s0 [4M/superpage] -> server [8M]
206 assert (server->mem_space()->v_lookup (Virt_addr(0x800000), &phys, &size, &page_attribs)
210 Test_fpage::mem(0x400000, Config::SUPERPAGE_SHIFT, L4_fpage::RWX),
212 L4_fpage::mem(0x800000, Config::SUPERPAGE_SHIFT),
215 assert (server->mem_space()->v_lookup (Virt_addr(0x800000), &phys, &size, &page_attribs)
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));
222 assert (mapdb->lookup (sigma0, Virt_addr(0x400000), Virt_addr(0x400000), &m, &frame));
223 print_node (m, frame);
227 // server [8M+4K] -> client [8K]
229 assert (client->mem_space()->v_lookup (Virt_addr(0x8000), &phys, &size, &page_attribs)
233 Test_fpage::mem(0x801000, Config::PAGE_SHIFT, L4_fpage::RWX),
235 L4_fpage::mem(0, L4_fpage::Whole_space),
238 assert (client->mem_space()->v_lookup (Virt_addr(0x8000), &phys, &size, &page_attribs)
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));
245 // Previously, the 4K submapping is attached to the Sigma0 parent.
248 assert (mapdb->lookup (sigma0, Virt_addr(0x400000), Virt_addr(0x400000), &m, &frame));
249 print_node (m, frame);
253 // Overmap a read-only page. The writable attribute should not be
257 Test_fpage::mem(0x801000, Config::PAGE_SHIFT, L4_fpage::RX),
259 L4_fpage::mem(0, L4_fpage::Whole_space),
262 assert (client->mem_space()->v_lookup (Virt_addr(0x8000), &phys, &size, &page_attribs)
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));
269 #if 0 // no selective unmap anymore
271 // Try selective unmap
274 Test_fpage::mem(0x801000, Config::PAGE_SHIFT, L4_fpage::RWX),
276 L4_fpage::all_spaces(),
279 assert (client2->mem_space()->v_lookup (0x1000, &phys, &size, &page_attribs)
281 assert (size == Config::PAGE_SIZE);
282 assert (phys == 0x401000);
283 assert (page_attribs == (Mem_space::Page_writable
284 | Mem_space::Page_user_accessible));
286 assert (mapdb->lookup (sigma0, 0x400000, 0x400000, &m, &frame));
287 print_node (m, frame);
291 Test_fpage (false, true, Config::PAGE_SHIFT, 0x801000),
292 mask(false, client2->id(), true, false, false));
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)
298 assert (client->mem_space()->v_lookup (0x8000, &phys, &size, &page_attribs)
300 assert (size == Config::PAGE_SIZE);
301 assert (phys == 0x401000);
302 assert (page_attribs == (Mem_space::Page_writable
303 | Mem_space::Page_user_accessible));
305 assert (mapdb->lookup (sigma0->id(), 0x400000, 0x400000, &m, &frame));
306 print_node (m, frame);
313 // Try some Accessed / Dirty flag unmaps
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);
321 assert (client->mem_space()->v_lookup (Virt_addr(0x8000), &phys, &size, &page_attribs)
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);
335 assert (client->mem_space()->v_lookup (Virt_addr(0x8000), &phys, &size, &page_attribs)
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...
342 assert (server->mem_space()->v_lookup (Virt_addr(0x801000), &phys, &size, &page_attribs)
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
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);
356 assert (client->mem_space()->v_lookup (Virt_addr(0x8000), &phys, &size, &page_attribs)
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
363 assert (server->mem_space()->v_lookup (Virt_addr(0x800000), &phys, &size, &page_attribs)
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
370 assert (sigma0->mem_space()->v_lookup (Virt_addr(0x400000), &phys, &size, &page_attribs)
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));
384 // do not do this because the mapping database would crash if
385 // they has mappings without spaces
392 cerr << "OK" << endl;
397 static void print_node(Mapping* node, const Mapdb::Frame& frame,
398 Address va_begin = 0, Address va_end = ~0UL)
402 size_t size = Mapdb::shift(frame, node);
404 for (Mapdb::Iterator i (frame, node, Virt_addr(va_begin), Virt_addr(va_end)); node;)
406 for (int d = node->depth(); d != 0; d--)
410 << "space=0x" << (unsigned long) (node->space())
411 << " vaddr=0x" << node->page() << size
412 << " size=0x" << size;
414 if (Mapping* p = node->parent())
416 cout << " parent=0x" << (unsigned long)p->space()
417 << " p.vaddr=0x" << p->page().value() << size;