00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <l4/dde/ddekit/pgtab.h>
00013
00014 #include <l4/sys/l4int.h>
00015 #include <l4/sys/consts.h>
00016 #include <l4/util/macros.h>
00017 #include <l4/dm_mem/dm_mem.h>
00018 #include <l4/log/l4log.h>
00019
00020
00021
00022
00023
00024
00025
00026 enum
00027 {
00028 PDIR_SHIFT = L4_SUPERPAGESHIFT,
00029 PDIR_MASK = L4_SUPERPAGEMASK,
00030 PDIR_ENTRIES = (1 << (L4_MWORD_BITS - PDIR_SHIFT)),
00031 PTAB_ENTRIES = (1 << (PDIR_SHIFT - L4_PAGESHIFT)),
00032 PTAB_SIZE = (sizeof(void*) * PTAB_ENTRIES)
00033 };
00034
00035
00036
00037
00038
00039
00040
00041 typedef union
00042 {
00043 unsigned compact;
00044 struct
00045 {
00046 unsigned type : 2;
00047 unsigned pages : 10;
00048 unsigned phys : 20;
00049 } components;
00050 } ddekit_pte;
00051
00052
00053
00054
00055 static inline unsigned pt_num(l4_addr_t addr) {
00056 return addr >> PDIR_SHIFT; }
00057
00058
00059
00060
00061
00062 static inline unsigned pg_num(l4_addr_t addr) {
00063 return (addr & ~PDIR_MASK) >> L4_PAGESHIFT; }
00064
00065
00066
00067 static ddekit_pte *page_dir[PDIR_ENTRIES];
00068
00069
00070
00071
00072
00073 static inline ddekit_pte ddekit_get_pte(void *p)
00074 {
00075 l4_addr_t addr = (l4_mword_t)p;
00076 ddekit_pte *tab;
00077
00078 tab = page_dir[pt_num(addr)];
00079 if (!tab) return (ddekit_pte) 0U;
00080
00081 return tab[pg_num(addr)];
00082 }
00083
00084
00085
00086
00087
00088 static inline void ddekit_set_pte(void *p, ddekit_pte pte)
00089 {
00090 l4_addr_t addr = (l4_addr_t) p;
00091 ddekit_pte *tab;
00092
00093 tab = page_dir[pt_num(addr)];
00094 if (!tab) {
00095
00096 tab = (ddekit_pte *)
00097 l4dm_mem_allocate_named(PTAB_SIZE, L4DM_CONTIGUOUS|L4DM_PINNED|L4RM_MAP,
00098 "ddekit ptab");
00099 Assert(tab);
00100
00101 memset(tab, 0, PTAB_SIZE);
00102 page_dir[pt_num(addr)] = tab;
00103
00104 if (1) {
00105 l4_addr_t a = l4_trunc_superpage(addr);
00106 LOG("created page table for range [0x%08lx,0x%08lx) @ %p\n",
00107 a, a + L4_SUPERPAGESIZE, tab);
00108 }
00109
00110 }
00111
00112 tab[pg_num(addr)] = pte;
00113 }
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128 void ddekit_pte_set_region(void *virtual, ddekit_addr_t physical, int pages, int type)
00129 {
00130 ddekit_pte new;
00131
00132 #ifdef INVARIANTS
00133 ddekit_pte pte;
00134
00135 pte = ddekit_get_pte(virtual);
00136 LOGd(pte.compact, "first pte already set! pte=0x%04x", pte.compact);
00137 #endif
00138
00139
00140 new.components.type = type;
00141 new.components.pages = pages;
00142 new.components.phys = physical >> L4_PAGESHIFT;
00143
00144
00145 ddekit_set_pte(virtual, new);
00146
00147
00148 new.components.pages = 0;
00149
00150
00151 for (pages--; pages; pages--) {
00152
00153 virtual += L4_PAGESIZE;
00154 new.components.phys++;
00155
00156 #ifdef INVARIANTS
00157
00158 pte = ddekit_get_pte(virtual);
00159 LOGd(pte.compact, "continuation pte already set! pte=0x%04x", pte.compact);
00160 #endif
00161
00162
00163 ddekit_set_pte(virtual, new);
00164 }
00165 }
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176 void ddekit_pte_clear_region(void *virtual, int type)
00177 {
00178 ddekit_pte pte;
00179 int pages = 0;
00180 pte = ddekit_get_pte(virtual);
00181
00182 pages = pte.components.pages;
00183
00184 if (pages==0) {
00185 LOG("continuation pte found at base");
00186 return;
00187 }
00188
00189 #ifdef INVARIANTS
00190 LOGd(! pte.compact, "pte is already clear");
00191 LOGd(pte.components.type!=type, "pte of wrong type");
00192 #endif
00193
00194 ddekit_set_pte(virtual, (ddekit_pte) 0U);
00195
00196 for (pages--; pages; pages--) {
00197 virtual += L4_PAGESIZE;
00198
00199 #ifdef INVARIANTS
00200
00201 pte = ddekit_get_pte(virtual);
00202 if (! pte.compact) {
00203 LOG("pte is already clear");
00204 break;
00205 }
00206 if (pte.components.type!=type) {
00207 LOG("pte of wrong type");
00208 break;
00209 }
00210 if (pte.components.pages) {
00211 LOG("unexpected non-continuation pte found");
00212 break;
00213 }
00214 #endif
00215
00216 ddekit_set_pte(virtual, (ddekit_pte) 0U);
00217 }
00218 }
00219