#include "static_init.h"
#include "usermode.h"
#include "vmem_alloc.h"
-#include "mem_space_sigma0.h"
IMPLEMENTATION:
class Test_space : public Space
{
public:
- Test_space (Ram_quota *rq)
- : Space (Space::Default_factory(), rq, L4_fpage::mem(0x1200000, Config::PAGE_SHIFT))
- {}
+ Test_space(Ram_quota *rq, char const *name)
+ : Space(rq, Caps::all()), name(name)
+ {
+ initialize();
+ }
void* operator new (size_t s)
{ return malloc (s); }
void operator delete (void *p)
{ ::free (p); }
+
+ char const *const name;
+};
+
+class Sigma0_space : public Test_space
+{
+public:
+ explicit Sigma0_space(Ram_quota *q) : Test_space(q, "s0") {}
+ bool is_sigma0() const { return true; }
};
+
+PUBLIC
+bool
+Sigma0_space::v_fabricate(Mem_space::Vaddr address,
+ Mem_space::Phys_addr *phys, Mem_space::Page_order *size,
+ Mem_space::Attr *attribs = 0)
+{
+ // special-cased because we don't do ptab lookup for sigma0
+ *size = static_cast<Mem_space const &>(*this).largest_page_size();
+ *phys = cxx::mask_lsb(Virt_addr(address), *size);
+
+ if (attribs)
+ *attribs = Mem_space::Attr(L4_fpage::Rights::URWX());
+
+ return true;
+}
+
+PUBLIC inline
+Page_number
+Sigma0_space::mem_space_map_max_address() const
+{ return Page_number(1UL << (MWORD_BITS - Mem_space::Page_shift)); }
+
class Timeout;
DEFINE_PER_CPU Per_cpu<Timeout *> timeslice_timeout;
static void init()
{
- Usermode::init(0);
+ Usermode::init(Cpu_number::boot_cpu());
Boot_info::init();
- Kip_init::setup_ux();
- Kmem_alloc::base_init();
Kip_init::init();
+ Kmem_alloc::base_init();
Kmem_alloc::init();
// Initialize cpu-local data management and run constructors for CPU 0
Per_cpu_data::init_ctors();
- Per_cpu_data_alloc::alloc(0);
- Per_cpu_data::run_ctors(0);
+ Per_cpu_data_alloc::alloc(Cpu_number::boot_cpu());
+ Per_cpu_data::run_ctors(Cpu_number::boot_cpu());
+ Mem_space::init_page_sizes();
}
static void init2()
Cpu::init_global_features();
Config::init();
Kmem::init_mmu(*Cpu::boot_cpu());
- Vmem_alloc::init();
Pic::init();
}
-static Ram_quota rq;
-
-struct Sigma0_space_factory
+class Fake_factory : public Ram_quota
{
- static void create(Mem_space *v, Ram_quota *q)
- { new (v) Mem_space_sigma0(q); }
+};
- template< typename S >
- static void create(S *v)
- { new (v) S(); }
+extern Static_object<Mapdb> mapdb_mem;
+static Fake_factory rq;
-};
+static
+Mem_space *ms(Space *s) { return s; }
+
+static
+Mem_space::Vaddr
+to_vaddr(Address a)
+{ return Mem_space::Vaddr(Virt_addr(a)); }
+
+static
+Mapdb::Pfn to_pfn(Address a)
+{ return Mem_space::to_pfn(Virt_addr(a)); }
int main()
{
- //
- // Create tasks
- //
- Space *sigma0 = new Space (Sigma0_space_factory(), &rq, L4_fpage::mem(0x1200000, Config::PAGE_SHIFT));
+ cout << "[UTEST] *** Create tasks ***" << endl;
+
+ Space *sigma0 = new Sigma0_space(&rq);
init_mapdb_mem(sigma0);
- Test_space *server = new Test_space (&rq);
+ Test_space *server = new Test_space (&rq, "server");
assert (server);
- Test_space *client = new Test_space (&rq);
+ Test_space *client = new Test_space (&rq, "client");
assert (client);
- Test_space *client2 = new Test_space (&rq);
+ Test_space *client2 = new Test_space (&rq, "client2");
assert (client2);
- //
- // Manipulate mappings.
- //
- Mapdb* mapdb = mapdb_instance();
+ cout << "[UTEST] *** Manipulate mappings ***" << endl;
+
+ Mapdb* mapdb = mapdb_mem.get();
- Mem_space::Phys_addr phys;
- Virt_size size;
- unsigned page_attribs;
+ typedef Mem_space::Page_order Page_order;
+ typedef Mem_space::Phys_addr Phys_addr;
+ typedef Mem_space::Attr Attr;;
+
+ Phys_addr phys;
+ Page_order order;
+ Attr page_attribs;
Mapping *m;
Mapdb::Frame frame;
-
- //
- // s0 [0x10000] -> server [0x1000]
- //
- assert (server->mem_space()->v_lookup (Virt_addr(0x1000), &phys, &size, &page_attribs)
+
+ cout << "[UTEST] s0 [0x10000] -> server [0x1000]" << endl;
+
+ assert (ms(server)->v_lookup(to_vaddr(0x1000), &phys, &order, &page_attribs)
== false);
Reap_list reap;
- fpage_map (sigma0,
- Test_fpage::mem(0x10000, Config::PAGE_SHIFT, L4_fpage::RWX),
- server,
- L4_fpage::all_spaces(),
- 0x1000, &reap);
+ fpage_map(sigma0,
+ Test_fpage::mem(0x10000, Config::PAGE_SHIFT, L4_fpage::Rights::URWX()),
+ server,
+ L4_fpage::all_spaces(),
+ L4_msg_item(0x1000), &reap);
- assert (server->mem_space()->v_lookup (Virt_addr(0x1000), &phys, &size, &page_attribs)
+ assert (ms(server)->v_lookup(to_vaddr(0x1000), &phys, &order, &page_attribs)
== true);
- assert (size == Virt_size(Config::PAGE_SIZE));
- assert (phys == Virt_addr(0x10000));
- assert (page_attribs == (Mem_space::Page_writable
- | Mem_space::Page_user_accessible));
+ assert (order == Page_order(Config::PAGE_SHIFT));
+ assert (phys == Phys_addr(0x10000));
+ assert (page_attribs.rights == L4_fpage::Rights::URWX());
- assert (mapdb->lookup (sigma0, Virt_addr(0x10000), Virt_addr(0x10000), &m, &frame));
+ assert (mapdb->lookup(sigma0, to_pfn(0x10000), to_pfn(0x10000), &m, &frame));
print_node (m, frame);
mapdb->free (frame);
- //
- // s0 [0/superpage] -> server [0] -> should map many 4K pages and
- // overmap previous mapping
- //
- assert (server->mem_space()->v_lookup (Virt_addr(0), &phys, &size, &page_attribs)
+ cout << "[UTEST] s0 [0/superpage] -> server [0] -> should map many 4K pages and "
+ "overmap previous mapping" << endl;
+
+ assert (ms(server)->v_lookup(to_vaddr(0), &phys, &order, &page_attribs)
== false);
- fpage_map (sigma0,
- L4_fpage::mem(0, Config::SUPERPAGE_SHIFT, L4_fpage::RX),
- server,
- L4_fpage::all_spaces(),
- 0, &reap);
+ fpage_map(sigma0,
+ L4_fpage::mem(0, Config::SUPERPAGE_SHIFT, L4_fpage::Rights::URX()),
+ server,
+ L4_fpage::all_spaces(),
+ L4_msg_item(0), &reap);
- assert (server->mem_space()->v_lookup (Virt_addr(0), &phys, &size, &page_attribs)
+ assert (ms(server)->v_lookup(to_vaddr(0), &phys, &order, &page_attribs)
== true);
- assert (size == Virt_size(Config::PAGE_SIZE)); // and not SUPERPAGE_SIZE!
- assert (phys == Virt_addr(0));
- assert (page_attribs == Mem_space::Page_user_accessible);
+ assert (order == Page_order(Config::PAGE_SHIFT)); // and not SUPERPAGE_SIZE!
+ assert (phys == Phys_addr(0));
+ assert (page_attribs.rights == L4_fpage::Rights::URX());
- assert (mapdb->lookup (sigma0, Virt_addr(0), Virt_addr(0), &m, &frame));
+ assert (mapdb->lookup(sigma0, to_pfn(0), to_pfn(0), &m, &frame));
print_node (m, frame);
mapdb->free (frame);
// previous mapping still there?
- assert (server->mem_space()->v_lookup (Virt_addr(0x1000), &phys, &size, &page_attribs)
- == true);
- assert (size == Virt_size(Config::PAGE_SIZE));
+ assert (ms(server)->v_lookup(to_vaddr(0x1000), &phys, &order, &page_attribs));
+ assert (order == Page_order(Config::PAGE_SHIFT));
// Previously, overmapping did not work and was ignored, so the
// lookup yielded the previously established mapping:
// assert (phys == 0x10000);
// assert (page_attribs == (Mem_space::Page_writable | Mem_space::Page_user_accessible));
// Now, the previous mapping should have been overwritten:
- assert (phys == Virt_addr(0x1000));
- assert (page_attribs == Mem_space::Page_user_accessible);
+ assert (phys == Phys_addr(0x1000));
+ assert (page_attribs.rights == L4_fpage::Rights::URX());
// mapdb entry -- tree should now contain another mapping
// s0 [0x10000] -> server [0x10000]
- assert (mapdb->lookup (sigma0, Virt_addr(0x10000), Virt_addr(0x10000), &m, &frame));
+ assert (mapdb->lookup(sigma0, to_pfn(0x10000), to_pfn(0x10000), &m, &frame));
print_node (m, frame, 0x10000, 0x11000);
mapdb->free (frame);
- //
- // Partially unmap superpage s0 [0/superpage]
- //
- assert (server->mem_space()->v_lookup (Virt_addr(0x101000), &phys, &size, &page_attribs)
+ cout << "[UTEST] Partially unmap superpage s0 [0/superpage]" << endl;
+
+ assert (ms(server)->v_lookup(to_vaddr(0x101000), &phys, &order, &page_attribs)
== true);
- assert (size == Virt_size(Config::PAGE_SIZE));
- assert (phys == Virt_addr(0x101000));
- assert (page_attribs == Mem_space::Page_user_accessible);
+ assert (order == Page_order(Config::PAGE_SHIFT));
+ assert (phys == Phys_addr(0x101000));
+ assert (page_attribs.rights == L4_fpage::Rights::URX());
- fpage_unmap (sigma0,
- Test_fpage::mem(0x100000, Config::SUPERPAGE_SHIFT - 2, L4_fpage::RWX),
- L4_map_mask(0) /*full unmap, not me too)*/, reap.list());
+ fpage_unmap(sigma0,
+ Test_fpage::mem(0x100000, Config::SUPERPAGE_SHIFT - 2, L4_fpage::Rights::URWX()),
+ L4_map_mask(0) /*full unmap, not me too)*/, reap.list());
- assert (mapdb->lookup (sigma0, Virt_addr(0x0), Virt_addr(0x0), &m, &frame));
+ assert (mapdb->lookup(sigma0, to_pfn(0x0), to_pfn(0x0), &m, &frame));
print_node (m, frame);
mapdb->free (frame);
-
- assert (! server->mem_space()->v_lookup (Virt_addr(0x101000), &phys, &size,
- &page_attribs)
- == true);
+
+ assert (! ms(server)->v_lookup(to_vaddr(0x101000), &phys, &order, &page_attribs));
//
// s0 [4M/superpage] -> server [8M]
//
- assert (server->mem_space()->v_lookup (Virt_addr(0x800000), &phys, &size, &page_attribs)
+ assert (ms(server)->v_lookup(to_vaddr(0x800000), &phys, &order, &page_attribs)
== false);
- fpage_map (sigma0,
- Test_fpage::mem(0x400000, Config::SUPERPAGE_SHIFT, L4_fpage::RWX),
- server,
- L4_fpage::mem(0x800000, Config::SUPERPAGE_SHIFT),
- 0, &reap);
+ fpage_map(sigma0,
+ Test_fpage::mem(0x400000, Config::SUPERPAGE_SHIFT, L4_fpage::Rights::URWX()),
+ server,
+ L4_fpage::mem(0x800000, Config::SUPERPAGE_SHIFT),
+ L4_msg_item(0), &reap);
- assert (server->mem_space()->v_lookup (Virt_addr(0x800000), &phys, &size, &page_attribs)
+ assert (ms(server)->v_lookup(to_vaddr(0x800000), &phys, &order, &page_attribs)
== true);
- assert (size == Virt_size(Config::SUPERPAGE_SIZE));
+ assert (order == Page_order(Config::SUPERPAGE_SHIFT));
assert (phys == Virt_addr(0x400000));
- assert (page_attribs == (Mem_space::Page_writable
- | Mem_space::Page_user_accessible));
+ assert (page_attribs.rights == L4_fpage::Rights::URWX());
- assert (mapdb->lookup (sigma0, Virt_addr(0x400000), Virt_addr(0x400000), &m, &frame));
+ assert (mapdb->lookup(sigma0, to_pfn(0x400000), to_pfn(0x400000), &m, &frame));
print_node (m, frame);
mapdb->free (frame);
//
// server [8M+4K] -> client [8K]
//
- assert (client->mem_space()->v_lookup (Virt_addr(0x8000), &phys, &size, &page_attribs)
+ assert (ms(client)->v_lookup(to_vaddr(0x8000), &phys, &order, &page_attribs)
== false);
- fpage_map (server,
- Test_fpage::mem(0x801000, Config::PAGE_SHIFT, L4_fpage::RWX),
- client,
- L4_fpage::mem(0, L4_fpage::Whole_space),
- 0x8000, &reap);
+ fpage_map(server,
+ Test_fpage::mem(0x801000, Config::PAGE_SHIFT, L4_fpage::Rights::URWX()),
+ client,
+ L4_fpage::mem(0, L4_fpage::Whole_space),
+ L4_msg_item(0x8000), &reap);
- assert (client->mem_space()->v_lookup (Virt_addr(0x8000), &phys, &size, &page_attribs)
+ assert (ms(client)->v_lookup(to_vaddr(0x8000), &phys, &order, &page_attribs)
== true);
- assert (size == Virt_size(Config::PAGE_SIZE));
+ assert (order == Page_order(Config::PAGE_SHIFT));
assert (phys == Virt_addr(0x401000));
- assert (page_attribs == (Mem_space::Page_writable
- | Mem_space::Page_user_accessible));
+ assert (page_attribs.rights == L4_fpage::Rights::URWX());
// Previously, the 4K submapping is attached to the Sigma0 parent.
// Not any more.
- assert (mapdb->lookup (sigma0, Virt_addr(0x400000), Virt_addr(0x400000), &m, &frame));
+ assert (mapdb->lookup(sigma0, to_pfn(0x400000), to_pfn(0x400000), &m, &frame));
print_node (m, frame);
mapdb->free (frame);
// Overmap a read-only page. The writable attribute should not be
// flushed.
//
- fpage_map (server,
- Test_fpage::mem(0x801000, Config::PAGE_SHIFT, L4_fpage::RX),
- client,
- L4_fpage::mem(0, L4_fpage::Whole_space),
- 0x8000, &reap);
+ fpage_map(server,
+ Test_fpage::mem(0x801000, Config::PAGE_SHIFT, L4_fpage::Rights::URX()),
+ client,
+ L4_fpage::mem(0, L4_fpage::Whole_space),
+ L4_msg_item(0x8000), &reap);
- assert (client->mem_space()->v_lookup (Virt_addr(0x8000), &phys, &size, &page_attribs)
+ assert (ms(client)->v_lookup(to_vaddr(0x8000), &phys, &order, &page_attribs)
== true);
- assert (size == Virt_size(Config::PAGE_SIZE));
+ assert (order == Page_order(Config::PAGE_SHIFT));
assert (phys == Virt_addr(0x401000));
- assert (page_attribs == (Mem_space::Page_writable
- | Mem_space::Page_user_accessible));
+ assert (page_attribs.rights == L4_fpage::Rights::URWX());
#if 0 // no selective unmap anymore
//
print_node (m, frame);
mapdb->free (frame);
#endif
- cerr << "... ";
//
//
// touch page in client
- assert (client->mem_space()->v_insert (Virt_addr(0x401000), Virt_addr(0x8000), Virt_size(Config::PAGE_SIZE),
- Mem_space::Page_dirty | Mem_space::Page_referenced)
- == Mem_space::Insert_warn_attrib_upgrade);
+ ms(client)->v_set_access_flags(to_vaddr(0x8000), L4_fpage::Rights::RW());
- assert (client->mem_space()->v_lookup (Virt_addr(0x8000), &phys, &size, &page_attribs)
+ assert (ms(client)->v_lookup(to_vaddr(0x8000), &phys, &order, &page_attribs)
== true);
- assert (size == Virt_size(Config::PAGE_SIZE));
+ assert (order == Page_order(Config::PAGE_SHIFT));
assert (phys == Virt_addr(0x401000));
- assert (page_attribs == (Mem_space::Page_writable
- | Mem_space::Page_user_accessible
- | Mem_space::Page_dirty | Mem_space::Page_referenced));
+ assert (page_attribs.rights == L4_fpage::Rights::URWX());
+ // the next would reset flags, so don't do it!!
+ // assert (ms(client)->v_delete(to_vaddr(0x8000), order, L4_fpage::Rights(0)) == L4_fpage::Rights::RW());
+
// reset dirty from server
- assert (fpage_unmap (server,
- Test_fpage::mem(0x801000, Config::PAGE_SHIFT),
- L4_map_mask(0), reap.list()
- /*no_unmap + reset_refs*/)
- == Mem_space::Page_referenced | Mem_space::Page_dirty);
+ assert (fpage_unmap(server,
+ Test_fpage::mem(0x801000, Config::PAGE_SHIFT),
+ L4_map_mask(0), reap.list()
+ /*no_unmap + reset_refs*/)
+ == L4_fpage::Rights::RW());
- assert (client->mem_space()->v_lookup (Virt_addr(0x8000), &phys, &size, &page_attribs)
+ assert (ms(client)->v_lookup(to_vaddr(0x8000), &phys, &order, &page_attribs)
== true);
- assert (size == Virt_size(Config::PAGE_SIZE));
+ assert (order == Page_order(Config::PAGE_SHIFT));
assert (phys == Virt_addr(0x401000));
- assert (page_attribs == (Mem_space::Page_writable
- | Mem_space::Page_user_accessible)); // Page_dirty | Page_referecned is gone...
+ assert (ms(client)->v_delete(to_vaddr(0x8000), order, L4_fpage::Rights(0)) == L4_fpage::Rights(0));
- assert (server->mem_space()->v_lookup (Virt_addr(0x801000), &phys, &size, &page_attribs)
+ assert (ms(server)->v_lookup(to_vaddr(0x801000), &phys, &order, &page_attribs)
== true);
- assert (size == Virt_size(Config::SUPERPAGE_SIZE));
+ assert (order == Page_order(Config::SUPERPAGE_SHIFT));
assert (phys == Virt_addr(0x400000));
- assert (page_attribs == (Mem_space::Page_writable
- | Mem_space::Page_user_accessible
- | Mem_space::Page_dirty | Mem_space::Page_referenced)); // ...and went here
// flush dirty and accessed from server
- assert (fpage_unmap (server,
- Test_fpage::mem(0x800000, Config::SUPERPAGE_SHIFT),
- L4_map_mask(0x80000000), reap.list())
- == Mem_space::Page_dirty | Mem_space::Page_referenced);
+ assert (fpage_unmap(server,
+ Test_fpage::mem(0x800000, Config::SUPERPAGE_SHIFT),
+ L4_map_mask(0x80000000), reap.list())
+ == L4_fpage::Rights::RW());
- assert (client->mem_space()->v_lookup (Virt_addr(0x8000), &phys, &size, &page_attribs)
+ assert (ms(client)->v_lookup(to_vaddr(0x8000), &phys, &order, &page_attribs)
== true);
- assert (size == Virt_size(Config::PAGE_SIZE));
+ assert (order == Page_order(Config::PAGE_SHIFT));
assert (phys == Virt_addr(0x401000));
- assert (page_attribs == (Mem_space::Page_writable
- | Mem_space::Page_user_accessible)); // dirty/ref gone
-
- assert (server->mem_space()->v_lookup (Virt_addr(0x800000), &phys, &size, &page_attribs)
- == true);
- assert (size == Virt_size(Config::SUPERPAGE_SIZE));
- assert (phys == Virt_addr(0x400000));
- assert (page_attribs == (Mem_space::Page_writable
- | Mem_space::Page_user_accessible)); // dirty/ref gone
+ assert (ms(client)->v_delete(to_vaddr(0x8000), order, L4_fpage::Rights(0)) == L4_fpage::Rights(0));
- assert (sigma0->mem_space()->v_lookup (Virt_addr(0x400000), &phys, &size, &page_attribs)
+ assert (ms(server)->v_lookup(to_vaddr(0x800000), &phys, &order, &page_attribs)
== true);
- assert (size == Virt_size(Config::SUPERPAGE_SIZE));
+ assert (order == Page_order(Config::SUPERPAGE_SHIFT));
assert (phys == Virt_addr(0x400000));
- // Be a bit more lax in checking Sigma0's address space: It does
- // not contain Page_writable / Page_user_accessible flags unless
- // they are faulted in.
- assert (page_attribs & (Mem_space::Page_dirty | Mem_space::Page_referenced));
-
+ assert (page_attribs.rights == L4_fpage::Rights::URWX());
//
// Delete tasks
return 0;
}
+
+static
+std::ostream &operator << (std::ostream &s, Mapdb::Pfn v)
+{
+ s << cxx::int_value<Mapdb::Pfn>(v);
+ return s;
+}
+
+static
+std::ostream &operator << (std::ostream &s, Mapping::Page v)
+{
+ s << cxx::int_value<Mapping::Page>(v);
+ return s;
+}
+
+static
+std::ostream &operator << (std::ostream &s, Space const &sp)
+{
+ Test_space const *t = static_cast<Test_space const *>(&sp);
+ if (!t)
+ s << "<NULL>";
+ else
+ s << t->name;
+ return s;
+}
+
+
static void print_node(Mapping* node, const Mapdb::Frame& frame,
Address va_begin = 0, Address va_end = ~0UL)
{
assert (node);
- size_t size = Mapdb::shift(frame, node);
+ Mapdb::Order size = Mapdb::shift(frame, node);
- for (Mapdb::Iterator i (frame, node, Virt_addr(va_begin), Virt_addr(va_end)); node;)
+ for (Mapdb::Iterator i (frame, node, to_pfn(va_begin), to_pfn(va_end)); node;)
{
+ cout << "[UTEST] ";
for (int d = node->depth(); d != 0; d--)
cout << ' ';
cout << setbase(16)
- << "space=0x" << (unsigned long) (node->space())
- << " vaddr=0x" << node->page() << size
- << " size=0x" << size;
+ << "space=" << *node->space()
+ << " vaddr=0x" << (node->page() << size)
+ << " size=0x" << (Mapdb::Pfn(1) << size);
if (Mapping* p = node->parent())
{
- cout << " parent=0x" << (unsigned long)p->space()
- << " p.vaddr=0x" << p->page().value() << size;
+ cout << " parent=" << *p->space()
+ << " p.vaddr=0x" << (p->page() << size);
}
cout << endl;
node = i;
if (node)
{
- size = i.shift();
+ size = i.order();
++i;
}
}
- cout << endl;
+ cout << "[UTEST] " << endl;
}