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);
47 // ------------------------------------------------------------------------
48 INTERFACE [obj_space_virt]:
50 #include "cxx/type_traits"
53 * Allows to override the virtually mapped object space Space
54 * by the multi-level table based structure.
56 * This is useful for Vm or Io spaces that never run threads, and
57 * saves the overhead of software page-table walks and phys-to-virt
58 * translations for capability lookup.
60 template<typename BASE>
61 class Obj_space_phys_override :
63 Obj_space_phys< Obj_space_phys_override<BASE> >
65 typedef Obj_space_phys< Obj_space_phys_override<BASE> > Obj_space;
68 using BASE::ram_quota;
69 static Ram_quota *ram_quota(Obj_space const *obj_sp)
70 { return static_cast<Obj_space_phys_override<BASE> const *>(obj_sp)->ram_quota(); }
73 v_lookup(typename Obj_space::V_pfn const &virt,
74 typename Obj_space::Phys_addr *phys,
75 typename Obj_space::Page_order *size,
76 typename Obj_space::Attr *attribs) override
77 { return Obj_space::v_lookup(virt, phys, size, attribs); }
79 L4_fpage::Rights FIASCO_FLATTEN
80 v_delete(typename Obj_space::V_pfn virt, Order size,
81 L4_fpage::Rights page_attribs) override
82 { return Obj_space::v_delete(virt, size, page_attribs); }
84 Obj::Insert_result FIASCO_FLATTEN
85 v_insert(typename Obj_space::Phys_addr phys,
86 typename Obj_space::V_pfn const &virt,
88 typename Obj_space::Attr page_attribs) override
89 { return Obj_space::v_insert(phys, virt, size, page_attribs); }
91 typename Obj_space::Capability FIASCO_FLATTEN
92 lookup(Cap_index virt) override
93 { return Obj_space::lookup(virt); }
95 typename Obj_space::V_pfn FIASCO_FLATTEN
96 obj_map_max_address() const override
97 { return Obj_space::obj_map_max_address(); }
99 void FIASCO_FLATTEN caps_free() override
100 { Obj_space::caps_free(); }
102 template<typename ...ARGS>
103 Obj_space_phys_override(ARGS &&...args) : BASE(cxx::forward<ARGS>(args)...) {}
106 // ------------------------------------------------------------------------
107 INTERFACE [!obj_space_virt]:
109 #include "cxx/type_traits"
112 * The noop version when Space already uses a multi-level array for
115 template<typename BASE>
116 class Obj_space_phys_override : public BASE
119 template<typename ...ARGS>
120 Obj_space_phys_override(ARGS &&...args) : BASE(cxx::forward<ARGS>(args)...) {}
123 //----------------------------------------------------------------------------
132 #include "kmem_alloc.h"
134 #include "mem_layout.h"
135 #include "ram_quota.h"
136 #include "static_assert.h"
138 PUBLIC template< typename SPACE >
139 inline NEEDS["static_assert.h"]
140 Obj_space_phys<SPACE>::Obj_space_phys()
142 static_assert(sizeof(Cap_dir) == Config::PAGE_SIZE, "cap_dir size mismatch");
143 _dir = (Cap_dir*)Kmem_alloc::allocator()->q_unaligned_alloc(ram_quota(), Config::PAGE_SIZE);
145 Mem::memset_mwords(_dir, 0, Config::PAGE_SIZE / sizeof(Mword));
148 PRIVATE template< typename SPACE >
149 typename Obj_space_phys<SPACE>::Entry *
150 Obj_space_phys<SPACE>::get_cap(Cap_index index)
152 if (EXPECT_FALSE(!_dir))
155 unsigned d_idx = cxx::int_value<Cap_index>(index) >> Obj::Caps_per_page_ld2;
156 if (EXPECT_FALSE(d_idx >= Slots_per_dir))
159 Cap_table *tab = _dir->d[d_idx];
161 if (EXPECT_FALSE(!tab))
164 unsigned offs = cxx::get_lsb(cxx::int_value<Cap_index>(index), Obj::Caps_per_page_ld2);
165 return &tab->e[offs];
168 PRIVATE template< typename SPACE >
169 typename Obj_space_phys<SPACE>::Entry *
170 Obj_space_phys<SPACE>::caps_alloc(Cap_index virt)
172 static_assert(sizeof(Cap_table) == Config::PAGE_SIZE, "cap table size mismatch");
173 unsigned d_idx = cxx::int_value<Cap_index>(virt) >> Obj::Caps_per_page_ld2;
174 if (EXPECT_FALSE(d_idx >= Slots_per_dir))
177 void *mem = Kmem_alloc::allocator()->q_unaligned_alloc(ram_quota(), Config::PAGE_SIZE);
182 Obj::add_cap_page_dbg_info(mem, SPACE::get_space(this), cxx::int_value<Cap_index>(virt));
184 Mem::memset_mwords(mem, 0, Config::PAGE_SIZE / sizeof(Mword));
186 Cap_table *tab = _dir->d[d_idx] = (Cap_table*)mem;
187 return &tab->e[ cxx::get_lsb(cxx::int_value<Cap_index>(virt), Obj::Caps_per_page_ld2)];
190 PUBLIC template< typename SPACE >
192 Obj_space_phys<SPACE>::caps_free()
200 Kmem_alloc *a = Kmem_alloc::allocator();
201 for (unsigned i = 0; i < Slots_per_dir; ++i)
206 Obj::remove_cap_page_dbg_info(d->d[i]);
207 a->q_unaligned_free(ram_quota(), Config::PAGE_SIZE, d->d[i]);
210 a->q_unaligned_free(ram_quota(), Config::PAGE_SIZE, d);
214 // Utilities for map<Obj_space_phys> and unmap<Obj_space_phys>
217 IMPLEMENT template< typename SPACE >
218 inline NEEDS[Obj_space_phys::get_cap]
220 Obj_space_phys<SPACE>::v_lookup(V_pfn const &virt, Phys_addr *phys,
221 Page_order *size, Attr *attribs)
223 if (size) *size = Page_order(0);
224 Entry *cap = get_cap(virt);
226 if (EXPECT_FALSE(!cap))
228 if (size) *size = Page_order(Obj::Caps_per_page_ld2);
234 Obj::set_entry(virt, cap);
235 if (phys) *phys = c.obj();
236 if (c.valid() && attribs) *attribs = cap->rights();
240 IMPLEMENT template< typename SPACE >
241 inline NEEDS [Obj_space_phys::get_cap]
242 typename Obj_space_phys<SPACE>::Capability FIASCO_FLATTEN
243 Obj_space_phys<SPACE>::lookup(Cap_index virt)
245 Capability *c = get_cap(virt);
247 if (EXPECT_FALSE(!c))
248 return Capability(0); // void
253 PUBLIC template< typename SPACE >
256 Obj_space_phys<SPACE>::lookup_local(Cap_index virt, L4_fpage::Rights *rights)
258 Entry *c = get_cap(virt);
260 if (EXPECT_FALSE(!c))
266 *rights = L4_fpage::Rights(cap.rights());
272 IMPLEMENT template< typename SPACE >
273 inline NEEDS[<cassert>, Obj_space_phys::get_cap]
274 L4_fpage::Rights FIASCO_FLATTEN
275 Obj_space_phys<SPACE>::v_delete(V_pfn virt, Page_order size,
276 L4_fpage::Rights page_attribs = L4_fpage::Rights::FULL())
279 assert (size == Page_order(0));
280 Capability *c = get_cap(virt);
284 if (page_attribs & L4_fpage::Rights::R())
287 c->del_rights(page_attribs);
290 return L4_fpage::Rights(0);
293 IMPLEMENT template< typename SPACE >
294 inline NEEDS[Obj_space_phys::caps_alloc]
295 typename Obj::Insert_result FIASCO_FLATTEN
296 Obj_space_phys<SPACE>::v_insert(Phys_addr phys, V_pfn const &virt, Page_order size,
300 assert (size == Page_order(0));
302 Entry *c = get_cap(virt);
304 if (!c && !(c = caps_alloc(virt)))
305 return Obj::Insert_err_nomem;
309 if (c->obj() == phys)
311 if (EXPECT_FALSE(c->rights() == page_attribs))
312 return Obj::Insert_warn_exists;
314 c->add_rights(page_attribs);
315 return Obj::Insert_warn_attrib_upgrade;
318 return Obj::Insert_err_exists;
321 Obj::set_entry(virt, c);
322 c->set(phys, page_attribs);
323 return Obj::Insert_ok;
327 PUBLIC template< typename SPACE >
329 typename Obj_space_phys<SPACE>::V_pfn
330 Obj_space_phys<SPACE>::obj_map_max_address() const
332 return V_pfn(Slots_per_dir * Obj::Caps_per_page);
335 // ------------------------------------------------------------------------------
336 IMPLEMENTATION [debug]:
338 PUBLIC template< typename SPACE >
339 typename Obj_space_phys<SPACE>::Entry *
340 Obj_space_phys<SPACE>::jdb_lookup_cap(Cap_index index)
341 { return get_cap(index); }
343 // ------------------------------------------------------------------------------
344 IMPLEMENTATION [obj_space_virt && debug]:
346 PUBLIC template<typename BASE> static inline
347 Obj_space_phys_override<BASE> *
348 Obj_space_phys_override<BASE>::get_space(Obj_space *base)
349 { return static_cast<Obj_space_phys_override<BASE> *>(base); }
351 PUBLIC template<typename BASE>
353 Obj_space_phys_override<BASE>::jdb_lookup_cap(Cap_index index) override
354 { return Obj_space::jdb_lookup_cap(index); }
356 // ------------------------------------------------------------------------------
357 IMPLEMENTATION [obj_space_virt && !debug]:
359 PUBLIC template<typename BASE> static inline
360 Obj_space_phys_override<BASE> *
361 Obj_space_phys_override<BASE>::get_space(Obj_space *)