3 #ifndef _ARCH_PAGETABLE_H
4 #define _ARCH_PAGETABLE_H
6 #include <lowlevel/misc.h>
7 #include <lowlevel/atomic.h>
11 typedef ulong PhysAddr, VirtAddr;
16 PhysAddr Writeable:1; // Low-level write access:
17 // equivalent to PermWrite && !FaultOnWrite
19 PhysAddr WriteThrough:1;
20 PhysAddr CacheDisable:1;
23 PhysAddr PageAttrTable:1;
25 PhysAddr FaultOnWrite:1;
26 PhysAddr PermWrite:1; // High-level permission-based write access
27 PhysAddr AddressOnly:1;
33 PTE(PhysAddr init) : raw(init)
46 static uint addr_to_offset(VirtAddr addr, int shift)
48 int pages_per_table = page_size / sizeof(PhysAddr);
49 return (addr >> shift) & (pages_per_table - 1);
52 PhysAddr pte_to_addr()
54 return raw & 0xfffff000;
57 static PTE addr_to_pte(PhysAddr phys)
59 return phys & 0xfffff000;
65 return static_cast<PTE *>(phys_to_kvirt(pte_to_addr()));
69 static DirPTE set_table(void *addr)
71 return addr_to_pte(kvirt_to_phys(addr)) | 7;
74 static void flags_to_pte(Mem::PTEFlags flagsin,
82 maskout.Valid = maskin.Valid;
83 maskout.FaultOnWrite = maskin.FaultOnWrite;
84 maskout.AddressOnly = maskin.AddressOnly;
85 maskout.CacheDisable = maskin.Uncached;
87 flagsout.Valid = flagsin.Valid;
88 flagsout.FaultOnWrite = flagsin.FaultOnWrite;
89 flagsout.AddressOnly = flagsin.AddressOnly;
90 flagsout.CacheDisable = flagsin.Uncached;
92 if (maskin.Writeable) {
93 maskout.Writeable = 1;
94 maskout.PermWrite = 1;
95 flagsout.Writeable = flagsin.Writeable;
96 flagsout.PermWrite = flagsin.Writeable;
98 // This must be done here if both mask bits are set,
99 // as we may not be going through set_flags in that case.
101 if (maskin.FaultOnWrite)
102 flagsout.Writeable &= !flagsout.FaultOnWrite;
107 flagsout.User = flagsin.User;
111 PTE set_flags(PTE mask, PTE flags)
117 new_pte = (raw & ~mask) | flags;
118 new_pte.Writeable &= !new_pte.FaultOnWrite;
119 } while (!ll_cmpxchg_long(reinterpret_cast<PhysAddr *>
120 (this), ret, new_pte));
125 Mem::PTEFlags pte_to_flags()
127 Mem::PTEFlags ret = 0;
134 ret.Writeable = PermWrite;
136 ret.Uncached = CacheDisable;
137 ret.FaultOnWrite = FaultOnWrite;
138 ret.AddressOnly = AddressOnly;
144 void set_pte(PTE *table, uint offset)
149 PTE xchg_pte(PTE *table, uint offset)
151 return ll_xchg_long(reinterpret_cast<PhysAddr *>(&table[offset]), raw);
170 page_size = Arch::page_size,
171 page_shift = Arch::page_shift,
173 pages_per_table = page_size / sizeof(PhysAddr),
175 shift_per_level = 10,
177 // All "upper" addresses belong to the kernel.
184 static inline void invalidate_tlb_entry(ulong addr)
186 ll_invalidate_tlb_entry(addr);