3 #include "assert_opt.h"
4 #include "obj_space_types.h"
7 template< typename SPACE >
11 typedef Obj::Attr Attr;
12 typedef Obj::Capability Capability;
13 typedef Obj::Entry Entry;
14 typedef Kobject_iface *Phys_addr;
16 typedef Obj::Cap_addr V_pfn;
17 typedef Cap_diff V_pfc;
18 typedef Order Page_order;
20 bool v_lookup(V_pfn const &virt, Phys_addr *phys,
21 Page_order *size, Attr *attribs);
23 L4_fpage::Rights v_delete(V_pfn virt, Order size,
24 L4_fpage::Rights page_attribs);
25 Obj::Insert_result v_insert(Phys_addr phys, V_pfn const &virt, Order size,
28 Capability lookup(Cap_index virt);
33 Slots_per_dir = Config::PAGE_SIZE / sizeof(void*)
36 struct Cap_table { Entry e[Obj::Caps_per_page]; };
37 struct Cap_dir { Cap_table *d[Slots_per_dir]; };
40 Ram_quota *ram_quota() const
43 return SPACE::ram_quota(this);
48 //----------------------------------------------------------------------------
57 #include "kmem_alloc.h"
59 #include "mem_layout.h"
60 #include "ram_quota.h"
61 #include "static_assert.h"
63 PUBLIC template< typename SPACE >
64 inline NEEDS["static_assert.h"]
65 Obj_space_phys<SPACE>::Obj_space_phys()
67 static_assert(sizeof(Cap_dir) == Config::PAGE_SIZE, "cap_dir size mismatch");
68 _dir = (Cap_dir*)Kmem_alloc::allocator()->q_unaligned_alloc(ram_quota(), Config::PAGE_SIZE);
70 Mem::memset_mwords(_dir, 0, Config::PAGE_SIZE / sizeof(Mword));
73 PRIVATE template< typename SPACE >
74 typename Obj_space_phys<SPACE>::Entry *
75 Obj_space_phys<SPACE>::get_cap(Cap_index index)
77 if (EXPECT_FALSE(!_dir))
80 unsigned d_idx = cxx::int_value<Cap_index>(index) >> Obj::Caps_per_page_ld2;
81 if (EXPECT_FALSE(d_idx >= Slots_per_dir))
84 Cap_table *tab = _dir->d[d_idx];
86 if (EXPECT_FALSE(!tab))
89 unsigned offs = cxx::get_lsb(cxx::int_value<Cap_index>(index), Obj::Caps_per_page_ld2);
93 PRIVATE template< typename SPACE >
94 typename Obj_space_phys<SPACE>::Entry *
95 Obj_space_phys<SPACE>::caps_alloc(Cap_index virt)
97 static_assert(sizeof(Cap_table) == Config::PAGE_SIZE, "cap table size mismatch");
98 unsigned d_idx = cxx::int_value<Cap_index>(virt) >> Obj::Caps_per_page_ld2;
99 if (EXPECT_FALSE(d_idx >= Slots_per_dir))
102 void *mem = Kmem_alloc::allocator()->q_unaligned_alloc(ram_quota(), Config::PAGE_SIZE);
107 Obj::add_cap_page_dbg_info(mem, SPACE::get_space(this), cxx::int_value<Cap_index>(virt));
109 Mem::memset_mwords(mem, 0, Config::PAGE_SIZE / sizeof(Mword));
111 Cap_table *tab = _dir->d[d_idx] = (Cap_table*)mem;
112 return &tab->e[ cxx::get_lsb(cxx::int_value<Cap_index>(virt), Obj::Caps_per_page_ld2)];
115 PUBLIC template< typename SPACE >
117 Obj_space_phys<SPACE>::caps_free()
125 Kmem_alloc *a = Kmem_alloc::allocator();
126 for (unsigned i = 0; i < Slots_per_dir; ++i)
131 Obj::remove_cap_page_dbg_info(d->d[i]);
132 a->q_unaligned_free(ram_quota(), Config::PAGE_SIZE, d->d[i]);
135 a->q_unaligned_free(ram_quota(), Config::PAGE_SIZE, d);
139 // Utilities for map<Obj_space_phys> and unmap<Obj_space_phys>
142 IMPLEMENT template< typename SPACE >
143 inline NEEDS[Obj_space_phys::get_cap]
145 Obj_space_phys<SPACE>::v_lookup(V_pfn const &virt, Phys_addr *phys,
146 Page_order *size, Attr *attribs)
148 if (size) *size = Page_order(0);
149 Entry *cap = get_cap(virt);
151 if (EXPECT_FALSE(!cap))
153 if (size) *size = Page_order(Obj::Caps_per_page_ld2);
159 Obj::set_entry(virt, cap);
160 if (phys) *phys = c.obj();
161 if (c.valid() && attribs) *attribs = cap->rights();
165 IMPLEMENT template< typename SPACE >
166 inline NEEDS [Obj_space_phys::get_cap]
167 typename Obj_space_phys<SPACE>::Capability FIASCO_FLATTEN
168 Obj_space_phys<SPACE>::lookup(Cap_index virt)
170 Capability *c = get_cap(virt);
172 if (EXPECT_FALSE(!c))
173 return Capability(0); // void
178 PUBLIC template< typename SPACE >
181 Obj_space_phys<SPACE>::lookup_local(Cap_index virt, L4_fpage::Rights *rights)
183 Entry *c = get_cap(virt);
185 if (EXPECT_FALSE(!c))
191 *rights = L4_fpage::Rights(cap.rights());
197 IMPLEMENT template< typename SPACE >
198 inline NEEDS[<cassert>, Obj_space_phys::get_cap]
199 L4_fpage::Rights FIASCO_FLATTEN
200 Obj_space_phys<SPACE>::v_delete(V_pfn virt, Page_order size,
201 L4_fpage::Rights page_attribs = L4_fpage::Rights::FULL())
204 assert (size == Page_order(0));
205 Capability *c = get_cap(virt);
209 if (page_attribs & L4_fpage::Rights::R())
212 c->del_rights(page_attribs);
215 return L4_fpage::Rights(0);
218 IMPLEMENT template< typename SPACE >
219 inline NEEDS[Obj_space_phys::caps_alloc]
220 typename Obj::Insert_result FIASCO_FLATTEN
221 Obj_space_phys<SPACE>::v_insert(Phys_addr phys, V_pfn const &virt, Page_order size,
225 assert (size == Page_order(0));
227 Entry *c = get_cap(virt);
229 if (!c && !(c = caps_alloc(virt)))
230 return Obj::Insert_err_nomem;
234 if (c->obj() == phys)
236 if (EXPECT_FALSE(c->rights() == page_attribs))
237 return Obj::Insert_warn_exists;
239 c->add_rights(page_attribs);
240 return Obj::Insert_warn_attrib_upgrade;
243 return Obj::Insert_err_exists;
246 Obj::set_entry(virt, c);
247 c->set(phys, page_attribs);
248 return Obj::Insert_ok;
252 PUBLIC template< typename SPACE >
254 typename Obj_space_phys<SPACE>::V_pfn
255 Obj_space_phys<SPACE>::obj_map_max_address() const
257 return V_pfn(Slots_per_dir * Obj::Caps_per_page);
260 // ------------------------------------------------------------------------------
261 IMPLEMENTATION [debug]:
263 PUBLIC template< typename SPACE >
264 typename Obj_space_phys<SPACE>::Entry *
265 Obj_space_phys<SPACE>::jdb_lookup_cap(Cap_index index)
266 { return get_cap(index); }