]> git.buserror.net Git - polintos/scott/priv.git/blobdiff - kernel/include/kern/generic-pagetable.h
Lots of stuff.
[polintos/scott/priv.git] / kernel / include / kern / generic-pagetable.h
diff --git a/kernel/include/kern/generic-pagetable.h b/kernel/include/kern/generic-pagetable.h
new file mode 100644 (file)
index 0000000..a3a6984
--- /dev/null
@@ -0,0 +1,85 @@
+// 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