]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/ppc32/paging-ppc32.cpp
update
[l4.git] / kernel / fiasco / src / kern / ppc32 / paging-ppc32.cpp
1 INTERFACE[ppc32]:
2
3 #include "types.h"
4
5 class PF {};
6
7 //------------------------------------------------------------------------------
8 INTERFACE[ppc32]:
9
10 #include <cassert>
11 #include "types.h"
12 #include "ptab_base.h"
13 #include "kdb_ke.h"
14
15 class Paging {};
16
17 class Pte_base
18 {
19   public:
20     typedef Mword Raw;
21   enum
22   {
23     Super_level   = 0,
24     Htab_entry    = 0x00000400,  ///< is raw entry of htab
25     Valid         = 0x00000004,  ///< Valid
26     Pse_bit       = 0x00000800,  ///< Indicates a super page in hierarch. pgt.
27     Writable      = 0x00000002,  ///< Writable
28     User          = 0x00000001,  ///< User accessible
29     Write_through = 0x00000050,  ///< Write through
30     Cacheable     = 0x00000000,  ///< Cache is enabled
31     Cacheable_mask= 0xffffff87,
32     Noncacheable  = 0x00000020,  ///< Caching is off
33     Referenced    = 0x00000100,  ///< Page was referenced
34     Dirty         = 0x00000080,  ///< Page was modified
35     Pfn           = 0xfffff000,  ///< page frame number
36 //    Cpu_global    = 0x00000100, ///< pinned in the TLB
37 //    L4_global     = 0x00000200, ///< pinned in the TLB
38   };
39
40     Mword addr() const { return _raw & Pfn;}
41     bool is_super_page() const { return _raw & Pse_bit; }
42   protected:
43     Raw _raw;
44 };
45
46 class Pt_entry : public Pte_base
47 {
48 public:
49   Mword leaf() const { return true; }
50   void set(Address p, bool intermed, bool /*present*/, unsigned long attrs = 0)
51   {
52     _raw = (p & Pfn)
53       | (intermed ? (Writable | User) : 0) | attrs;
54     _raw &= intermed ? (Mword)Cacheable_mask : ~0;
55   }
56 };
57
58 class Pd_entry : public Pte_base
59 {
60 public:
61   Mword leaf() const { return false; }
62   void set(Address p, bool intermed, bool present, unsigned long attrs = 0)
63   {
64     _raw = (p & Pfn) | (present ? (Mword)Valid : 0)
65       | (intermed ? (Writable | User) : Pse_bit) | attrs;
66     _raw &= intermed ? (Mword)Cacheable_mask : ~0;
67   }
68 };
69
70 class Pte_htab {
71   public:
72     Pte_htab(Mword, Mword, Mword);
73
74     union {
75       struct {
76         Mword valid : 1; // valid bit
77         Mword vsid  :24; // address-space id
78         Mword h     : 1; // hash-function bit
79         Mword api   : 6; // abbreviated-page index
80         Mword rpn   :20; // physical-page numer
81         Mword zero  : 3; // reserved
82         Mword r     : 1; // referenced bit
83         Mword c     : 1; // changed bit
84         Mword wimg  : 4; // cache controls
85         Mword zero1 : 1; // reserved
86         Mword pp    : 2; // protection bits
87       } pte;
88       struct {
89         Unsigned32 raw0;
90         Unsigned32 raw1;
91       } raw;
92     };
93
94     bool inline valid()
95     { return this->pte.valid; }
96
97     bool inline v_equal(Pte_htab *entry) 
98     { return this->raw.raw0 == entry->raw.raw0; }
99
100     bool inline p_equal(Pte_htab *entry)
101     { return this->raw.raw1 == entry->raw.raw1; }
102
103     Address inline virt()
104     { return this->raw.raw0; }
105
106     Address inline phys()
107     { return this->raw.raw1; }
108 };
109
110 namespace Page
111 {
112   typedef Unsigned32 Attribs;
113   enum Attribs_enum 
114   {
115     KERN_RW      = 0x00000000,
116     USER_RO      = 0x00000001,
117     USER_RW      = 0x00000002,
118     Cache_mask   = 0x00000078,
119     CACHEABLE    = 0x00000000,
120     NONCACHEABLE = 0x00000040,
121     BUFFERED     = 0x00000080, //XXX not sure
122   };
123 };
124
125
126 typedef Ptab::List< Ptab::Traits<Pd_entry, 22, 10, true>,
127                     Ptab::Traits<Pt_entry, 12, 10, true> > Ptab_traits;
128
129 typedef Ptab::Shift<Ptab_traits, Virt_addr::Shift>::List Ptab_traits_vpn;
130 typedef Ptab::Page_addr_wrap<Page_number, Virt_addr::Shift> Ptab_va_vpn;
131
132
133 IMPLEMENTATION[ppc32]:
134
135 #include "config.h"
136 #include "msr.h"
137 #include "lock_guard.h"
138 #include "cpu_lock.h"
139
140
141 /* this functions do nothing on PPC32 architecture */
142 PUBLIC static inline
143 Address
144 Paging::canonize(Address addr)
145 {
146   return addr;
147 }
148
149 PUBLIC static inline
150 Address
151 Paging::decanonize(Address addr)
152 {
153   return addr;
154 }
155
156 //---------------------------------------------------------------------------
157 IMPLEMENT inline 
158 Mword PF::is_translation_error(Mword error)
159 {
160   return !(error & 1 << 30) /* DSISR/SRR1 bit 1 */;
161 }
162
163 IMPLEMENT inline NEEDS["msr.h"]
164 Mword PF::is_usermode_error(Mword error)
165 {
166   return (error & Msr::Msr_pr);
167 }
168
169 IMPLEMENT inline
170 Mword PF::is_read_error(Mword error)
171 {
172   return !(error & (1 << 25)) /* DSISR bit 6*/;
173 }
174
175 IMPLEMENT inline
176 Mword PF::addr_to_msgword0(Address pfa, Mword error)
177 {
178   Mword a = pfa & ~3;
179   if(is_translation_error(error))
180     a |= 1;
181   if(!is_read_error(error))
182     a |= 2;
183   return a;
184 }
185
186 //---------------------------------------------------------------------------
187
188 PUBLIC
189 Pte_base::Pte_base(Mword raw) : _raw(raw) {}
190
191 PUBLIC
192 Pte_base::Pte_base() {}
193
194 PUBLIC inline
195 Pte_base &
196 Pte_base::operator = (Pte_base const &other)
197 {
198   _raw = other.raw();
199   return *this;
200 }
201
202 PUBLIC inline
203 Pte_base &
204 Pte_base::operator = (Mword raw)
205 {
206   _raw = raw;
207   return *this;
208 }
209
210 PUBLIC inline
211 Mword
212 Pte_base::raw() const
213 {
214   return _raw;
215 }
216
217 PUBLIC inline
218 void
219 Pte_base::add_attr(Mword attr)
220 {
221   _raw |= attr;
222 }
223
224 PUBLIC inline
225 void
226 Pte_base::del_attr(Mword attr)
227 {
228   _raw &= ~attr;
229 }
230
231 PUBLIC inline
232 void
233 Pte_base::clear()
234 { _raw = 0; }
235
236 PUBLIC inline
237 int
238 Pte_base::valid() const
239 {
240   return 
241     _raw & Valid || is_htab_entry();
242 }
243
244 PUBLIC inline
245 int
246 Pte_base::writable() const
247 {
248   return _raw & Writable;
249 }
250
251 PUBLIC inline
252 bool
253 Pte_base::is_htab_entry() const
254 {
255   return ((_raw & Htab_entry) && !(_raw & Valid));
256 }
257
258 PUBLIC inline
259 unsigned
260 Pte_base::to_htab_entry(unsigned page_attribs = 0)
261 {
262   _raw |= Htab_entry;
263   _raw &= ~Valid;
264   return page_attribs & ~Valid;
265 }
266
267 PUBLIC inline
268 bool
269 Pte_base::is_htab_ptr() const
270 {
271   return (_raw & Valid);
272 }
273
274 PUBLIC inline
275 void
276 Pte_base::to_htab_ptr()
277 {
278   _raw |= Valid;
279 }
280
281 PUBLIC inline
282 Address
283 Pt_entry::pfn() const
284 {
285   return _raw & Pfn;
286 }
287
288 //------------------------------------------------------------------------------
289 /*
290  * Hash Page-table entries
291  */
292 IMPLEMENT inline NEEDS[Pte_htab::api]
293 Pte_htab::Pte_htab(Address pa, Address ea, Address vsid)
294 {
295   this->raw.raw0      = 0;
296   this->pte.valid     = 1;
297   this->pte.vsid      = vsid;
298   this->pte.api       = api(ea);
299   this->raw.raw1      = pa;
300 }
301
302 PRIVATE static inline
303 Address
304 Pte_htab::api(Address ea)
305 {
306   //bits 4-9
307   return (ea >> 22) & 0x3f;
308 }
309
310 PRIVATE inline
311 Address
312 Pte_htab::api_reverse()
313 {
314   return this->pte.api << 22;
315 }
316
317 PUBLIC inline NEEDS[Pte_htab::api_reverse, "config.h"]
318 Address
319 Pte_htab::pte_to_ea()
320 {
321   Address pteg = (Address)this;
322   //if secondary hash
323   if(this->pte.h)
324     pteg = ~pteg;
325
326   Address va = 0x3ff /*10bit*/ & (this->pte.vsid ^ (pteg >> 6));
327   va <<= Config::PAGE_SHIFT;
328   va |= this->api_reverse();
329   va |= (this->pte.vsid & 0xf) << 28;
330   return va;
331 }
332
333
334 PUBLIC static inline
335 Pte_htab * 
336 Pte_htab::addr_to_pte(Address pte_addr)
337 {
338   return reinterpret_cast<Pte_htab*>(pte_addr & ~Pte_base::Valid);
339 }
340
341 PUBLIC static inline
342 Address
343 Pte_htab::pte_to_addr(Pte_base *e)
344 {
345   Address raw;
346
347   if(e->is_htab_entry())
348     raw = e->raw();
349   else
350     {
351       Pte_htab *pte_phys = addr_to_pte(e->raw());
352       raw = pte_phys->phys();
353     }
354
355   return raw;
356 }
357
358 PUBLIC static
359 bool
360 Pte_htab::pte_lookup(Pte_base *e, Address *phys = 0, 
361                      unsigned *page_attribs = 0)
362 {
363   auto guard = lock_guard(cpu_lock);
364
365   Address raw;
366
367   if(e->is_htab_entry())
368     {
369       raw = e->raw();
370     }
371   else
372     {
373       Pte_htab *pte = addr_to_pte(e->raw());
374       raw = pte->phys();
375
376       if(!pte->valid())
377         return false;
378     }
379
380   assert(raw);
381
382   if(phys) *phys = raw & (~0UL << Config::PAGE_SHIFT);
383   if(page_attribs) *page_attribs = raw;
384
385   return true;
386 }