11 //-------------------------------------------------------------------------------------
12 INTERFACE [arm && !arm_lpae]:
24 Pte_ptr(void *p, unsigned char level) : pte((Mword*)p), level(level) {}
26 bool is_valid() const { return *pte & 3; }
27 void clear() { *pte = 0; }
32 case 0: return (*pte & 3) == 2;
37 Mword next_level() const
39 // 1KB second level tables
40 return cxx::mask_lsb(*pte, 10);
43 void set_next_level(Mword phys)
45 write_now(pte, phys | 1);
48 unsigned char page_order() const
53 { // no tiny pages !!!
61 Mword page_addr() const
62 { return cxx::mask_lsb(*pte, page_order()); }
69 { public: enum { Ttbcr_bits = 0, Mair0_bits = 0 }; };
71 //-----------------------------------------------------------------------------
72 INTERFACE [arm && arm_lpae]:
77 typedef Unsigned64 Entry;
85 Pte_ptr(void *p, unsigned char level) : pte((Unsigned64*)p), level(level) {}
87 bool is_valid() const { return *pte & 1; }
88 void clear() { *pte = 0; }
93 return (*pte & 3) == 1;
96 Unsigned64 next_level() const
98 // 1KB second level tables
99 return cxx::get_lsb(cxx::mask_lsb(*pte, 12), 40);
102 void set_next_level(Unsigned64 phys)
104 write_now(pte, phys | 3);
107 Mword page_addr() const
108 { return cxx::mask_lsb(*pte, page_order()); }
119 Ttbcr_bits = (1 << 31) // EAE
123 Mair0_bits = 0x00ff4400
127 //---------------------------------------------------------------------------
128 IMPLEMENTATION [arm && arm_lpae]:
132 Pte_ptr::page_order() const
133 { return Pdir::page_order_for_level(level); }
136 //-----------------------------------------------------------------------------
137 INTERFACE [arm && armv5]:
144 typedef Unsigned32 Attribs;
149 NONCACHEABLE = 0x00, ///< Caching is off
150 CACHEABLE = 0x0c, ///< Cache is enabled
152 // The next are ARM specific
153 WRITETHROUGH = 0x08, ///< Write through cached
154 BUFFERED = 0x04, ///< Write buffer enabled
157 enum Default_entries : Mword
159 Section_cachable = 0x40e,
160 Section_no_cache = 0x402,
166 EXTENSION class Pte_ptr
168 // we have virtually tagged caches so need a cache flush before enabling
170 enum { Need_cache_clean = false }; // we have virtuially tagged caches
175 //---------------------------------------------------------------------------
176 INTERFACE [arm && armv6plus && (mpcore || armca9)]:
183 Section_shared = 1UL << 16,
184 Mp_set_shared = 0x400,
188 //---------------------------------------------------------------------------
189 INTERFACE [arm && armv6plus && !(mpcore || armca9)]:
201 //---------------------------------------------------------------------------
202 INTERFACE [arm && (armv5 || (armv6 && !mpcore))]:
205 { public: enum { Ttbr_bits = 0 }; };
207 //---------------------------------------------------------------------------
208 INTERFACE [arm && mpcore]:
211 { public: enum { Ttbr_bits = 0xa }; };
213 //---------------------------------------------------------------------------
214 INTERFACE [arm && armca9 && !arm_lpae]:
216 // S Sharable | RGN = Outer WB-WA | IRGN = Inner WB-WA | NOS
218 { public: enum { Ttbr_bits = 0x6a }; };
220 //---------------------------------------------------------------------------
221 INTERFACE [arm && armca9 && arm_lpae]:
224 { public: enum { Ttbr_bits = 0 }; };
226 //---------------------------------------------------------------------------
227 INTERFACE [arm && armca8]: // armv7 w/o multiprocessing ext.
230 { public: enum { Ttbr_bits = 0x2b }; };
232 //----------------------------------------------------------------------------
233 INTERFACE [arm && (armv6 || armv7) && !arm_lpae]:
243 NONCACHEABLE = 0x000, ///< Caching is off
244 CACHEABLE = 0x144, ///< Cache is enabled
246 // The next are ARM specific
247 WRITETHROUGH = 0x08, ///< Write through cached
248 BUFFERED = 0x40, ///< Write buffer enabled -- Normal, non-cached
251 enum Default_entries : Mword
253 Section_cachable = 0x5406 | Section_shared,
254 Section_no_cache = 0x0402 | Section_shared,
255 Section_local = (1 << 17),
260 //-----------------------------------------------------------------------------
261 INTERFACE [arm && !arm_lpae]:
263 #include "ptab_base.h"
265 typedef Ptab::List< Ptab::Traits< Unsigned32, 20, 12, true>,
266 Ptab::Traits< Unsigned32, 12, 8, true> > Ptab_traits;
268 typedef Ptab::Shift<Ptab_traits, Virt_addr::Shift>::List Ptab_traits_vpn;
269 typedef Ptab::Page_addr_wrap<Page_number, Virt_addr::Shift> Ptab_va_vpn;
271 //-----------------------------------------------------------------------------
272 INTERFACE [arm && arm_lpae]:
274 #include "ptab_base.h"
283 NONCACHEABLE = 0x000, ///< Caching is off
284 CACHEABLE = 0x008, ///< Cache is enabled
285 BUFFERED = 0x004, ///< Write buffer enabled -- Normal, non-cached
289 typedef Ptab::Tupel< Ptab::Traits< Unsigned64, 30, 2, true>,
290 Ptab::Traits< Unsigned64, 21, 9, true>,
291 Ptab::Traits< Unsigned64, 12, 9, true> >::List Ptab_traits;
293 typedef Ptab::Shift<Ptab_traits, Virt_addr::Shift>::List Ptab_traits_vpn;
294 typedef Ptab::Page_addr_wrap<Page_number, Virt_addr::Shift> Ptab_va_vpn;
296 //---------------------------------------------------------------------------
297 IMPLEMENTATION [arm && armv5]:
301 Pte_ptr::need_cache_write_back(bool current_pt)
302 { return current_pt; }
306 Pte_ptr::write_back_if(bool current_pt, Mword /*asid*/ = 0)
309 Mem_unit::clean_dcache(pte);
314 Pte_ptr::write_back(void *start, void *end)
315 { Mem_unit::clean_dcache(start, end); }
317 //---------------------------------------------------------------------------
318 IMPLEMENTATION [arm && armv6]:
322 Pte_ptr::need_cache_write_back(bool)
327 Pte_ptr::write_back_if(bool, Mword asid = Mem_unit::Asid_invalid)
329 Mem_unit::clean_dcache(pte);
330 if (asid != Mem_unit::Asid_invalid)
331 Mem_unit::tlb_flush(asid);
336 Pte_ptr::write_back(void *start, void *end)
337 { Mem_unit::clean_dcache(start, end); }
339 //---------------------------------------------------------------------------
340 IMPLEMENTATION [arm && armv7]:
344 Pte_ptr::need_cache_write_back(bool)
349 Pte_ptr::write_back_if(bool, Mword asid = Mem_unit::Asid_invalid)
351 if (asid != Mem_unit::Asid_invalid)
352 Mem_unit::tlb_flush(asid);
357 Pte_ptr::write_back(void *, void *)
361 //---------------------------------------------------------------------------
362 IMPLEMENTATION [arm && armv5]:
365 Mword PF::is_alignment_error(Mword error)
366 { return (error & 0xf0000d) == 0x400001; }
370 Pte_ptr::_attribs_mask() const
373 return ~Entry(0x00000c0c);
375 return ~Entry(0x00000ffc);
380 Pte_ptr::_attribs(Page::Attr attr) const
382 static const unsigned short perms[] = {
383 0x1 << 10, // 0000: none, hmmm
384 0x1 << 10, // 000X: kernel rw (there is no ro)
404 typedef Page::Type T;
405 typedef Page::Kern K;
407 if (attr.type == T::Normal()) r |= Page::CACHEABLE;
408 if (attr.type == T::Buffered()) r |= Page::BUFFERED;
409 if (attr.type == T::Uncached()) r |= Page::NONCACHEABLE;
411 return r | perms[cxx::int_value<L4_fpage::Rights>(attr.rights)];
414 Mword p = perms[cxx::int_value<L4_fpage::Rights>(attr.rights)];
423 Pte_ptr::attribs() const
425 auto r = access_once(pte);
429 typedef L4_fpage::Rights R;
430 typedef Page::Type T;
435 case 0x000: rights = R::URX(); break;
437 case 0x400: rights = R::RWX(); break;
438 case 0xc00: rights = R::URWX(); break;
445 case Page::CACHEABLE: type = T::Normal(); break;
446 case Page::BUFFERED: type = T::Buffered(); break;
447 case Page::NONCACHEABLE: type = T::Uncached(); break;
449 return Page::Attr(rights, type);
452 PUBLIC inline NEEDS[Pte_ptr::_attribs, Pte_ptr::_attribs_mask]
454 Pte_ptr::set_attribs(Page::Attr attr)
456 Mword p = access_once(pte);
457 p = (p & _attribs_mask()) | _attribs(attr);
461 PUBLIC inline NEEDS[Pte_ptr::_attribs]
463 Pte_ptr::create_page(Phys_mem_addr addr, Page::Attr attr)
465 Mword p = 2 | _attribs(attr) | cxx::int_value<Phys_mem_addr>(addr);
471 Pte_ptr::add_attribs(Page::Attr attr)
473 typedef L4_fpage::Rights R;
475 if (attr.rights & R::W())
477 auto p = access_once(pte);
478 if ((p & 0xc00) == 0x000)
480 p |= level == 0 ? 0xc00 : 0xff0;
490 Pte_ptr::access_flags() const
491 { return Page::Rights(0); }
495 Pte_ptr::del_rights(L4_fpage::Rights r)
497 if (!(r & L4_fpage::Rights::W()))
500 auto p = access_once(pte);
501 if ((p & 0xc00) == 0xc00)
503 p &= (level == 0) ? ~Mword(0xc00) : ~Mword(0xff0);
509 //---------------------------------------------------------------------------
510 IMPLEMENTATION [arm && !arm_lpae && (armv6 || armv7)]:
514 Pte_ptr::_attribs_mask() const
517 return ~Entry(0x0000881c);
519 return ~Entry(0x0000022d);
524 Pte_ptr::_attribs(Page::Attr attr) const
526 typedef L4_fpage::Rights R;
527 typedef Page::Type T;
528 typedef Page::Kern K;
530 Mword lower = Page::Mp_set_shared;
531 if (attr.type == T::Normal()) lower |= Page::CACHEABLE;
532 if (attr.type == T::Buffered()) lower |= Page::BUFFERED;
533 if (attr.type == T::Uncached()) lower |= Page::NONCACHEABLE;
534 Mword upper = lower & ~0x0f;
537 if (!(attr.kern & K::Global()))
540 if (!(attr.rights & R::W()))
543 if (attr.rights & R::U())
546 if (!(attr.rights & R::X()))
555 return lower | (upper << 6);
557 return lower | upper;
562 Pte_ptr::attribs() const
564 typedef L4_fpage::Rights R;
565 typedef Page::Type T;
566 typedef Page::Kern K;
568 auto c = access_once(pte);
577 c = (c & 0x0f) | ((c >> 6) & 0xfff0);
579 else if (!(c & 0x01))
588 switch (c & Page::Cache_mask)
591 case Page::CACHEABLE: type = T::Normal(); break;
592 case Page::BUFFERED: type = T::Buffered(); break;
593 case Page::NONCACHEABLE: type = T::Uncached(); break;
600 return Page::Attr(rights, type, k);
603 PUBLIC inline NEEDS[Pte_ptr::_attribs]
605 Pte_ptr::create_page(Phys_mem_addr addr, Page::Attr attr)
607 Mword p = 2 | _attribs(attr) | cxx::int_value<Phys_mem_addr>(addr);
618 Pte_ptr::add_attribs(Page::Attr attr)
620 typedef L4_fpage::Rights R;
623 if (attr.rights & R::W())
631 if (attr.rights & R::X())
640 auto p = access_once(pte);
653 Pte_ptr::access_flags() const
654 { return Page::Rights(0); }
658 Pte_ptr::del_rights(L4_fpage::Rights r)
661 if (r & L4_fpage::Rights::W())
669 if (r & L4_fpage::Rights::X())
680 auto p = access_once(pte);
681 if ((p & n_attr) != n_attr)
689 //---------------------------------------------------------------------------
690 IMPLEMENTATION [arm && arm_lpae && (armv6 || armv7)]:
694 Pte_ptr::_attribs_mask() const
695 { return ~Entry(0x00400000000008dc); }
699 Pte_ptr::_attribs(Page::Attr attr) const
701 typedef L4_fpage::Rights R;
702 typedef Page::Type T;
703 typedef Page::Kern K;
705 Entry lower = 0x300; // inner sharable
706 if (attr.type == T::Normal()) lower |= Page::CACHEABLE;
707 if (attr.type == T::Buffered()) lower |= Page::BUFFERED;
708 if (attr.type == T::Uncached()) lower |= Page::NONCACHEABLE;
710 if (!(attr.kern & K::Global()))
713 if (!(attr.rights & R::W()))
716 if (attr.rights & R::U())
719 if (!(attr.rights & R::X()))
720 lower |= 0x0040000000000000;
727 Pte_ptr::attribs() const
729 typedef L4_fpage::Rights R;
730 typedef Page::Type T;
731 typedef Page::Kern K;
733 auto c = access_once(pte);
741 if (!(c & 0x0040000000000000))
745 switch (c & Page::Cache_mask)
748 case Page::CACHEABLE: type = T::Normal(); break;
749 case Page::BUFFERED: type = T::Buffered(); break;
750 case Page::NONCACHEABLE: type = T::Uncached(); break;
757 return Page::Attr(rights, type, k);
760 PUBLIC inline NEEDS[Pte_ptr::_attribs]
762 Pte_ptr::create_page(Phys_mem_addr addr, Page::Attr attr)
764 Entry p = 0x400 | _attribs(attr) | cxx::int_value<Phys_mem_addr>(addr);
765 if (level == Pdir::Depth)
775 Pte_ptr::add_attribs(Page::Attr attr)
777 typedef L4_fpage::Rights R;
781 if (attr.rights & R::W())
784 if (attr.rights & R::X())
785 n_attr |= 0x0040000000000000;
790 auto p = access_once(pte);
802 Pte_ptr::access_flags() const
803 { return Page::Rights(0); }
807 Pte_ptr::del_rights(L4_fpage::Rights r)
810 if (r & L4_fpage::Rights::W())
813 if (r & L4_fpage::Rights::X())
814 n_attr |= 0x0040000000000000;
819 auto p = access_once(pte);
820 if ((p & n_attr) != n_attr)
830 //---------------------------------------------------------------------------
831 IMPLEMENTATION [arm && (armv6 || armv7) && !arm_lpae]:
834 Mword PF::is_alignment_error(Mword error)
835 { return (error & 0xf0040f) == 0x400001; }
837 //---------------------------------------------------------------------------
838 IMPLEMENTATION [arm && (armv6 || armv7) && arm_lpae]:
841 Mword PF::is_alignment_error(Mword error)
842 { return (error & 0xf0003f) == 0x400021; }
844 //---------------------------------------------------------------------------
845 IMPLEMENTATION [arm && (armv6 || armv7)]:
847 PUBLIC inline NEEDS[Pte_ptr::_attribs, Pte_ptr::_attribs_mask]
849 Pte_ptr::set_attribs(Page::Attr attr)
851 Entry p = access_once(pte);
852 p = (p & _attribs_mask()) | _attribs(attr);
858 //---------------------------------------------------------------------------
859 IMPLEMENTATION [arm && !arm_lpae]:
862 Mword PF::is_translation_error( Mword error )
864 return (error & 0x0d/*FSR_STATUS_MASK*/) == 0x05/*FSR_TRANSL*/;
867 //---------------------------------------------------------------------------
868 IMPLEMENTATION [arm && arm_lpae]:
871 Mword PF::is_translation_error(Mword error)
873 return (error & 0x3c) == 0x04;
876 //---------------------------------------------------------------------------
877 IMPLEMENTATION [arm]:
880 Mword PF::is_usermode_error( Mword error )
882 return (error & 0x00010000/*PF_USERMODE*/);
886 Mword PF::is_read_error( Mword error )
888 return !(error & (1UL << 11));
892 Mword PF::addr_to_msgword0( Address pfa, Mword error )
895 if(is_translation_error( error ))
897 if(!is_read_error(error))