]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/space.cpp
update
[l4.git] / kernel / fiasco / src / kern / space.cpp
1 INTERFACE [!io]:
2
3 class Io_space;
4
5 //--------------------------------------------------------------------------
6 INTERFACE [io]:
7
8 #include "config.h"
9 #include "io_space.h"
10 #include "l4_types.h"
11
12 class Space;
13
14 /** Global definition of Io_space for map_util stuff. */
15 typedef Generic_io_space<Space> Io_space;
16
17 //--------------------------------------------------------------------------
18 INTERFACE:
19
20 #include "mem_space.h"
21 #include "member_offs.h"
22 #include "obj_space.h"
23 #include "spin_lock.h"
24 #include "ref_obj.h"
25 #include "slab_cache_anon.h"
26
27 class Ram_quota;
28 class Context;
29 class Kobject;
30
31 class Space;
32
33 typedef Generic_obj_space<Space> Obj_space;
34
35 class Space : public Ref_cnt_obj
36 {
37   MEMBER_OFFSET();
38   friend class Jdb_space;
39
40 public:
41
42   struct Default_factory
43   {
44     /** Create a usual Mem_space object. */
45     template< typename A1 >
46     static void create(Mem_space *v, A1 a1)
47     { new (v) Mem_space(a1); }
48
49     /** Create a kernel Mem_space object. */
50     template< typename A1, typename A2 >
51     static void create(Mem_space *v, A1 a1, A2 a2)
52     { new (v) Mem_space(a1, a2); }
53
54     template< typename S >
55     static void create(S *v)
56     { new (v) S(); }
57   };
58
59   /** The interface for Obj_space to get the surrounding Space. */
60   static Space *space(Obj_space const *os)
61   {
62     return reinterpret_cast<Space*>(Address(os) - Address(&reinterpret_cast<Space*>(32)->_obj_space) + 32);
63   }
64
65   enum State
66   { // we must use values with the two lest significant bits == 0
67     Starting    = 0x00,
68     Ready       = 0x08,
69     In_deletion = 0x10
70   };
71
72   struct Ku_mem
73   {
74     Ku_mem *next;
75     User<void>::Ptr u_addr;
76     void *k_addr;
77     unsigned size;
78
79     static slab_cache_anon *a;
80
81     Ku_mem() : next(0) {}
82
83     void *operator new (size_t, Ram_quota *q) throw()
84     { return a->q_alloc(q); }
85
86     void free(Ram_quota *q) throw()
87     { a->q_free(q, this); }
88
89     template<typename T>
90     T *kern_addr(Smart_ptr<T, Simple_ptr_policy, User_ptr_discr> ua) const
91     {
92       typedef Address A;
93       return (T*)((A)ua.get() - (A)u_addr.get() + (A)k_addr);
94     }
95   };
96
97 private:
98   template<typename SPACE>
99   class Space_container
100   {
101   public:
102     char __attribute__((aligned(__alignof__(Mword)))) s[sizeof(SPACE)];
103
104     template< typename SF >
105     Space_container(SF const &sf)
106     { sf.create(get()); }
107
108     template< typename SF, typename A1 >
109     Space_container(SF const &sf, A1 a1)
110     { sf.create(get(), a1); }
111
112     template< typename SF, typename A1, typename A2 >
113     Space_container(SF const &sf, A1 a1, A2 a2)
114     { sf.create(get(), a1, a2); }
115
116     ~Space_container()
117     { delete get(); }
118
119     SPACE *get()
120     { return reinterpret_cast<SPACE*>(s); }
121
122     SPACE const *get() const
123     { return reinterpret_cast<SPACE const*>(s); }
124   };
125
126   typedef Space_container<Mem_space> Mem_space_container;
127
128   // DATA
129   Mem_space_container _mem_space;
130   Obj_space _obj_space;
131
132   void switchin_ldt() const;
133
134 protected:
135   Ku_mem *_ku_mem;
136 };
137
138
139 //---------------------------------------------------------------------------
140 IMPLEMENTATION:
141
142 #include "atomic.h"
143 #include "kdb_ke.h"
144 #include "lock_guard.h"
145 #include "config.h"
146 #include "globalconfig.h"
147 #include "l4_types.h"
148
149 //
150 // class Space
151 //
152
153
154
155 /**
156  * UTCB area functions.
157  */
158 //@{
159
160
161 /**
162  * Get size of UTCB area in bytes.
163  *
164  * @return the size of the UTCB area in bytes.
165  */
166 PUBLIC inline
167 unsigned long
168 Space::utcb_area_size() const
169 { return _ku_mem->size; }
170
171 PUBLIC inline
172 Address
173 Space::kern_utcb_area() const
174 { return (Address)_ku_mem->k_addr; }
175
176 /**
177  * Get the start of the UTCB area in the user address-space.
178  *
179  * @return the start address of the UTCB area in trhe user address-space.
180  */
181 PUBLIC inline
182 Address
183 Space::user_utcb_area() const
184 { return (Address)_ku_mem->u_addr.get(); }
185
186
187 //@}
188
189 PUBLIC
190 Space::Ku_mem const *
191 Space::find_ku_mem(User<void>::Ptr p, unsigned size)
192 {
193   Address const pa = (Address)p.get();
194
195   // alignment check
196   if (EXPECT_FALSE(pa & (sizeof(double) - 1)))
197     return 0;
198
199   // overflow check
200   if (EXPECT_FALSE(pa + size < pa))
201     return 0;
202
203   for (Ku_mem const *f = _ku_mem; f; f = f->next)
204     {
205       Address const a = (Address)f->u_addr.get();
206       if (a <= pa && (a + f->size) >= (pa + size))
207         return f;
208     }
209
210   return 0;
211 }
212
213 PUBLIC virtual
214 Space::~Space()
215 {}
216
217
218
219 /** Constructor.  Creates a new address space and registers it with
220   * Space_index.
221   *
222   * Registration may fail (if a task with the given number already
223   * exists, or if another thread creates an address space for the same
224   * task number concurrently).  In this case, the newly-created
225   * address space should be deleted again.
226   *
227   * @param number Task number of the new address space
228   */
229 PUBLIC template< typename SPACE_FACTORY >
230 inline
231 Space::Space(SPACE_FACTORY const &sf, Ram_quota *q)
232   : _mem_space(sf, q), _ku_mem(0)
233 #ifdef CONFIG_IO_PROT
234     , _io_space(sf)
235 #endif
236 {}
237
238
239 PROTECTED template<typename SPACE_FACTORY>
240 Space::Space(SPACE_FACTORY const &sf, Ram_quota *q, Mem_space::Dir_type* pdir)
241   : _mem_space(sf, q, pdir)
242 #ifdef CONFIG_IO_PROT
243     , _io_space(sf)
244 #endif
245 {}
246
247
248 PUBLIC inline
249 Ram_quota *
250 Space::ram_quota() const
251 { return _mem_space.get()->ram_quota(); }
252
253 PROTECTED
254 void
255 Space::reset_dirty()
256 {
257   _mem_space.get()->reset_dirty();
258 }
259
260
261 PUBLIC inline
262 void
263 Space::switchin_context(Space *from)
264 {
265   // XXX: check when activating unbound thread for drq-handling
266   // better solution: set freshly created (unbound) threads to kernel_space
267   // so that we do not have to make the following 'if':
268   if (this)
269     {
270       _mem_space.get()->switchin_context(from->mem_space());
271
272       if (this != from)
273         switchin_ldt();
274     }
275 }
276
277
278 // Mem_space utilities
279
280 // Return memory space.
281 PUBLIC inline
282 Mem_space const *
283 Space::mem_space() const
284 { return _mem_space.get(); }
285
286 PUBLIC inline
287 Mem_space*
288 Space::mem_space()
289 {
290   return _mem_space.get();
291 }
292
293 PUBLIC static inline
294 bool
295 Space::is_user_memory(Address address, Mword len)
296 {
297   return    address < Mem_layout::User_max
298          && address < address + len // prevent overflow
299          && address + len <= Mem_layout::User_max;
300 }
301
302 PUBLIC inline
303 bool
304 Space::lookup_space(Mem_space** out_space)
305 {
306   *out_space = mem_space();
307   return true;
308 }
309
310 PUBLIC inline
311 Obj_space*
312 Space::obj_space()
313 {
314   return &_obj_space;
315 }
316
317 PUBLIC inline
318 bool
319 Space::lookup_space(Obj_space** out_cap_space)
320 {
321   *out_cap_space = obj_space();
322   return true;
323 }
324
325 // ------------------------------------------------------------------------
326 IMPLEMENTATION [!io && !ux]:
327
328 // Is this task a privileged one?
329 PUBLIC static inline
330 bool
331 Space::has_io_privileges()
332 { return true; }