]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/obj_space_virt_util.cpp
Some minor fixes.
[l4.git] / kernel / fiasco / src / kern / obj_space_virt_util.cpp
1 INTERFACE:
2
3 #include "mem.h"
4 #include "mem_space.h"
5 #include "ram_quota.h"
6 #include "obj_space_types.h"
7
8 template<typename SPACE>
9 class Obj_space_virt
10 {
11 public:
12   typedef Obj::Attr Attr;
13   typedef Obj::Capability Capability;
14   typedef Obj::Entry Entry;
15   typedef Kobject_iface *Phys_addr;
16
17   typedef Obj::Cap_addr V_pfn;
18   typedef Cap_diff V_pfc;
19   typedef Order Page_order;
20
21   bool v_lookup(V_pfn const &virt, Phys_addr *phys,
22                 Page_order *size, Attr *attribs);
23
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,
27                               Attr page_attribs);
28
29   Capability lookup(Cap_index virt);
30
31 private:
32   enum
33   {
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.
38     Optimize_local = 0,
39
40     Whole_space = 20,
41     Map_max_address = 1UL << 20, /* 20bit obj index */
42   };
43 };
44
45 IMPLEMENTATION:
46
47 #include <cstring>
48 #include <cassert>
49
50 #include "atomic.h"
51 #include "config.h"
52 #include "cpu.h"
53 #include "kmem_alloc.h"
54 #include "mem_layout.h"
55
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); }
61
62
63
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)
68 {
69   Mem_space *ms = SPACE::mem_space(this);
70
71   Address phys = Address(ms->virt_to_phys((Address)cap_virt(index)));
72   if (EXPECT_FALSE(phys == ~0UL))
73     return 0;
74
75   return reinterpret_cast<Entry*>(Mem_layout::phys_to_pmem(phys));
76 }
77
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)
83 {
84   Address cv = (Address)cap_virt(virt);
85   void *mem = Kmem_alloc::allocator()->q_unaligned_alloc(SPACE::ram_quota(this), Config::PAGE_SIZE);
86
87   if (!mem)
88     return 0;
89
90   Obj::add_cap_page_dbg_info(mem, SPACE::get_space(this), cxx::int_value<Cap_index>(virt));
91
92   Mem::memset_mwords(mem, 0, Config::PAGE_SIZE / sizeof(Mword));
93
94   Mem_space::Status s;
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);
101
102   switch (s)
103     {
104     case Mem_space::Insert_ok:
105       break;
106     case Mem_space::Insert_warn_exists:
107     case Mem_space::Insert_warn_attrib_upgrade:
108       assert (false);
109       break;
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);
114       return 0;
115     };
116
117   unsigned long cap = cv & (Config::PAGE_SIZE - 1) | (unsigned long)mem;
118
119   return reinterpret_cast<Entry*>(cap);
120 }
121
122 PROTECTED template< typename SPACE >
123 void
124 Obj_space_virt<SPACE>::caps_free()
125 {
126   Mem_space *ms = SPACE::mem_space(this);
127   if (EXPECT_FALSE(!ms || !ms->dir()))
128     return;
129
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))
133     {
134       Entry *c = get_cap(i);
135       if (!c)
136         continue;
137
138       Address cp = Address(ms->virt_to_phys(Address(c)));
139       assert (cp != ~0UL);
140       void *cv = (void*)Mem_layout::phys_to_pmem(cp);
141       Obj::remove_cap_page_dbg_info(cv);
142
143       a->q_unaligned_free(SPACE::ram_quota(this), Config::PAGE_SIZE, cv);
144     }
145   ms->dir()->destroy(Virt_addr(Mem_layout::Caps_start),
146                      Virt_addr(Mem_layout::Caps_end-1),
147                      Pdir::Super_level,
148                      Pdir::Depth,
149                      Kmem_alloc::q_allocator(SPACE::ram_quota(this)));
150 }
151
152 //
153 // Utilities for map<Obj_space_virt> and unmap<Obj_space_virt>
154 //
155
156 IMPLEMENT  template< typename SPACE >
157 inline  NEEDS[Obj_space_virt::cap_virt, Obj_space_virt::get_cap]
158 bool FIASCO_FLATTEN
159 Obj_space_virt<SPACE>::v_lookup(V_pfn const &virt, Phys_addr *phys,
160                                    Page_order *size, Attr *attribs)
161 {
162   if (size) *size = Order(0);
163   Entry *cap;
164
165   if (Optimize_local
166       && SPACE::mem_space(this) == Mem_space::current_mem_space(current_cpu()))
167     cap = cap_virt(virt);
168   else
169     cap = get_cap(virt);
170
171   if (EXPECT_FALSE(!cap))
172     {
173       if (size) *size = Order(Obj::Caps_per_page_ld2);
174       return false;
175     }
176
177   if (Optimize_local)
178     {
179       Capability c = Mem_layout::read_special_safe((Capability*)cap);
180
181       if (phys) *phys = c.obj();
182       if (c.valid() && attribs)
183         *attribs = Attr(c.rights());
184       return c.valid();
185     }
186   else
187     {
188       Obj::set_entry(virt, cap);
189       if (phys) *phys = cap->obj();
190       if (cap->valid() && attribs)
191         *attribs = Attr(cap->rights());
192       return cap->valid();
193     }
194 }
195
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)
200 {
201   Capability *c;
202   virt &= Cap_index(~(~0UL << Whole_space));
203
204   if (SPACE::mem_space(this) == Mem_space::current_mem_space(current_cpu()))
205     c = reinterpret_cast<Capability*>(cap_virt(virt));
206   else
207     c = get_cap(virt);
208
209   if (EXPECT_FALSE(!c))
210     return Capability(0); // void
211
212   return Mem_layout::read_special_safe(c);
213 }
214
215 PUBLIC template< typename SPACE >
216 inline NEEDS [Obj_space_virt::cap_virt]
217 Kobject_iface *
218 Obj_space_virt<SPACE>::lookup_local(Cap_index virt, L4_fpage::Rights *rights)
219 {
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());
224   return cap.obj();
225 }
226
227
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)
233 {
234   (void)size;
235   assert (size == Order(0));
236
237   Entry *c;
238   if (Optimize_local
239       && SPACE::mem_space(this) == Mem_space::current_mem_space(current_cpu()))
240     {
241       c = cap_virt(virt);
242       if (!c)
243         return L4_fpage::Rights(0);
244
245       Capability cap = Mem_layout::read_special_safe((Capability*)c);
246       if (!cap.valid())
247         return L4_fpage::Rights(0);
248     }
249   else
250     c = get_cap(virt);
251
252   if (c && c->valid())
253     {
254       if (page_attribs & L4_fpage::Rights::R())
255         c->invalidate();
256       else
257         c->del_rights(page_attribs & L4_fpage::Rights::CWSD());
258     }
259
260   return L4_fpage::Rights(0);
261 }
262
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,
268                                 Attr page_attribs)
269 {
270   (void)size;
271   assert (size == Order(0));
272
273   Entry *c;
274
275   if (Optimize_local
276       && SPACE::mem_space(this) == Mem_space::current_mem_space(current_cpu()))
277     {
278       c = cap_virt(virt);
279       if (!c)
280         return Obj::Insert_err_nomem;
281
282       Capability cap;
283       if (!Mem_layout::read_special_safe((Capability*)c, cap)
284           && !caps_alloc(virt))
285         return Obj::Insert_err_nomem;
286     }
287   else
288     {
289       c = get_cap(virt);
290       if (!c && !(c = caps_alloc(virt)))
291         return Obj::Insert_err_nomem;
292       Obj::set_entry(virt, c);
293     }
294
295   if (c->valid())
296     {
297       if (c->obj() == phys)
298         {
299           if (EXPECT_FALSE(c->rights() == page_attribs))
300             return Obj::Insert_warn_exists;
301
302           c->add_rights(page_attribs);
303           return Obj::Insert_warn_attrib_upgrade;
304         }
305       else
306         return Obj::Insert_err_exists;
307     }
308
309   c->set(phys, page_attribs);
310   return Obj::Insert_ok;
311 }
312
313
314 PUBLIC  template< typename SPACE >
315 virtual inline
316 typename Obj_space_virt<SPACE>::V_pfn
317 Obj_space_virt<SPACE>::obj_map_max_address() const
318 {
319   Mword r;
320
321   r = (Mem_layout::Caps_end - Mem_layout::Caps_start) / sizeof(Entry);
322   if (Map_max_address < r)
323     r = Map_max_address;
324
325   return V_pfn(r);
326 }
327
328 // ------------------------------------------------------------------------------
329 IMPLEMENTATION [debug]:
330
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); }
335