--- /dev/null
+// This is a generic pagetable implementation that most architectures
+// should be able to use as is, though architectures with weird paging
+// hardware can provide their own implementation. It corresponds to
+// mem/pagetable.cc.
+
+#ifndef _KERN_GENERIC_PAGETABLE_H
+#define _KERN_GENERIC_PAGETABLE_H
+
+#include <kern/mem.h>
+#include <util/lock.h>
+#include <arch/pagetable.h>
+#include <kern/pagetable.h>
+
+namespace Mem {
+ template<typename PTE>
+ class PageTableImpl : public PageTable {
+ public:
+ typedef Mem::PTEFlags Flags;
+ typedef System::Mem::Region Region;
+ typedef System::Mem::RegionWithOffset RegionWithOffset;
+ typedef typename PTE::VirtAddr VirtAddr;
+ typedef typename PTE::DirPTE DirPTE;
+
+ private:
+ // The lock of any page table may nest in the lock of any
+ // aspace.
+
+ Lock::Lock lock;
+
+ // For non-process aspaces, the number of levels may be more or
+ // less than what the hardware provides (in particular, large file
+ // mappings on 32-bit targets will need more levels). For process
+ // aspaces, num_levels must equal PTE::num_levels. Levels for
+ // non-process address spaces can be added dynamically as needed.
+ // Non-proc aspaces may also use a different PTE format.
+
+ int num_levels;
+ int toplevel_shift, lastlevel_shift;
+
+ static uint pages_per_table()
+ {
+ return 1 << PTE::shift_per_level;
+ }
+
+ static uint pages_per_dtable()
+ {
+ return 1 << DirPTE::shift_per_level;
+ }
+
+ void end_map(RegionWithOffset region, PTE flags, void *table);
+
+ void end_unmap(Region region, void *table);
+
+ void end_set_flags(Region region, PTE flags, PTE mask, void *table);
+
+ void rec_map(RegionWithOffset region, PTE flags,
+ void *table, int shift);
+
+ void rec_unmap(Region region, void *table, int shift);
+
+ void rec_set_flags(Region region, PTE flags,
+ PTE mask, void *table, int shift);
+
+ public:
+ PageTableImpl(bool process);
+ PageTableImpl(void *table);
+
+ virtual ~PageTableImpl();
+
+ virtual void map(RegionWithOffset region, Flags flags);
+ virtual void unmap(Region region);
+ virtual void set_flags(Region region, Flags flags, Flags mask);
+ virtual void get_mapping(u64 addr, u64 *phys, Flags *flags);
+
+ virtual void get_size(u64 *size)
+ {
+ if (is_process)
+ *size = 1ULL << (PTE::num_levels * PTE::shift_per_level);
+ else
+ *size = 1ULL << (64 - PTE::page_shift);
+ }
+ };
+}
+
+#endif