7 EXTENSION class Generic_obj_space
9 // do not use the virtually mapped cap table in
10 // v_lookup and v_insert, because the map logic needs the kernel
11 // address for link pointers in the map-nodes and these addresses must
12 // be valid in all address spaces.
13 enum { Optimize_local = 0 };
25 #include "kmem_alloc.h"
26 #include "mem_layout.h"
28 PRIVATE template< typename SPACE > inline
30 Generic_obj_space<SPACE>::mem_space()
31 { return static_cast<SPACE*>(this); }
33 PRIVATE template< typename SPACE >
34 static inline NEEDS["mem_layout.h"]
35 typename Generic_obj_space<SPACE>::Entry *
36 Generic_obj_space<SPACE>::cap_virt(Address index)
37 { return reinterpret_cast<Entry*>(Mem_layout::Caps_start) + index; }
39 PRIVATE template< typename SPACE >
40 inline NEEDS["mem_space.h", "mem_layout.h", Generic_obj_space::cap_virt]
41 typename Generic_obj_space<SPACE>::Entry *
42 Generic_obj_space<SPACE>::alien_lookup(Address index)
44 Mem_space *ms = mem_space();
46 Address phys = Address(ms->virt_to_phys((Address)cap_virt(index)));
47 if (EXPECT_FALSE(phys == ~0UL))
50 return reinterpret_cast<Entry*>(Mem_layout::phys_to_pmem(phys));
53 PRIVATE template< typename SPACE >
54 typename Generic_obj_space<SPACE>::Entry *
55 Generic_obj_space<SPACE>::get_cap(Address index)
56 { return alien_lookup(index); }
58 PUBLIC template< typename SPACE >
59 inline NEEDS["mem_space.h"]
61 Generic_obj_space<SPACE>::ram_quota() const
62 { return static_cast<SPACE const *>(this)->ram_quota(); }
65 PRIVATE template< typename SPACE >
66 /*inline NEEDS["kmem_alloc.h", <cstring>, "ram_quota.h",
67 Generic_obj_space::cap_virt]*/
68 typename Generic_obj_space<SPACE>::Entry *
69 Generic_obj_space<SPACE>::caps_alloc(Address virt)
71 Address cv = (Address)cap_virt(virt);
72 void *mem = Kmem_alloc::allocator()->q_unaligned_alloc(ram_quota(), Config::PAGE_SIZE);
77 add_dbg_info(mem, this, virt);
79 Mem::memset_mwords(mem, 0, Config::PAGE_SIZE / sizeof(Mword));
82 s = mem_space()->v_insert(
83 Mem_space::Phys_addr::create(Mem_space::kernel_space()->virt_to_phys((Address)mem)),
84 Mem_space::Addr::create(cv).trunc(Mem_space::Size::create(Config::PAGE_SIZE)),
85 Mem_space::Size::create(Config::PAGE_SIZE),
86 Mem_space::Page_cacheable | Mem_space::Page_writable
87 | Mem_space::Page_referenced | Mem_space::Page_dirty);
93 case Insert_warn_exists:
94 case Insert_warn_attrib_upgrade:
97 case Insert_err_exists:
98 case Insert_err_nomem:
99 Kmem_alloc::allocator()->q_unaligned_free(ram_quota(),
100 Config::PAGE_SIZE, mem);
104 unsigned long cap = cv & (Config::PAGE_SIZE - 1) | (unsigned long)mem;
106 return reinterpret_cast<Entry*>(cap);
109 PRIVATE template< typename SPACE >
111 Generic_obj_space<SPACE>::caps_free()
113 Mem_space *ms = mem_space();
114 if (EXPECT_FALSE(!ms || !ms->dir()))
117 Kmem_alloc *a = Kmem_alloc::allocator();
118 for (unsigned long i = 0; i < map_max_address().value();
121 Entry *c = get_cap(i);
125 Address cp = Address(ms->virt_to_phys(Address(c)));
126 assert_kdb (cp != ~0UL);
127 void *cv = (void*)Mem_layout::phys_to_pmem(cp);
130 a->q_unaligned_free(ram_quota(), Config::PAGE_SIZE, cv);
132 #if defined (CONFIG_ARM)
133 ms->dir()->free_page_tables((void*)Mem_layout::Caps_start, (void*)Mem_layout::Caps_end, Kmem_alloc::q_allocator(ram_quota()));
135 ms->dir()->destroy(Virt_addr(Mem_layout::Caps_start),
136 Virt_addr(Mem_layout::Caps_end), Pdir::Depth - 1,
137 Kmem_alloc::q_allocator(ram_quota()));
142 // Utilities for map<Generic_obj_space> and unmap<Generic_obj_space>
145 PUBLIC template< typename SPACE >
146 inline NEEDS[Generic_obj_space::cap_virt, Generic_obj_space::get_cap]
148 Generic_obj_space<SPACE>::v_lookup(Addr const &virt, Phys_addr *phys = 0,
149 Size *size = 0, unsigned *attribs = 0)
151 if (size) size->set_value(1);
155 && mem_space() == Mem_space::current_mem_space(current_cpu()))
156 cap = cap_virt(virt.value());
158 cap = get_cap(virt.value());
160 if (EXPECT_FALSE(!cap))
162 if (size) size->set_value(Caps_per_page);
168 Capability c = Mem_layout::read_special_safe((Capability*)cap);
170 if (phys) *phys = c.obj();
171 if (c.valid() && attribs) *attribs = c.rights();
176 Obj::set_entry(virt, cap);
177 if (phys) *phys = cap->obj();
178 if (cap->valid() && attribs) *attribs = cap->rights();
183 PUBLIC template< typename SPACE >
184 inline NEEDS [Generic_obj_space::cap_virt, Generic_obj_space::get_cap]
185 typename Generic_obj_space<SPACE>::Capability
186 Generic_obj_space<SPACE>::lookup(Address virt)
189 virt &= ~(~0UL << Whole_space);
191 if (mem_space() == Mem_space::current_mem_space(current_cpu()))
192 c = reinterpret_cast<Capability*>(cap_virt(virt));
196 if (EXPECT_FALSE(!c))
197 return Capability(0); // void
199 return Mem_layout::read_special_safe(c);
202 PUBLIC template< typename SPACE >
203 inline NEEDS [Generic_obj_space::cap_virt]
205 Generic_obj_space<SPACE>::lookup_local(Address virt, unsigned char *rights = 0)
207 virt &= ~(~0UL << Whole_space);
208 Capability *c = reinterpret_cast<Capability*>(cap_virt(virt));
209 Capability cap = Mem_layout::read_special_safe(c);
210 if (rights) *rights = cap.rights();
215 PUBLIC template< typename SPACE >
216 inline NEEDS[<cassert>, Generic_obj_space::cap_virt, Generic_obj_space::get_cap]
218 Generic_obj_space<SPACE>::v_delete(Page_number virt, Size size,
219 unsigned long page_attribs = L4_fpage::CRWSD)
222 assert (size.value() == 1);
226 && mem_space() == Mem_space::current_mem_space(current_cpu()))
228 c = cap_virt(virt.value());
232 Capability cap = Mem_layout::read_special_safe((Capability*)c);
237 c = get_cap(virt.value());
241 if (page_attribs & L4_fpage::R)
244 c->del_rights(page_attribs & L4_fpage::CWSD);
250 PUBLIC template< typename SPACE >
251 inline NEEDS[Generic_obj_space::cap_virt, Generic_obj_space::caps_alloc,
252 Generic_obj_space::alien_lookup, "kdb_ke.h"]
253 typename Generic_obj_space<SPACE>::Status
254 Generic_obj_space<SPACE>::v_insert(Phys_addr phys, Addr const &virt, Size size,
255 unsigned char page_attribs)
258 assert (size.value() == 1);
263 && mem_space() == Mem_space::current_mem_space(current_cpu()))
265 c = cap_virt(virt.value());
267 return Insert_err_nomem;
270 if (!Mem_layout::read_special_safe((Capability*)c, cap)
271 && !caps_alloc(virt.value()))
272 return Insert_err_nomem;
276 c = alien_lookup(virt.value());
277 if (!c && !(c = caps_alloc(virt.value())))
278 return Insert_err_nomem;
279 Obj::set_entry(virt, c);
284 if (c->obj() == phys)
286 if (EXPECT_FALSE(c->rights() == page_attribs))
287 return Insert_warn_exists;
289 c->add_rights(page_attribs);
290 return Insert_warn_attrib_upgrade;
293 return Insert_err_exists;
296 c->set(phys, page_attribs);
301 PUBLIC template< typename SPACE >
303 typename Generic_obj_space<SPACE>::Addr
304 Generic_obj_space<SPACE>::map_max_address()
308 r = (Mem_layout::Caps_end - Mem_layout::Caps_start) / sizeof(Entry);
309 if (Map_max_address < r)