]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/obj_space_phys_util.cpp
update
[l4.git] / kernel / fiasco / src / kern / obj_space_phys_util.cpp
1 INTERFACE:
2
3 #include "assert_opt.h"
4 #include "obj_space_types.h"
5 #include "ram_quota.h"
6
7 template< typename SPACE >
8 class Obj_space_phys
9 {
10 public:
11   typedef Obj::Attr Attr;
12   typedef Obj::Capability Capability;
13   typedef Obj::Entry Entry;
14   typedef Kobject_iface *Phys_addr;
15
16   typedef Obj::Cap_addr V_pfn;
17   typedef Cap_diff V_pfc;
18   typedef Order Page_order;
19
20   bool v_lookup(V_pfn const &virt, Phys_addr *phys,
21                 Page_order *size, Attr *attribs);
22
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,
26                               Attr page_attribs);
27
28   Capability lookup(Cap_index virt);
29
30 private:
31   enum
32   {
33     Slots_per_dir = Config::PAGE_SIZE / sizeof(void*)
34   };
35
36   struct Cap_table { Entry e[Obj::Caps_per_page]; };
37   struct Cap_dir   { Cap_table *d[Slots_per_dir]; };
38   Cap_dir *_dir;
39
40   Ram_quota *ram_quota() const
41   {
42     assert_opt (this);
43     return SPACE::ram_quota(this);
44   }
45 };
46
47
48 //----------------------------------------------------------------------------
49 IMPLEMENTATION:
50
51 #include <cstring>
52 #include <cassert>
53
54 #include "atomic.h"
55 #include "config.h"
56 #include "cpu.h"
57 #include "kmem_alloc.h"
58 #include "mem.h"
59 #include "mem_layout.h"
60 #include "ram_quota.h"
61 #include "static_assert.h"
62
63 PUBLIC template< typename SPACE >
64 inline NEEDS["static_assert.h"]
65 Obj_space_phys<SPACE>::Obj_space_phys()
66 {
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);
69   if (_dir)
70     Mem::memset_mwords(_dir, 0, Config::PAGE_SIZE / sizeof(Mword));
71 }
72
73 PRIVATE template< typename SPACE >
74 typename Obj_space_phys<SPACE>::Entry *
75 Obj_space_phys<SPACE>::get_cap(Cap_index index)
76 {
77   if (EXPECT_FALSE(!_dir))
78     return 0;
79
80   unsigned d_idx = cxx::int_value<Cap_index>(index) >> Obj::Caps_per_page_ld2;
81   if (EXPECT_FALSE(d_idx >= Slots_per_dir))
82     return 0;
83
84   Cap_table *tab = _dir->d[d_idx];
85
86   if (EXPECT_FALSE(!tab))
87     return 0;
88
89   unsigned offs  = cxx::get_lsb(cxx::int_value<Cap_index>(index), Obj::Caps_per_page_ld2);
90   return &tab->e[offs];
91 }
92
93 PRIVATE template< typename SPACE >
94 typename Obj_space_phys<SPACE>::Entry *
95 Obj_space_phys<SPACE>::caps_alloc(Cap_index virt)
96 {
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))
100     return 0;
101
102   void *mem = Kmem_alloc::allocator()->q_unaligned_alloc(ram_quota(), Config::PAGE_SIZE);
103
104   if (!mem)
105     return 0;
106
107   Obj::add_cap_page_dbg_info(mem, SPACE::get_space(this),  cxx::int_value<Cap_index>(virt));
108
109   Mem::memset_mwords(mem, 0, Config::PAGE_SIZE / sizeof(Mword));
110
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)];
113 }
114
115 PUBLIC template< typename SPACE >
116 void
117 Obj_space_phys<SPACE>::caps_free()
118 {
119   if (!_dir)
120     return;
121
122   Cap_dir *d = _dir;
123   _dir = 0;
124
125   Kmem_alloc *a = Kmem_alloc::allocator();
126   for (unsigned i = 0; i < Slots_per_dir; ++i)
127     {
128       if (!d->d[i])
129         continue;
130
131       Obj::remove_cap_page_dbg_info(d->d[i]);
132       a->q_unaligned_free(ram_quota(), Config::PAGE_SIZE, d->d[i]);
133     }
134
135   a->q_unaligned_free(ram_quota(), Config::PAGE_SIZE, d);
136 }
137
138 //
139 // Utilities for map<Obj_space_phys> and unmap<Obj_space_phys>
140 //
141
142 IMPLEMENT template< typename SPACE >
143 inline NEEDS[Obj_space_phys::get_cap]
144 bool FIASCO_FLATTEN
145 Obj_space_phys<SPACE>::v_lookup(V_pfn const &virt, Phys_addr *phys,
146                                 Page_order *size, Attr *attribs)
147 {
148   if (size) *size = Page_order(0);
149   Entry *cap = get_cap(virt);
150
151   if (EXPECT_FALSE(!cap))
152     {
153       if (size) *size = Page_order(Obj::Caps_per_page_ld2);
154       return false;
155     }
156
157   Capability c = *cap;
158
159   Obj::set_entry(virt, cap);
160   if (phys) *phys = c.obj();
161   if (c.valid() && attribs) *attribs = cap->rights();
162   return c.valid();
163 }
164
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)
169 {
170   Capability *c = get_cap(virt);
171
172   if (EXPECT_FALSE(!c))
173     return Capability(0); // void
174
175   return *c;
176 }
177
178 PUBLIC template< typename SPACE >
179 inline
180 Kobject_iface *
181 Obj_space_phys<SPACE>::lookup_local(Cap_index virt, L4_fpage::Rights *rights)
182 {
183   Entry *c = get_cap(virt);
184
185   if (EXPECT_FALSE(!c))
186     return 0;
187
188   Capability cap = *c;
189
190   if (rights)
191     *rights = L4_fpage::Rights(cap.rights());
192
193   return cap.obj();
194 }
195
196
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())
202 {
203   (void)size;
204   assert (size == Page_order(0));
205   Capability *c = get_cap(virt);
206
207   if (c && c->valid())
208     {
209       if (page_attribs & L4_fpage::Rights::R())
210         c->invalidate();
211       else
212         c->del_rights(page_attribs);
213     }
214
215   return L4_fpage::Rights(0);
216 }
217
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,
222                                 Attr page_attribs)
223 {
224   (void)size;
225   assert (size == Page_order(0));
226
227   Entry *c = get_cap(virt);
228
229   if (!c && !(c = caps_alloc(virt)))
230     return Obj::Insert_err_nomem;
231
232   if (c->valid())
233     {
234       if (c->obj() == phys)
235         {
236           if (EXPECT_FALSE(c->rights() == page_attribs))
237             return Obj::Insert_warn_exists;
238
239           c->add_rights(page_attribs);
240           return Obj::Insert_warn_attrib_upgrade;
241         }
242       else
243         return Obj::Insert_err_exists;
244     }
245
246   Obj::set_entry(virt, c);
247   c->set(phys, page_attribs);
248   return Obj::Insert_ok;
249 }
250
251
252 PUBLIC template< typename SPACE >
253 inline
254 typename Obj_space_phys<SPACE>::V_pfn
255 Obj_space_phys<SPACE>::obj_map_max_address() const
256 {
257   return V_pfn(Slots_per_dir * Obj::Caps_per_page);
258 }
259
260 // ------------------------------------------------------------------------------
261 IMPLEMENTATION [debug]:
262
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); }
267