6 #include "obj_space_types.h"
8 template<typename SPACE>
12 typedef Obj::Attr Attr;
13 typedef Obj::Capability Capability;
14 typedef Obj::Entry Entry;
15 typedef Kobject_iface *Phys_addr;
17 typedef Obj::Cap_addr V_pfn;
18 typedef Cap_diff V_pfc;
19 typedef Order Page_order;
21 bool v_lookup(V_pfn const &virt, Phys_addr *phys,
22 Page_order *size, Attr *attribs);
24 L4_fpage::Rights v_delete(V_pfn virt, Order size,
25 L4_fpage::Rights page_attribs);
26 Obj::Insert_result v_insert(Phys_addr phys, V_pfn const &virt, Order size,
29 Capability lookup(Cap_index virt);
34 // do not use the virtually mapped cap table in
35 // v_lookup and v_insert, because the map logic needs the kernel
36 // address for link pointers in the map-nodes and these addresses must
37 // be valid in all address spaces.
41 Map_max_address = 1UL << 20, /* 20bit obj index */
53 #include "kmem_alloc.h"
54 #include "mem_layout.h"
56 PRIVATE template< typename SPACE >
57 static inline NEEDS["mem_layout.h"]
58 typename Obj_space_virt<SPACE>::Entry *
59 Obj_space_virt<SPACE>::cap_virt(Cap_index index)
60 { return reinterpret_cast<Entry*>(Mem_layout::Caps_start) + cxx::int_value<Cap_index>(index); }
64 PRIVATE template< typename SPACE >
65 inline NEEDS["mem_space.h", "mem_layout.h", Obj_space_virt::cap_virt]
66 typename Obj_space_virt<SPACE>::Entry *
67 Obj_space_virt<SPACE>::get_cap(Cap_index index)
69 Mem_space *ms = SPACE::mem_space(this);
71 Address phys = Address(ms->virt_to_phys((Address)cap_virt(index)));
72 if (EXPECT_FALSE(phys == ~0UL))
75 return reinterpret_cast<Entry*>(Mem_layout::phys_to_pmem(phys));
78 PRIVATE template< typename SPACE >
79 /*inline NEEDS["kmem_alloc.h", <cstring>, "ram_quota.h",
80 Obj_space_virt::cap_virt]*/
81 typename Obj_space_virt<SPACE>::Entry *
82 Obj_space_virt<SPACE>::caps_alloc(Cap_index virt)
84 Address cv = (Address)cap_virt(virt);
85 void *mem = Kmem_alloc::allocator()->q_unaligned_alloc(SPACE::ram_quota(this), Config::PAGE_SIZE);
90 Obj::add_cap_page_dbg_info(mem, SPACE::get_space(this), cxx::int_value<Cap_index>(virt));
92 Mem::memset_mwords(mem, 0, Config::PAGE_SIZE / sizeof(Mword));
95 s = SPACE::mem_space(this)->v_insert(
96 Mem_space::Phys_addr(Mem_space::kernel_space()->virt_to_phys((Address)mem)),
97 cxx::mask_lsb(Virt_addr(cv), Mem_space::Page_order(Config::PAGE_SHIFT)),
98 Mem_space::Page_order(Config::PAGE_SHIFT),
99 Mem_space::Attr(L4_fpage::Rights::RW()));
100 //| Mem_space::Page_referenced | Mem_space::Page_dirty);
104 case Mem_space::Insert_ok:
106 case Mem_space::Insert_warn_exists:
107 case Mem_space::Insert_warn_attrib_upgrade:
110 case Mem_space::Insert_err_exists:
111 case Mem_space::Insert_err_nomem:
112 Kmem_alloc::allocator()->q_unaligned_free(SPACE::ram_quota(this),
113 Config::PAGE_SIZE, mem);
117 unsigned long cap = cv & (Config::PAGE_SIZE - 1) | (unsigned long)mem;
119 return reinterpret_cast<Entry*>(cap);
122 PROTECTED template< typename SPACE >
124 Obj_space_virt<SPACE>::caps_free()
126 Mem_space *ms = SPACE::mem_space(this);
127 if (EXPECT_FALSE(!ms || !ms->dir()))
130 Kmem_alloc *a = Kmem_alloc::allocator();
131 for (Cap_index i = Cap_index(0); i < obj_map_max_address();
132 i += Cap_diff(Obj::Caps_per_page))
134 Entry *c = get_cap(i);
138 Address cp = Address(ms->virt_to_phys(Address(c)));
140 void *cv = (void*)Mem_layout::phys_to_pmem(cp);
141 Obj::remove_cap_page_dbg_info(cv);
143 a->q_unaligned_free(SPACE::ram_quota(this), Config::PAGE_SIZE, cv);
145 ms->dir()->destroy(Virt_addr(Mem_layout::Caps_start),
146 Virt_addr(Mem_layout::Caps_end-1),
149 Kmem_alloc::q_allocator(SPACE::ram_quota(this)));
153 // Utilities for map<Obj_space_virt> and unmap<Obj_space_virt>
156 IMPLEMENT template< typename SPACE >
157 inline NEEDS[Obj_space_virt::cap_virt, Obj_space_virt::get_cap]
159 Obj_space_virt<SPACE>::v_lookup(V_pfn const &virt, Phys_addr *phys,
160 Page_order *size, Attr *attribs)
162 if (size) *size = Order(0);
166 && SPACE::mem_space(this) == Mem_space::current_mem_space(current_cpu()))
167 cap = cap_virt(virt);
171 if (EXPECT_FALSE(!cap))
173 if (size) *size = Order(Obj::Caps_per_page_ld2);
179 Capability c = Mem_layout::read_special_safe((Capability*)cap);
181 if (phys) *phys = c.obj();
182 if (c.valid() && attribs)
183 *attribs = Attr(c.rights());
188 Obj::set_entry(virt, cap);
189 if (phys) *phys = cap->obj();
190 if (cap->valid() && attribs)
191 *attribs = Attr(cap->rights());
196 IMPLEMENT template< typename SPACE >
197 inline NEEDS [Obj_space_virt::cap_virt, Obj_space_virt::get_cap]
198 typename Obj_space_virt<SPACE>::Capability FIASCO_FLATTEN
199 Obj_space_virt<SPACE>::lookup(Cap_index virt)
202 virt &= Cap_index(~(~0UL << Whole_space));
204 if (SPACE::mem_space(this) == Mem_space::current_mem_space(current_cpu()))
205 c = reinterpret_cast<Capability*>(cap_virt(virt));
209 if (EXPECT_FALSE(!c))
210 return Capability(0); // void
212 return Mem_layout::read_special_safe(c);
215 PUBLIC template< typename SPACE >
216 inline NEEDS [Obj_space_virt::cap_virt]
218 Obj_space_virt<SPACE>::lookup_local(Cap_index virt, L4_fpage::Rights *rights)
220 virt &= Cap_index(~(~0UL << Whole_space));
221 Capability *c = reinterpret_cast<Capability*>(cap_virt(virt));
222 Capability cap = Mem_layout::read_special_safe(c);
223 if (rights) *rights = L4_fpage::Rights(cap.rights());
228 IMPLEMENT template< typename SPACE >
229 inline NEEDS[<cassert>, Obj_space_virt::cap_virt, Obj_space_virt::get_cap]
230 L4_fpage::Rights FIASCO_FLATTEN
231 Obj_space_virt<SPACE>::v_delete(V_pfn virt, Order size,
232 L4_fpage::Rights page_attribs)
235 assert (size == Order(0));
239 && SPACE::mem_space(this) == Mem_space::current_mem_space(current_cpu()))
243 return L4_fpage::Rights(0);
245 Capability cap = Mem_layout::read_special_safe((Capability*)c);
247 return L4_fpage::Rights(0);
254 if (page_attribs & L4_fpage::Rights::R())
257 c->del_rights(page_attribs & L4_fpage::Rights::CWSD());
260 return L4_fpage::Rights(0);
263 IMPLEMENT template< typename SPACE >
264 inline NEEDS[Obj_space_virt::cap_virt, Obj_space_virt::caps_alloc,
265 Obj_space_virt::get_cap, <cassert>]
266 typename Obj::Insert_result FIASCO_FLATTEN
267 Obj_space_virt<SPACE>::v_insert(Phys_addr phys, V_pfn const &virt, Order size,
271 assert (size == Order(0));
276 && SPACE::mem_space(this) == Mem_space::current_mem_space(current_cpu()))
280 return Obj::Insert_err_nomem;
283 if (!Mem_layout::read_special_safe((Capability*)c, cap)
284 && !caps_alloc(virt))
285 return Obj::Insert_err_nomem;
290 if (!c && !(c = caps_alloc(virt)))
291 return Obj::Insert_err_nomem;
292 Obj::set_entry(virt, c);
297 if (c->obj() == phys)
299 if (EXPECT_FALSE(c->rights() == page_attribs))
300 return Obj::Insert_warn_exists;
302 c->add_rights(page_attribs);
303 return Obj::Insert_warn_attrib_upgrade;
306 return Obj::Insert_err_exists;
309 c->set(phys, page_attribs);
310 return Obj::Insert_ok;
314 PUBLIC template< typename SPACE >
316 typename Obj_space_virt<SPACE>::V_pfn
317 Obj_space_virt<SPACE>::obj_map_max_address() const
321 r = (Mem_layout::Caps_end - Mem_layout::Caps_start) / sizeof(Entry);
322 if (Map_max_address < r)
328 // ------------------------------------------------------------------------------
329 IMPLEMENTATION [debug]:
331 PUBLIC template< typename SPACE >
332 typename Obj_space_virt<SPACE>::Entry *
333 Obj_space_virt<SPACE>::jdb_lookup_cap(Cap_index index)
334 { return get_cap(index); }