1 // This is a generic pagetable implementation that most architectures
2 // should be able to use as is, though architectures with weird paging
3 // hardware can provide their own implementation. It corresponds to
6 #ifndef _KERN_GENERIC_PAGETABLE_H
7 #define _KERN_GENERIC_PAGETABLE_H
10 #include <util/lock.h>
11 #include <arch/pagetable.h>
12 #include <kern/pagetable.h>
15 template<typename PTE>
16 class PageTableImpl : public PageTable {
18 typedef Mem::PTEFlags Flags;
19 typedef System::Mem::Region Region;
20 typedef System::Mem::RegionWithOffset RegionWithOffset;
21 typedef typename PTE::VirtAddr VirtAddr;
22 typedef typename PTE::DirPTE DirPTE;
25 // The lock of any page table may nest in the lock of any
30 // For non-process aspaces, the number of levels may be more or
31 // less than what the hardware provides (in particular, large file
32 // mappings on 32-bit targets will need more levels). For process
33 // aspaces, num_levels must equal PTE::num_levels. Levels for
34 // non-process address spaces can be added dynamically as needed.
35 // Non-proc aspaces may also use a different PTE format.
38 int toplevel_shift, lastlevel_shift;
40 static uint pages_per_table()
42 return 1 << PTE::shift_per_level;
45 static uint pages_per_dtable()
47 return 1 << DirPTE::shift_per_level;
50 void end_map(RegionWithOffset region, PTE flags, void *table);
52 void end_unmap(Region region, void *table);
54 void end_set_flags(Region region, PTE flags, PTE mask, void *table);
56 void rec_map(RegionWithOffset region, PTE flags,
57 void *table, int shift);
59 void rec_unmap(Region region, void *table, int shift);
61 void rec_set_flags(Region region, PTE flags,
62 PTE mask, void *table, int shift);
65 PageTableImpl(bool process);
66 PageTableImpl(void *table);
68 virtual ~PageTableImpl();
70 virtual void map(RegionWithOffset region, Flags flags);
71 virtual void unmap(Region region);
72 virtual void set_flags(Region region, Flags flags, Flags mask);
73 virtual void get_mapping(u64 addr, u64 *phys, Flags *flags);
75 virtual void get_size(u64 *size)
78 *size = 1ULL << (PTE::num_levels * PTE::shift_per_level);
80 *size = 1ULL << (64 - PTE::page_shift);