summaryrefslogtreecommitdiff
path: root/libddekit/pgtab-old.c
diff options
context:
space:
mode:
authorZheng Da <zhengda1936@gmail.com>2009-11-17 10:26:25 +0100
committerZheng Da <zhengda1936@gmail.com>2009-11-17 10:26:25 +0100
commita3eba19470c09f42272dac5ca1a34bd8a5cbe834 (patch)
tree06a10087ad78bcf7bc112de767e95d3b0a849c10 /libddekit/pgtab-old.c
parente0faf22f31c48fb27b43c1825897d26e58feafc4 (diff)
The original version of DDEKit.
Diffstat (limited to 'libddekit/pgtab-old.c')
-rw-r--r--libddekit/pgtab-old.c219
1 files changed, 219 insertions, 0 deletions
diff --git a/libddekit/pgtab-old.c b/libddekit/pgtab-old.c
new file mode 100644
index 00000000..2b13698a
--- /dev/null
+++ b/libddekit/pgtab-old.c
@@ -0,0 +1,219 @@
+/*
+ * \brief Virtual page-table facility
+ * \author Thomas Friebel <tf13@os.inf.tu-dresden.de>
+ * \author Christian Helmuth <ch12@os.inf.tu-dresden.de>
+ * \date 2006-11-01
+ *
+ * Implementation of page tables for saving virt->phys assignments.
+ *
+ * FIXME: This works for 32-bit architectures only! (Mostly because of pgtab.h.)
+ */
+
+#include <l4/dde/ddekit/pgtab.h>
+
+#include <l4/sys/l4int.h>
+#include <l4/sys/consts.h>
+#include <l4/util/macros.h>
+#include <l4/dm_mem/dm_mem.h>
+#include <l4/log/l4log.h>
+
+
+/**********************************
+ ** Page-table utility functions **
+ **********************************/
+
+/* some useful consts */
+enum
+{
+ PDIR_SHIFT = L4_SUPERPAGESHIFT, /* readable alias */
+ PDIR_MASK = L4_SUPERPAGEMASK, /* readable alias */
+ PDIR_ENTRIES = (1 << (L4_MWORD_BITS - PDIR_SHIFT)),
+ PTAB_ENTRIES = (1 << (PDIR_SHIFT - L4_PAGESHIFT)),
+ PTAB_SIZE = (sizeof(void*) * PTAB_ENTRIES)
+};
+
+/**
+ * Page table entry.
+ * bit 00-01: type, 0->largemalloc 1->slab page 2->contigmalloc (PTE_TYPE_*)
+ * bit 02-11: size in number of pages
+ * bit 12-31: physical page address
+ */
+typedef union
+{
+ unsigned compact;
+ struct
+ {
+ unsigned type : 2;
+ unsigned pages : 10;
+ unsigned phys : 20;
+ } components;
+} ddekit_pte;
+
+/**
+ * Calculate offset of address in page directory - page-table number
+ */
+static inline unsigned pt_num(l4_addr_t addr) {
+ return addr >> PDIR_SHIFT; }
+
+
+/**
+ * Calculate offset of address in page table - page number
+ */
+static inline unsigned pg_num(l4_addr_t addr) {
+ return (addr & ~PDIR_MASK) >> L4_PAGESHIFT; }
+
+
+/* page directory */
+static ddekit_pte *page_dir[PDIR_ENTRIES];
+
+
+/**
+ * Get page-table entry
+ */
+static inline ddekit_pte ddekit_get_pte(void *p)
+{
+ l4_addr_t addr = (l4_mword_t)p;
+ ddekit_pte *tab;
+
+ tab = page_dir[pt_num(addr)];
+ if (!tab) return (ddekit_pte) 0U;
+
+ return tab[pg_num(addr)];
+}
+
+
+/**
+ * Set page-table entry
+ */
+static inline void ddekit_set_pte(void *p, ddekit_pte pte)
+{
+ l4_addr_t addr = (l4_addr_t) p;
+ ddekit_pte *tab;
+
+ tab = page_dir[pt_num(addr)];
+ if (!tab) {
+ /* create new page table */
+ tab = (ddekit_pte *)
+ l4dm_mem_allocate_named(PTAB_SIZE, L4DM_CONTIGUOUS|L4DM_PINNED|L4RM_MAP,
+ "ddekit ptab");
+ Assert(tab);
+
+ memset(tab, 0, PTAB_SIZE);
+ page_dir[pt_num(addr)] = tab;
+
+ if (1) {
+ l4_addr_t a = l4_trunc_superpage(addr);
+ LOG("created page table for range [0x%08lx,0x%08lx) @ %p\n",
+ a, a + L4_SUPERPAGESIZE, tab);
+ }
+
+ }
+
+ tab[pg_num(addr)] = pte;
+}
+
+
+/*****************************
+ ** Page-table facility API **
+ *****************************/
+
+/**
+ * Set virtual->physical mapping for VM region
+ *
+ * \param virtual virtual start address for region
+ * \param physical physical start address for region
+ * \param pages number of pages in region
+ * \param type pte type for region
+ */
+void ddekit_pte_set_region(void *virtual, ddekit_addr_t physical, int pages, int type)
+{
+ ddekit_pte new;
+
+#ifdef INVARIANTS
+ ddekit_pte pte;
+ /* assert pte not set yet */
+ pte = ddekit_get_pte(virtual);
+ LOGd(pte.compact, "first pte already set! pte=0x%04x", pte.compact);
+#endif
+
+ /* build pte */
+ new.components.type = type;
+ new.components.pages = pages;
+ new.components.phys = physical >> L4_PAGESHIFT;
+
+ /* set first pte */
+ ddekit_set_pte(virtual, new);
+
+ /* continuation pte-s don't have pages set */
+ new.components.pages = 0;
+
+ /* set continuation pte-s */
+ for (pages--; pages; pages--) {
+ /* prepare continuation pte */
+ virtual += L4_PAGESIZE;
+ new.components.phys++;
+
+#ifdef INVARIANTS
+ /* assert pte not set yet */
+ pte = ddekit_get_pte(virtual);
+ LOGd(pte.compact, "continuation pte already set! pte=0x%04x", pte.compact);
+#endif
+
+ /* set continuation pte */
+ ddekit_set_pte(virtual, new);
+ }
+}
+
+
+/**
+ * Clear virtual->physical mapping for VM region
+ *
+ * \param virtual virtual start address for region
+ * \param type pte type for region
+ *
+ * XXX unused page-tables not free'd
+ */
+void ddekit_pte_clear_region(void *virtual, int type)
+{
+ ddekit_pte pte;
+ int pages = 0;
+ pte = ddekit_get_pte(virtual);
+ /* get number of pages from pte */
+ pages = pte.components.pages;
+ /* assert pages != 0 */
+ if (pages==0) {
+ LOG("continuation pte found at base");
+ return;
+ }
+ /* assert pte set and of correct type */
+#ifdef INVARIANTS
+ LOGd(! pte.compact, "pte is already clear");
+ LOGd(pte.components.type!=type, "pte of wrong type");
+#endif
+ /* clear first pte */
+ ddekit_set_pte(virtual, (ddekit_pte) 0U);
+ /* clear continuation pte-s */
+ for (pages--; pages; pages--) {
+ virtual += L4_PAGESIZE;
+
+#ifdef INVARIANTS
+ /* assert pte set and of correct type */
+ pte = ddekit_get_pte(virtual);
+ if (! pte.compact) {
+ LOG("pte is already clear");
+ break;
+ }
+ if (pte.components.type!=type) {
+ LOG("pte of wrong type");
+ break;
+ }
+ if (pte.components.pages) {
+ LOG("unexpected non-continuation pte found");
+ break;
+ }
+#endif
+
+ ddekit_set_pte(virtual, (ddekit_pte) 0U);
+ }
+}
+