kernel: scheduling fix for ARM
[minix.git] / lib / libddekit / src / pgtab.c
blob3206bde357231e558920e4db480884446b862581
1 /*
2 * @author: Dirk Vogt
3 * @date 2010-02-10
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.
8 * As soon as the DDE will use a premeptive thread mechanism access to
9 * the page table has to be sznchronized.
11 #include "common.h"
13 #include <ddekit/pgtab.h>
14 #include <ddekit/memory.h>
15 #include <ddekit/lock.h>
17 #ifdef DDEBUG_LEVEL_PGTAB
18 #undef DDEBUG
19 #define DDEBUG DDEBUG_LEVEL_PGTAB
20 #endif
22 #include "util.h"
23 #include "debug.h"
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);
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;
44 static struct dde_pgtab_region head = {0,0,0,0,&head,&head};
45 static ddekit_lock_t lock;
48 * INTERNAL HELPERS
51 /****************************************************************************/
52 /* lock_pgtab */
53 /****************************************************************************/
54 static void lock_pgtab()
56 ddekit_lock_lock(&lock);
60 /****************************************************************************/
61 /* unlock_pgtab */
62 /****************************************************************************/
63 static void unlock_pgtab()
65 ddekit_lock_unlock(&lock);
68 /****************************************************************************/
69 /* dde_pgtab_region */
70 /****************************************************************************/
71 static struct dde_pgtab_region * allocate_region()
73 struct dde_pgtab_region * res;
75 res = (struct dde_pgtab_region *)
76 ddekit_simple_malloc(sizeof(struct dde_pgtab_region));
77 if (!res)
79 DDEBUG_MSG_ERR("Could not allocate region");
81 return res;
84 /****************************************************************************/
85 /* free_region */
86 /****************************************************************************/
87 static void free_region(struct dde_pgtab_region *r)
89 ddekit_simple_free(r);
92 /****************************************************************************/
93 /* add_region */
94 /****************************************************************************/
95 static void add_region (struct dde_pgtab_region *r)
97 r->next = head.next;
98 head.next = r;
99 r->prev = &head;
101 if (r->next) {
103 r->next->prev = r;
108 /****************************************************************************/
109 /* rm_region */
110 /****************************************************************************/
111 static void rm_region(struct dde_pgtab_region *r)
113 if (r->next) {
114 r->next->prev = r->prev;
116 if (r->prev) {
117 r->prev->next = r->next;
119 r->next = 0;
120 r->prev = 0;
124 /****************************************************************************/
125 /* find_region_virt */
126 /****************************************************************************/
127 static struct dde_pgtab_region * find_region_virt(ddekit_addr_t va)
129 struct dde_pgtab_region * r;
131 for( r = head.next; r != &head ; r = r->next ) {
133 if ( (r->vm_start <= va) && (va < (r->vm_start + r->size) ) ) {
134 break;
138 if (r == &head) {
139 DDEBUG_MSG_VERBOSE("No virt->phys mapping found for %x", va);
140 r = 0;
143 return r;
146 /****************************************************************************/
147 /* find_region_phys */
148 /****************************************************************************/
149 static struct dde_pgtab_region * find_region_phys(ddekit_addr_t pa)
151 struct dde_pgtab_region * r;
153 for( r = head.next; r != &head ; r = r->next ) {
154 if ( (r->phy_start <= pa) && (pa < (r->phy_start + r->size) ) )
155 break;
158 if (r == &head) {
159 r=0;
160 DDEBUG_MSG_VERBOSE("No phys->virt mapping found for %x", pa);
163 return r;
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;
172 for( r = head.next; r != &head ; r = r->next ) {
173 ddekit_printf("%p",r->vm_start);
174 func(r->vm_start, r->size);
179 * Interface implementation
182 /****************************************************************************/
183 /* ddekit_pgtab_set_region */
184 /****************************************************************************/
185 void ddekit_pgtab_set_region(void *virt, ddekit_addr_t phys, int pages, int type)
187 ddekit_pgtab_set_region_with_size(virt, phys, (4096)*pages, type);
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)
195 struct dde_pgtab_region * r;
197 lock_pgtab();
199 r = allocate_region();
201 r->vm_start = (ddekit_addr_t) virt;
202 r->phy_start = phys;
203 r->size = size;
204 r->type = type;
206 add_region(r);
208 unlock_pgtab();
212 /****************************************************************************/
213 /* ddekit_pgtab_clear_region */
214 /****************************************************************************/
215 void ddekit_pgtab_clear_region(void *virt, int type) {
217 struct dde_pgtab_region *r;
219 lock_pgtab();
221 r = find_region_virt((ddekit_addr_t)virt);
223 if (r)
225 rm_region(r);
226 free_region(r);
229 unlock_pgtab();
234 /****************************************************************************/
235 /* ddekit_pgtab_get_physaddr */
236 /****************************************************************************/
237 ddekit_addr_t ddekit_pgtab_get_physaddr(const void *virt)
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) {
246 ret = ((ddekit_addr_t) virt - r->vm_start) + r->phy_start;
247 DDEBUG_MSG_VERBOSE("pa: %p -> %p\n", virt, ret);
250 return ret;
253 /****************************************************************************/
254 /* ddekit_pgtab_get_virtaddr */
255 /****************************************************************************/
256 ddekit_addr_t ddekit_pgtab_get_virtaddr(const ddekit_addr_t physical)
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)
264 return ((ddekit_addr_t) physical - r->phy_start) + r->vm_start;
267 return 0;
270 /****************************************************************************/
271 /* ddekit_pgtab_get_size */
272 /****************************************************************************/
273 int ddekit_pgtab_get_type(const void *virt)
276 * needed for dde fbsd
278 struct dde_pgtab_region *r;
280 lock_pgtab();
281 r = find_region_virt((ddekit_addr_t)virt);
282 unlock_pgtab();
283 return r->type;
287 /****************************************************************************/
288 /* ddekit_pgtab_get_size */
289 /****************************************************************************/
290 int ddekit_pgtab_get_size(const void *virt)
293 * needed for fbsd
295 struct dde_pgtab_region *r;
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;
306 /****************************************************************************/
307 /* ddekit_pgtab_init */
308 /****************************************************************************/
309 void ddekit_pgtab_init() {
310 /* called by ddekit_init() */
311 ddekit_lock_init(&lock);