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