]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/dde/ddekit/src/pgtab-old.c
Some minor fixes.
[l4.git] / l4 / pkg / dde / ddekit / src / pgtab-old.c
1 /*
2  * \brief   Virtual page-table facility
3  *
4  * Implementation of page tables for saving virt->phys assignments.
5  *
6  * FIXME: This works for 32-bit architectures only! (Mostly because of pgtab.h.)
7  */
8
9 /*
10  * This file is part of DDEKit.
11  *
12  * (c) 2006-2012 Bjoern Doebel <doebel@os.inf.tu-dresden.de>
13  *               Christian Helmuth <ch12@os.inf.tu-dresden.de>
14  *               Thomas Friebel <tf13@os.inf.tu-dresden.de>
15  *     economic rights: Technische Universitaet Dresden (Germany)
16  *
17  * This file is part of TUD:OS and distributed under the terms of the
18  * GNU General Public License 2.
19  * Please see the COPYING-GPL-2 file for details.
20  */
21
22 #include <l4/dde/ddekit/pgtab.h>
23
24 #include <l4/sys/l4int.h>
25 #include <l4/sys/consts.h>
26 #include <l4/util/macros.h>
27 #include <l4/dm_mem/dm_mem.h>
28 #include <l4/log/l4log.h>
29
30
31 /**********************************
32  ** Page-table utility functions **
33  **********************************/
34
35 /* some useful consts */
36 enum
37 {
38         PDIR_SHIFT   = L4_SUPERPAGESHIFT,  /* readable alias */
39         PDIR_MASK    = L4_SUPERPAGEMASK,   /* readable alias */
40         PDIR_ENTRIES = (1 << (L4_MWORD_BITS - PDIR_SHIFT)),
41         PTAB_ENTRIES = (1 << (PDIR_SHIFT - L4_PAGESHIFT)),
42         PTAB_SIZE    = (sizeof(void*) * PTAB_ENTRIES)
43 };
44
45 /**
46  * Page table entry.
47  * bit 00-01: type, 0->largemalloc 1->slab page 2->contigmalloc (PTE_TYPE_*)
48  * bit 02-11: size in number of pages
49  * bit 12-31: physical page address
50  */
51 typedef union
52 {
53         unsigned compact;
54         struct
55         {
56                 unsigned type  :  2;
57                 unsigned pages : 10;
58                 unsigned phys  : 20;
59         } components;
60 } ddekit_pte;
61
62 /**
63  * Calculate offset of address in page directory - page-table number
64  */
65 static inline unsigned pt_num(l4_addr_t addr) {
66         return addr >> PDIR_SHIFT; }
67
68
69 /**
70  * Calculate offset of address in page table - page number
71  */
72 static inline unsigned pg_num(l4_addr_t addr) {
73         return (addr & ~PDIR_MASK) >> L4_PAGESHIFT; }
74
75
76 /* page directory */
77 static ddekit_pte *page_dir[PDIR_ENTRIES];
78
79
80 /**
81  * Get page-table entry
82  */
83 static inline ddekit_pte ddekit_get_pte(void *p)
84 {
85         l4_addr_t addr = (l4_mword_t)p;
86         ddekit_pte *tab;
87
88         tab = page_dir[pt_num(addr)];
89         if (!tab) return (ddekit_pte) 0U;
90
91         return tab[pg_num(addr)];
92 }
93
94
95 /**
96  * Set page-table entry
97  */
98 static inline void ddekit_set_pte(void *p, ddekit_pte pte)
99 {
100         l4_addr_t addr = (l4_addr_t) p;
101         ddekit_pte *tab;
102
103         tab = page_dir[pt_num(addr)];
104         if (!tab) {
105                 /* create new page table */
106                 tab = (ddekit_pte *)
107                       l4dm_mem_allocate_named(PTAB_SIZE, L4DM_CONTIGUOUS|L4DM_PINNED|L4RM_MAP,
108                                               "ddekit ptab");
109                 Assert(tab);
110
111                 memset(tab, 0, PTAB_SIZE);
112                 page_dir[pt_num(addr)] = tab;
113
114                 if (1) {
115                         l4_addr_t a = l4_trunc_superpage(addr);
116                         LOG("created page table for range [0x%08lx,0x%08lx) @ %p\n",
117                              a, a + L4_SUPERPAGESIZE, tab);
118                 }
119
120         }
121
122         tab[pg_num(addr)] = pte;
123 }
124
125
126 /*****************************
127  ** Page-table facility API **
128  *****************************/
129
130 /**
131  * Set virtual->physical mapping for VM region
132  *
133  * \param virtual   virtual start address for region
134  * \param physical  physical start address for region
135  * \param pages     number of pages in region
136  * \param type      pte type for region
137  */
138 void ddekit_pte_set_region(void *virtual, ddekit_addr_t physical, int pages, int type)
139 {
140         ddekit_pte new;
141
142 #ifdef INVARIANTS
143         ddekit_pte pte;
144         /* assert pte not set yet */
145         pte = ddekit_get_pte(virtual);
146         LOGd(pte.compact, "first pte already set! pte=0x%04x", pte.compact);
147 #endif
148
149         /* build pte */
150         new.components.type  = type;
151         new.components.pages = pages;
152         new.components.phys  = physical >> L4_PAGESHIFT;
153
154         /* set first pte */
155         ddekit_set_pte(virtual, new);
156
157         /* continuation pte-s don't have pages set */
158         new.components.pages = 0;
159
160         /* set continuation pte-s */
161         for (pages--; pages; pages--) {
162                 /* prepare continuation pte */
163                 virtual += L4_PAGESIZE;
164                 new.components.phys++;
165
166 #ifdef INVARIANTS
167                 /* assert pte not set yet */
168                 pte = ddekit_get_pte(virtual);
169                 LOGd(pte.compact, "continuation pte already set! pte=0x%04x", pte.compact);
170 #endif
171
172                 /* set continuation pte */
173                 ddekit_set_pte(virtual, new);
174         }
175 }
176
177
178 /**
179  * Clear virtual->physical mapping for VM region
180  *
181  * \param virtual   virtual start address for region
182  * \param type      pte type for region
183  *
184  * XXX unused page-tables not free'd
185  */
186 void ddekit_pte_clear_region(void *virtual, int type)
187 {
188         ddekit_pte pte;
189         int pages = 0;
190         pte = ddekit_get_pte(virtual);
191         /* get number of pages from pte */
192         pages = pte.components.pages;
193         /* assert pages != 0 */
194         if (pages==0) {
195                 LOG("continuation pte found at base");
196                 return;
197         }
198         /* assert pte set and of correct type */
199 #ifdef INVARIANTS
200         LOGd(! pte.compact, "pte is already clear");
201         LOGd(pte.components.type!=type, "pte of wrong type");
202 #endif
203         /* clear first pte */
204         ddekit_set_pte(virtual, (ddekit_pte) 0U);
205         /* clear continuation pte-s */
206         for (pages--; pages; pages--) {
207                 virtual += L4_PAGESIZE;
208
209 #ifdef INVARIANTS
210                 /* assert pte set and of correct type */
211                 pte = ddekit_get_pte(virtual);
212                 if (! pte.compact) {
213                         LOG("pte is already clear");
214                         break;
215                 }
216                 if (pte.components.type!=type) {
217                         LOG("pte of wrong type");
218                         break;
219                 }
220                 if (pte.components.pages) {
221                         LOG("unexpected non-continuation pte found");
222                         break;
223                 }
224 #endif
225
226                 ddekit_set_pte(virtual, (ddekit_pte) 0U);
227         }
228 }
229