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