3 #include "assert_opt.h"
5 EXTENSION class Generic_obj_space
10 Slots_per_dir = Config::PAGE_SIZE / sizeof(void*)
13 struct Cap_table { Entry e[Caps_per_page]; };
14 struct Cap_dir { Cap_table *d[Slots_per_dir]; };
17 Ram_quota *ram_quota() const
20 return static_cast<SPACE const *>(this)->ram_quota();
25 //----------------------------------------------------------------------------
35 #include "kmem_alloc.h"
37 #include "mem_layout.h"
38 #include "ram_quota.h"
39 #include "static_assert.h"
42 PUBLIC template< typename SPACE >
43 inline NEEDS["static_assert.h"]
44 Generic_obj_space<SPACE>::Generic_obj_space()
46 static_assert(sizeof(Cap_dir) == Config::PAGE_SIZE, "cap_dir size mismatch");
47 _dir = (Cap_dir*)Kmem_alloc::allocator()->q_unaligned_alloc(ram_quota(), Config::PAGE_SIZE);
49 Mem::memset_mwords(_dir, 0, Config::PAGE_SIZE / sizeof(Mword));
52 PRIVATE template< typename SPACE >
53 typename Generic_obj_space<SPACE>::Entry *
54 Generic_obj_space<SPACE>::get_cap(Address index)
56 if (EXPECT_FALSE(!_dir))
59 unsigned d_idx = index / Caps_per_page;
60 if (EXPECT_FALSE(d_idx >= Slots_per_dir))
63 Cap_table *tab = _dir->d[d_idx];
65 if (EXPECT_FALSE(!tab))
68 unsigned offs = index % Caps_per_page;
72 PRIVATE template< typename SPACE >
73 typename Generic_obj_space<SPACE>::Entry *
74 Generic_obj_space<SPACE>::caps_alloc(Address virt)
76 static_assert(sizeof(Cap_table) == Config::PAGE_SIZE, "cap table size mismatch");
77 unsigned d_idx = virt / Caps_per_page;
78 if (EXPECT_FALSE(d_idx >= Slots_per_dir))
81 void *mem = Kmem_alloc::allocator()->q_unaligned_alloc(ram_quota(), Config::PAGE_SIZE);
86 add_dbg_info(mem, this, virt);
88 Mem::memset_mwords(mem, 0, Config::PAGE_SIZE / sizeof(Mword));
92 Cap_table *tab = _dir->d[d_idx] = (Cap_table*)mem;
94 return &tab->e[virt % Caps_per_page];
97 PRIVATE template< typename SPACE >
99 Generic_obj_space<SPACE>::caps_free()
107 Kmem_alloc *a = Kmem_alloc::allocator();
108 for (unsigned i = 0; i < Slots_per_dir; ++i)
113 remove_dbg_info(d->d[i]);
114 a->q_unaligned_free(ram_quota(), Config::PAGE_SIZE, d->d[i]);
117 a->q_unaligned_free(ram_quota(), Config::PAGE_SIZE, d);
121 // Utilities for map<Generic_obj_space> and unmap<Generic_obj_space>
124 PUBLIC template< typename SPACE >
125 inline NEEDS[Generic_obj_space::get_cap]
127 Generic_obj_space<SPACE>::v_lookup(Addr const &virt, Phys_addr *phys = 0,
128 Size *size = 0, unsigned *attribs = 0)
130 if (size) *size = Size::create(1);
131 Entry *cap = get_cap(virt.value());
133 if (EXPECT_FALSE(!cap))
135 if (size) *size = Size::create(Caps_per_page);
141 Obj::set_entry(virt, cap);
142 if (phys) *phys = c.obj();
143 if (c.valid() && attribs) *attribs = cap->rights();
147 PUBLIC template< typename SPACE >
148 inline NEEDS [Generic_obj_space::get_cap]
149 typename Generic_obj_space<SPACE>::Capability
150 Generic_obj_space<SPACE>::lookup(Address virt)
152 Capability *c = get_cap(virt);
154 if (EXPECT_FALSE(!c))
155 return Capability(0); // void
160 PUBLIC template< typename SPACE >
163 Generic_obj_space<SPACE>::lookup_local(Address virt, unsigned char *rights = 0)
165 Entry *c = get_cap(virt);
167 if (EXPECT_FALSE(!c))
173 *rights = cap.rights();
179 PUBLIC template< typename SPACE >
180 inline NEEDS[<cassert>, Generic_obj_space::get_cap]
182 Generic_obj_space<SPACE>::v_delete(Page_number virt, Size size,
183 unsigned long page_attribs = L4_fpage::RWX)
186 assert (size.value() == 1);
187 Capability *c = get_cap(virt.value());
191 if (page_attribs & L4_fpage::R)
194 c->del_rights(page_attribs & L4_fpage::WX);
200 PUBLIC template< typename SPACE >
201 inline NEEDS[Generic_obj_space::caps_alloc, "kdb_ke.h"]
202 typename Generic_obj_space<SPACE>::Status
203 Generic_obj_space<SPACE>::v_insert(Phys_addr phys, Addr const &virt, Size size,
204 unsigned char page_attribs)
207 assert (size.value() == 1);
209 Entry *c = get_cap(virt.value());
211 if (!c && !(c = caps_alloc(virt.value())))
212 return Insert_err_nomem;
214 assert (size.value() == 1);
218 if (c->obj() == phys)
220 if (EXPECT_FALSE(c->rights() == page_attribs))
221 return Insert_warn_exists;
223 c->add_rights(page_attribs);
224 return Insert_warn_attrib_upgrade;
227 return Insert_err_exists;
230 Obj::set_entry(virt, c);
231 c->set(phys, page_attribs);
236 PUBLIC template< typename SPACE >
238 typename Generic_obj_space<SPACE>::Addr
239 Generic_obj_space<SPACE>::map_max_address()
241 return Addr(Slots_per_dir * Caps_per_page);