]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/obj_space-phys.cpp
update
[l4.git] / kernel / fiasco / src / kern / obj_space-phys.cpp
1 INTERFACE:
2
3 #include "assert_opt.h"
4
5 EXTENSION class Generic_obj_space
6 {
7 private:
8   enum
9   {
10     Slots_per_dir = Config::PAGE_SIZE / sizeof(void*)
11   };
12
13   struct Cap_table { Entry e[Caps_per_page]; };
14   struct Cap_dir   { Cap_table *d[Slots_per_dir]; };
15   Cap_dir *_dir;
16
17   Ram_quota *ram_quota() const
18   {
19     assert_opt (this);
20     return static_cast<SPACE const *>(this)->ram_quota();
21   }
22 };
23
24
25 //----------------------------------------------------------------------------
26 IMPLEMENTATION:
27
28 #include <cstring>
29 #include <cassert>
30
31 #include "atomic.h"
32 #include "config.h"
33 #include "cpu.h"
34 #include "kdb_ke.h"
35 #include "kmem_alloc.h"
36 #include "mem.h"
37 #include "mem_layout.h"
38 #include "ram_quota.h"
39 #include "static_assert.h"
40
41
42 PUBLIC template< typename SPACE >
43 inline NEEDS["static_assert.h"]
44 Generic_obj_space<SPACE>::Generic_obj_space()
45 {
46   static_assert(sizeof(Cap_dir) == Config::PAGE_SIZE, "cap_dir size mismatch");
47   _dir = (Cap_dir*)Kmem_alloc::allocator()->q_unaligned_alloc(ram_quota(), Config::PAGE_SIZE);
48   if (_dir)
49     Mem::memset_mwords(_dir, 0, Config::PAGE_SIZE / sizeof(Mword));
50 }
51
52 PRIVATE template< typename SPACE >
53 typename Generic_obj_space<SPACE>::Entry *
54 Generic_obj_space<SPACE>::get_cap(Address index)
55 {
56   if (EXPECT_FALSE(!_dir))
57     return 0;
58
59   unsigned d_idx = index / Caps_per_page;
60   if (EXPECT_FALSE(d_idx >= Slots_per_dir))
61     return 0;
62
63   Cap_table *tab = _dir->d[d_idx];
64
65   if (EXPECT_FALSE(!tab))
66     return 0;
67
68   unsigned offs  = index % Caps_per_page;
69   return &tab->e[offs];
70 }
71
72 PRIVATE template< typename SPACE >
73 typename Generic_obj_space<SPACE>::Entry *
74 Generic_obj_space<SPACE>::caps_alloc(Address virt)
75 {
76   static_assert(sizeof(Cap_table) == Config::PAGE_SIZE, "cap table size mismatch");
77   unsigned d_idx = virt / Caps_per_page;
78   if (EXPECT_FALSE(d_idx >= Slots_per_dir))
79     return 0;
80
81   void *mem = Kmem_alloc::allocator()->q_unaligned_alloc(ram_quota(), Config::PAGE_SIZE);
82
83   if (!mem)
84     return 0;
85
86   add_dbg_info(mem, this, virt);
87
88   Mem::memset_mwords(mem, 0, Config::PAGE_SIZE / sizeof(Mword));
89
90
91
92   Cap_table *tab = _dir->d[d_idx] = (Cap_table*)mem;
93
94   return &tab->e[virt % Caps_per_page];
95 }
96
97 PRIVATE template< typename SPACE >
98 void
99 Generic_obj_space<SPACE>::caps_free()
100
101   if (!_dir)
102     return;
103
104   Cap_dir *d = _dir;
105   _dir = 0;
106
107   Kmem_alloc *a = Kmem_alloc::allocator();
108   for (unsigned i = 0; i < Slots_per_dir; ++i)
109     {
110       if (!d->d[i])
111         continue;
112
113       remove_dbg_info(d->d[i]);
114       a->q_unaligned_free(ram_quota(), Config::PAGE_SIZE, d->d[i]);
115     }
116
117   a->q_unaligned_free(ram_quota(), Config::PAGE_SIZE, d);
118 }
119
120 //
121 // Utilities for map<Generic_obj_space> and unmap<Generic_obj_space>
122 //
123
124 PUBLIC template< typename SPACE >
125 inline NEEDS[Generic_obj_space::get_cap]
126 bool
127 Generic_obj_space<SPACE>::v_lookup(Addr const &virt, Phys_addr *phys = 0,
128                                    Size *size = 0, unsigned *attribs = 0)
129 {
130   if (size) *size = Size::create(1);
131   Entry *cap = get_cap(virt.value());
132
133   if (EXPECT_FALSE(!cap))
134     {
135       if (size) *size = Size::create(Caps_per_page);
136       return false;
137     }
138
139   Capability c = *cap;
140
141   Obj::set_entry(virt, cap);
142   if (phys) *phys = c.obj();
143   if (c.valid() && attribs) *attribs = cap->rights();
144   return c.valid();
145 }
146
147 PUBLIC template< typename SPACE >
148 inline NEEDS [Generic_obj_space::get_cap]
149 typename Generic_obj_space<SPACE>::Capability
150 Generic_obj_space<SPACE>::lookup(Address virt)
151 {
152   Capability *c = get_cap(virt);
153
154   if (EXPECT_FALSE(!c))
155     return Capability(0); // void
156
157   return *c;
158 }
159
160 PUBLIC template< typename SPACE >
161 inline
162 Kobject_iface *
163 Generic_obj_space<SPACE>::lookup_local(Address virt, unsigned char *rights = 0)
164 {
165   Entry *c = get_cap(virt);
166
167   if (EXPECT_FALSE(!c))
168     return 0;
169
170   Capability cap = *c;
171
172   if (rights)
173     *rights = cap.rights();
174
175   return cap.obj();
176 }
177
178
179 PUBLIC template< typename SPACE >
180 inline NEEDS[<cassert>, Generic_obj_space::get_cap]
181 unsigned long
182 Generic_obj_space<SPACE>::v_delete(Page_number virt, Size size,
183                                    unsigned long page_attribs = L4_fpage::RWX)
184 {
185   (void)size;
186   assert (size.value() == 1);
187   Capability *c = get_cap(virt.value());
188
189   if (c && c->valid())
190     {
191       if (page_attribs & L4_fpage::R)
192         c->invalidate();
193       else
194         c->del_rights(page_attribs & L4_fpage::WX);
195     }
196
197   return 0;
198 }
199
200 PUBLIC template< typename SPACE >
201 inline NEEDS[Generic_obj_space::caps_alloc, "kdb_ke.h"]
202 typename Generic_obj_space<SPACE>::Status
203 Generic_obj_space<SPACE>::v_insert(Phys_addr phys, Addr const &virt, Size size,
204                                    unsigned char page_attribs)
205 {
206   (void)size;
207   assert (size.value() == 1);
208
209   Entry *c = get_cap(virt.value());
210
211   if (!c && !(c = caps_alloc(virt.value())))
212     return Insert_err_nomem;
213
214   assert (size.value() == 1);
215
216   if (c->valid())
217     {
218       if (c->obj() == phys)
219         {
220           if (EXPECT_FALSE(c->rights() == page_attribs))
221             return Insert_warn_exists;
222
223           c->add_rights(page_attribs);
224           return Insert_warn_attrib_upgrade;
225         }
226       else
227         return Insert_err_exists;
228     }
229
230   Obj::set_entry(virt, c);
231   c->set(phys, page_attribs);
232   return Insert_ok;
233 }
234
235
236 PUBLIC template< typename SPACE >
237 static inline
238 typename Generic_obj_space<SPACE>::Addr
239 Generic_obj_space<SPACE>::map_max_address()
240 {
241   return Addr(Slots_per_dir * Caps_per_page);
242 }
243