xref: /minix/minix/lib/libddekit/src/pgtab.c (revision 83133719)
1 /*
2  * @author: Dirk Vogt
3  * @date 2010-02-10
4  *
5  * This file implements a local pagetable, to prevent IPC on physical
6  * address lookups. For now it's implement in a signle linked list.
7  *
8  * As soon as the DDE will use a premeptive thread mechanism access to
9  * the page table has to be sznchronized.
10  */
11 #include "common.h"
12 
13 #include <ddekit/pgtab.h>
14 #include <ddekit/memory.h>
15 #include <ddekit/lock.h>
16 
17 #ifdef DDEBUG_LEVEL_PGTAB
18 #undef DDEBUG
19 #define DDEBUG DDEBUG_LEVEL_PGTAB
20 #endif
21 
22 #include "util.h"
23 #include "debug.h"
24 
25 
26 static void lock_pgtab(void);
27 static void unlock_pgtab(void);
28 static struct dde_pgtab_region * allocate_region(void);
29 static void free_region(struct dde_pgtab_region *r);
30 static void add_region(struct dde_pgtab_region *r);
31 static void rm_region(struct dde_pgtab_region *r);
32 static struct dde_pgtab_region * find_region_virt(ddekit_addr_t va);
33 static struct dde_pgtab_region * find_region_phys(ddekit_addr_t pa);
34 
35 struct dde_pgtab_region {
36 	ddekit_addr_t vm_start;
37 	ddekit_addr_t phy_start;
38 	unsigned size;
39 	unsigned type; /* do we really have to keep track of the type here? */
40 	struct dde_pgtab_region *next;
41 	struct dde_pgtab_region *prev;
42 };
43 
44 static struct dde_pgtab_region  head = {0,0,0,0,&head,&head};
45 static ddekit_lock_t lock;
46 
47 /*
48  * INTERNAL HELPERS
49  */
50 
51 /****************************************************************************/
52 /*      lock_pgtab                                                          */
53 /****************************************************************************/
54 static void lock_pgtab()
55 {
56 	ddekit_lock_lock(&lock);
57 }
58 
59 
60 /****************************************************************************/
61 /*      unlock_pgtab                                                        */
62 /****************************************************************************/
63 static void unlock_pgtab()
64 {
65 	ddekit_lock_unlock(&lock);
66 }
67 
68 /****************************************************************************/
69 /*      dde_pgtab_region                                                    */
70 /****************************************************************************/
71 static struct dde_pgtab_region * allocate_region()
72 {
73 	struct dde_pgtab_region * res;
74 
75 	res = (struct dde_pgtab_region *)
76 	          ddekit_simple_malloc(sizeof(struct dde_pgtab_region));
77 	if (!res)
78 	{
79 		DDEBUG_MSG_ERR("Could not allocate region");
80 	}
81 	return res;
82 }
83 
84 /****************************************************************************/
85 /*      free_region                                                         */
86 /****************************************************************************/
87 static void free_region(struct dde_pgtab_region *r)
88 {
89 	ddekit_simple_free(r);
90 }
91 
92 /****************************************************************************/
93 /*      add_region                                                          */
94 /****************************************************************************/
95 static void add_region (struct dde_pgtab_region *r)
96 {
97 	r->next    = head.next;
98 	head.next  = r;
99 	r->prev    = &head;
100 
101 	if (r->next) {
102 
103 		r->next->prev = r;
104 
105 	}
106 }
107 
108 /****************************************************************************/
109 /*      rm_region                                                           */
110 /****************************************************************************/
111 static void rm_region(struct dde_pgtab_region *r)
112 {
113 	if (r->next) {
114 		r->next->prev = r->prev;
115 	}
116 	if (r->prev) {
117 		r->prev->next = r->next;
118 	}
119 	r->next = 0;
120 	r->prev = 0;
121 }
122 
123 
124 /****************************************************************************/
125 /*      find_region_virt                                                    */
126 /****************************************************************************/
127 static struct dde_pgtab_region * find_region_virt(ddekit_addr_t va)
128 {
129 	struct dde_pgtab_region * r;
130 
131 	for( r = head.next; r != &head ; r = r->next ) {
132 
133 		if ( (r->vm_start <= va)  && (va < (r->vm_start + r->size) ) )  {
134 			break;
135 		}
136 	}
137 
138 	if (r == &head) {
139 		DDEBUG_MSG_VERBOSE("No virt->phys mapping found for %x", va);
140 		r = 0;
141 	}
142 
143 	return r;
144 }
145 
146 /****************************************************************************/
147 /*      find_region_phys                                                    */
148 /****************************************************************************/
149 static struct dde_pgtab_region * find_region_phys(ddekit_addr_t pa)
150 {
151 	struct dde_pgtab_region * r;
152 
153 	for( r = head.next; r != &head ; r = r->next ) {
154 		if ( (r->phy_start <= pa)  && (pa < (r->phy_start + r->size) ) )
155 			break;
156 	}
157 
158 	if (r == &head)	{
159 		r=0;
160 		DDEBUG_MSG_VERBOSE("No phys->virt mapping found for %x", pa);
161 	}
162 
163 	return r;
164 }
165 
166 /****************************************************************************/
167 /*      ddekit_pgtab_do_fo_each_region                                      */
168 /****************************************************************************/
169 void ddekit_pgtab_do_fo_each_region(void (*func) (unsigned, unsigned)) {
170 	struct dde_pgtab_region * r;
171 
172 	for( r = head.next; r != &head ; r = r->next ) {
173 		ddekit_printf("%p",r->vm_start);
174 		func(r->vm_start, r->size);
175 	}
176 }
177 
178 /*
179  * Interface implementation
180  */
181 
182 /****************************************************************************/
183 /*      ddekit_pgtab_set_region                                             */
184 /****************************************************************************/
185 void ddekit_pgtab_set_region(void *virt, ddekit_addr_t phys, int pages, int type)
186 {
187 	ddekit_pgtab_set_region_with_size(virt, phys, (4096)*pages, type);
188 }
189 
190 /****************************************************************************/
191 /*      ddekit_pgtab_set_region_with_size                                   */
192 /****************************************************************************/
193 void ddekit_pgtab_set_region_with_size(void *virt, ddekit_addr_t phys, int size, int type)
194 {
195 	struct dde_pgtab_region * r;
196 
197 	lock_pgtab();
198 
199 	r = allocate_region();
200 
201 	r->vm_start  = (ddekit_addr_t) virt;
202 	r->phy_start = phys;
203 	r->size      = size;
204 	r->type      = type;
205 
206 	add_region(r);
207 
208 	unlock_pgtab();
209 }
210 
211 
212 /****************************************************************************/
213 /*      ddekit_pgtab_clear_region                                           */
214 /****************************************************************************/
215 void ddekit_pgtab_clear_region(void *virt, int type) {
216 
217 	struct dde_pgtab_region *r;
218 
219 	lock_pgtab();
220 
221 	r = find_region_virt((ddekit_addr_t)virt);
222 
223 	if (r)
224 	{
225 		rm_region(r);
226 		free_region(r);
227 	}
228 
229 	unlock_pgtab();
230 
231 }
232 
233 
234 /****************************************************************************/
235 /*      ddekit_pgtab_get_physaddr                                           */
236 /****************************************************************************/
237 ddekit_addr_t ddekit_pgtab_get_physaddr(const void *virt)
238 {
239 	struct dde_pgtab_region *r;
240 	ddekit_addr_t ret = 0;
241 	lock_pgtab();
242     r = find_region_virt((ddekit_addr_t)virt);
243 	unlock_pgtab();
244 	if (r != NULL) {
245 
246 		ret =  ((ddekit_addr_t) virt - r->vm_start) + r->phy_start;
247 		DDEBUG_MSG_VERBOSE("pa: %p -> %p\n", virt, ret);
248 	}
249 
250 	return ret;
251 }
252 
253 /****************************************************************************/
254 /*      ddekit_pgtab_get_virtaddr                                           */
255 /****************************************************************************/
256 ddekit_addr_t ddekit_pgtab_get_virtaddr(const ddekit_addr_t physical)
257 {
258 	struct dde_pgtab_region *r;
259 	lock_pgtab();
260     r = find_region_phys((ddekit_addr_t)physical);
261 	unlock_pgtab();
262 	if (r != NULL)
263 	{
264 		return ((ddekit_addr_t) physical - r->phy_start) + r->vm_start;
265 	}
266 
267 	return 0;
268 }
269 
270 /****************************************************************************/
271 /*      ddekit_pgtab_get_size                                               */
272 /****************************************************************************/
273 int ddekit_pgtab_get_type(const void *virt)
274 {
275 	/*
276 	 * needed for dde fbsd
277 	 */
278 	struct dde_pgtab_region *r;
279 
280 	lock_pgtab();
281 	r = find_region_virt((ddekit_addr_t)virt);
282 	unlock_pgtab();
283 	return r->type;
284 }
285 
286 
287 /****************************************************************************/
288 /*      ddekit_pgtab_get_size                                               */
289 /****************************************************************************/
290 int ddekit_pgtab_get_size(const void *virt)
291 {
292 	/*
293 	 * needed for fbsd
294 	 */
295 	struct dde_pgtab_region *r;
296 
297 	lock_pgtab();
298 	r = find_region_virt((ddekit_addr_t)virt);
299 	unlock_pgtab();
300 	if(r)
301 		return r->size;
302 	else
303 		return 0;
304 }
305 
306 /****************************************************************************/
307 /*      ddekit_pgtab_init                                                   */
308 /****************************************************************************/
309 void ddekit_pgtab_init() {
310 	/* called by ddekit_init() */
311 	ddekit_lock_init(&lock);
312 }
313 
314