00001
00002
00011
00012
00013
00014
00015
00035
00036 #include <l4/env/errno.h>
00037 #include <l4/lock/lock.h>
00038 #include <l4/names/libnames.h>
00039 #include <l4/l4rm/l4rm.h>
00040 #include <l4/dm_mem/dm_mem.h>
00041 #include <l4/dm_phys/dm_phys.h>
00042 #include <l4/util/list_alloc.h>
00043 #include <l4/dde_linux/dde.h>
00044
00045
00046 #include <linux/slab.h>
00047 #include <linux/vmalloc.h>
00048
00049
00050 #include "__config.h"
00051 #include "internal.h"
00052
00055 unsigned long num_physpages = 0;
00056
00061 static int _initialized = 0;
00062
00063
00065 static l4la_free_t *kpool = L4LA_INITIALIZER;
00067 static unsigned int kregion_size;
00069 static unsigned int kcount = MM_KREGIONS - 1;
00071 static l4lock_t klock = L4LOCK_UNLOCKED_INITIALIZER;
00072
00073
00075 static l4la_free_t *vpool = L4LA_INITIALIZER;
00077 static l4lock_t vlock = L4LOCK_UNLOCKED_INITIALIZER;
00078
00098 static __inline__ int __more_kcore(l4_size_t size)
00099 {
00100 int error;
00101 l4_addr_t kaddr;
00102
00103 l4_size_t tmp;
00104 l4dm_mem_addr_t dm_paddr;
00105
00106 if (!(kcount) || (size > kregion_size))
00107 {
00108 LOGdL(DEBUG_ERRORS, "Error: out of memory (kmem)");
00109 return -L4_ENOMEM;
00110 }
00111
00112 LOGd(DEBUG_MALLOC, "requesting %d bytes (kmem)", size);
00113
00114
00115 kaddr = (l4_addr_t) \
00116 l4dm_mem_allocate_named(kregion_size,
00117 L4DM_CONTIGUOUS | L4DM_PINNED | L4RM_MAP,
00118 "dde kmem");
00119 if (!kaddr)
00120 {
00121 LOGdL(DEBUG_ERRORS, "Error: allocating kmem");
00122 return -L4_ENOMEM;
00123 }
00124
00125 error = l4dm_mem_phys_addr((void *) kaddr, 1, &dm_paddr, 1, &tmp);
00126 if (error != 1)
00127 {
00128 if (error>1 || !error)
00129 Panic("Ouch, what's that?");
00130 LOGdL(DEBUG_ERRORS, "Error: getting physical address (%d)", error);
00131 return error;
00132 }
00133
00134 LOGd(DEBUG_MALLOC, "adding %d Bytes (kmem) @ 0x%08lx (phys. 0x%08lx) region %d",
00135 size, kaddr, dm_paddr.addr, kcount);
00136
00137
00138 l4la_free(&kpool, (void*)kaddr, size);
00139
00140
00141 l4dde_add_region(kaddr, dm_paddr.addr, size);
00142
00143 return 0;
00144 }
00145
00155 static __inline__ int __more_vcore(l4_size_t size)
00156 {
00157 LOGdL(DEBUG_ERRORS, "Error: out of memory (vmem)");
00158 return -L4_ENOMEM;
00159 }
00160
00171 void *kmalloc(size_t size, int gfp)
00172 {
00173 l4_uint32_t *chunk;
00174
00175 if (gfp & GFP_DMA)
00176 LOGd(DEBUG_MSG, "Warning: No ISA DMA implemented.");
00177
00178
00179 l4lock_lock(&klock);
00180
00181 size += sizeof(size_t);
00182 while (!(chunk = l4la_alloc(&kpool, size, 0)))
00183 {
00184 if (__more_kcore(size))
00185 {
00186 #if DEBUG_MALLOC
00187 LOG("failed to allocate %d bytes (kmem)", size);
00188 l4la_dump(&kpool);
00189 #endif
00190 return NULL;
00191 }
00192 }
00193 *chunk = size;
00194
00195 LOGd(DEBUG_MALLOC_EACH, "allocated %d bytes @ %p (kmem)", *chunk, chunk);
00196
00197 l4lock_unlock(&klock);
00198
00199 return ++chunk;
00200 }
00201
00209 void kfree(const void *addr)
00210 {
00211 l4_uint32_t *chunk = (l4_uint32_t *) addr - 1;
00212
00213 if (!addr)
00214 return;
00215
00216
00217 l4lock_lock(&klock);
00218
00219 LOGd(DEBUG_MALLOC_EACH, "freeing %d bytes @ %p (kmem)", *chunk, chunk);
00220
00221 l4la_free(&kpool, chunk, *chunk);
00222
00223 l4lock_unlock(&klock);
00224 }
00225
00235 void *vmalloc(unsigned long size)
00236 {
00237 l4_uint32_t *chunk;
00238
00239
00240 l4lock_lock(&vlock);
00241
00242 size += sizeof(size_t);
00243 while (!(chunk = l4la_alloc(&vpool, size, 0)))
00244 {
00245 if (__more_vcore(size))
00246 {
00247 #if DEBUG_MALLOC
00248 LOG("failed to allocate %ld bytes (vmem)", size);
00249 l4la_dump(&vpool);
00250 #endif
00251 return NULL;
00252 }
00253 }
00254 *chunk = size;
00255
00256 LOGd(DEBUG_MALLOC_EACH, "allocated %d bytes @ %p (vmem)", *chunk, chunk);
00257
00258 l4lock_unlock(&vlock);
00259
00260 return ++chunk;
00261 }
00262
00270 void vfree(void *addr)
00271 {
00272 l4_uint32_t *chunk = (l4_uint32_t *) addr - 1;
00273
00274 if (!addr)
00275 return;
00276
00277
00278 l4lock_lock(&vlock);
00279
00280 l4la_free(&vpool, chunk, *chunk);
00281
00282 LOGd(DEBUG_MALLOC_EACH, "freed %d bytes @ %p (vmem)", *chunk, chunk);
00283
00284 l4lock_unlock(&vlock);
00285 }
00286
00287
00289
00290 static int __setup_kmem(unsigned int *max, l4_addr_t *addr)
00291 {
00292 unsigned int size = *max;
00293 int error;
00294
00295 l4_size_t tmp;
00296 l4dm_mem_addr_t dm_paddr;
00297
00298 kregion_size = size / MM_KREGIONS;
00299 LOGd(DEBUG_MALLOC, "size/regions = %d", kregion_size);
00300
00301 kregion_size = (kregion_size + L4_PAGESIZE - 1) & L4_PAGEMASK;
00302 LOGd(DEBUG_MALLOC, "rsize (mod PAGESIZE) = %d", kregion_size);
00303
00304 if (kregion_size * MM_KREGIONS < size)
00305 {
00306 kregion_size += L4_PAGESIZE;
00307 LOGd(DEBUG_MALLOC, "new rsize = %d\n", kregion_size);
00308 }
00309
00310 LOGd(DEBUG_MALLOC, "kregion_size = 0x%x regions = %d",
00311 kregion_size, MM_KREGIONS);
00312
00313
00314 *addr = (l4_addr_t) \
00315 l4dm_mem_allocate_named(kregion_size,
00316 L4DM_CONTIGUOUS | L4DM_PINNED | L4RM_MAP,
00317 "dde kmem");
00318 if (!*addr) return -L4_ENOMEM;
00319
00320 error = l4dm_mem_phys_addr((void *)*addr, 1, &dm_paddr, 1, &tmp);
00321 if (error != 1)
00322 {
00323 if (error>1 || !error)
00324 Panic("Ouch, what's that?");
00325 LOGdL(DEBUG_ERRORS, "Error: getting physical address (%d)", error);
00326 return error;
00327 }
00328
00329 LOGd(DEBUG_MALLOC, "adding %d Bytes (kmem) @ 0x%08lx (phys. 0x%08lx) region 0",
00330 kregion_size, *addr, dm_paddr.addr);
00331
00332
00333 l4la_free(&kpool, (void *) *addr, kregion_size);
00334
00335
00336 l4dde_add_region(*addr, dm_paddr.addr, kregion_size);
00337
00338 *max = kregion_size * MM_KREGIONS;
00339 return 0;
00340 }
00341
00342
00344
00345 static int __setup_vmem(unsigned int *max, l4_addr_t *addr)
00346 {
00347 unsigned int size = *max;
00348
00349
00350 size = (size + L4_PAGESIZE - 1) & L4_PAGEMASK;
00351
00352
00353 *addr = (l4_addr_t) l4dm_mem_allocate_named(size, L4RM_MAP, "dde vmem");
00354 if (!*addr) return -L4_ENOMEM;
00355
00356
00357 l4la_free(&vpool, (void *) *addr, size);
00358
00359 *max = size;
00360 return 0;
00361 }
00362
00377 int l4dde_mm_init(unsigned int max_vsize, unsigned int max_ksize)
00378 {
00379 int error;
00380 l4_addr_t vaddr, kaddr;
00381
00382 char *vsize_str;
00383 char *ksize_str;
00384
00385 if (_initialized)
00386 return 0;
00387
00388
00389 if ((error=__setup_vmem(&max_vsize, &vaddr)))
00390 {
00391 LOGdL(DEBUG_ERRORS, "Error: setting up vmem: %d (%s)",
00392 error, l4env_strerror(-error));
00393 return error;
00394 }
00395
00396
00397 if ((error=__setup_kmem(&max_ksize, &kaddr)))
00398 {
00399 LOGdL(DEBUG_ERRORS, "Error: setting up kmem %d (%s)",
00400 error, l4env_strerror(-error));
00401 return error;
00402 }
00403
00404
00405 num_physpages = max_ksize / L4_PAGESIZE;
00406
00407
00408 if (max_vsize > 8 * 1024 * 1024)
00409 {
00410 max_vsize /= (1024 * 1024);
00411 vsize_str = "MB";
00412 }
00413 else if (max_vsize > 8 * 1024)
00414 {
00415 max_vsize /= 1024;
00416 vsize_str = "kB";
00417 }
00418 else
00419 vsize_str = "Byte";
00420 if (max_ksize > 8 * 1024 * 1024)
00421 {
00422 max_ksize /= (1024 * 1024);
00423 ksize_str = "MB";
00424 }
00425 else if (max_ksize > 8 * 1024)
00426 {
00427 max_ksize /= 1024;
00428 ksize_str = "kB";
00429 }
00430 else
00431 ksize_str = "Byte";
00432 LOG("Using ...\n"
00433 " %d %s at 0x%08lx (vmem)\n"
00434 " %d %s in %d regions (kmem)",
00435 max_vsize, vsize_str, vaddr, max_ksize, ksize_str, MM_KREGIONS);
00436
00437 #if DEBUG_MALLOC
00438 {
00439 int debug;
00440 l4dm_dataspace_t ds;
00441 l4_offs_t offset;
00442 l4_addr_t map_addr;
00443 l4_size_t map_size;
00444 l4_threadid_t dummy;
00445
00446 debug = l4rm_lookup((void*)vaddr, &map_addr, &map_size, &ds, &offset, &dummy);
00447 if (debug != L4RM_REGION_DATASPACE)
00448 Panic("l4rm_lookup failed (%d)", debug);
00449 LOG("vmem: ds={%3u, "l4util_idfmt"} offset=%d map_addr=0x%08x map_size=%d",
00450 ds.id, l4util_idstr(ds.manager), offset, map_addr, map_size);
00451
00452 debug = l4rm_lookup((void*)kaddr, &map_addr, &map_size, &ds, &offset, &dummy);
00453 if (debug != L4RM_REGION_DATASPACE)
00454 Panic("l4rm_lookup failed (%d)", debug);
00455 LOG("kmem: ds={%3u, "l4util_idfmt"} offset=%d map_addr=0x%08x map_size=%d",
00456 ds.id, l4util_idstr(ds.manager), offset, map_addr, map_size);
00457 }
00458 #endif
00459
00460 ++_initialized;
00461 return 0;
00462 }
00463
00466 int l4dde_mm_kmem_avail(void)
00467 {
00468 if (_initialized)
00469 return l4la_avail(&kpool);
00470
00471 return 0;
00472 }
00473
00475 int l4dde_mm_kmem_region(unsigned num, l4_addr_t *start, l4_addr_t *end)
00476 {
00477 #if 0
00478 if (num >= MM_KREGIONS)
00479 return -L4_EINVAL;
00480
00481 *start = kregion[num].min;
00482 *end = kregion[num].max;
00483
00484 return 0;
00485 #endif
00486 return -L4_EINVAL;
00487 }