00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <l4/dde/ddekit/memory.h>
00014 #include <l4/dde/ddekit/panic.h>
00015 #include <l4/dde/ddekit/pgtab.h>
00016 #include <l4/dde/ddekit/printf.h>
00017
00018 #include <l4/lock/lock.h>
00019 #include <l4/slab/slab.h>
00020 #include <l4/dm_mem/dm_mem.h>
00021 #include <l4/util/atomic.h>
00022 #include <l4/util/util.h>
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 struct ddekit_pcache
00052 {
00053 struct ddekit_pcache *next;
00054 void *page;
00055 int contig;
00056 };
00057
00058
00059
00060 static struct ddekit_pcache *pcache_used;
00061
00062 static struct ddekit_pcache *pcache_free;
00063
00064
00065 static struct ddekit_pcache *pcache_used_contig;
00066
00067 static struct ddekit_pcache *pcache_free_contig;
00068
00069
00070
00071 static l4_uint32_t pcache_num_entries = 1;
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 void ddekit_slab_setup_page_cache(unsigned pages)
00084 {
00085
00086 while (pcache_num_entries < pages) {
00087 struct ddekit_pcache *new_entry, *new_contig;
00088
00089
00090 new_entry = (struct ddekit_pcache *) ddekit_simple_malloc(sizeof(*new_entry));
00091 new_contig = (struct ddekit_pcache *) ddekit_simple_malloc(sizeof(*new_contig));
00092
00093
00094 do {
00095 new_entry->next = pcache_free;
00096 } while (!l4util_cmpxchg32((l4_uint32_t*)&pcache_free,
00097 (l4_uint32_t)new_entry->next,
00098 (l4_uint32_t)new_entry));
00099
00100 do {
00101 new_contig->next = pcache_free_contig;
00102 } while (!l4util_cmpxchg32((l4_uint32_t*)&pcache_free_contig,
00103 (l4_uint32_t)new_entry->next,
00104 (l4_uint32_t)new_entry));
00105
00106
00107 l4util_inc32(&pcache_num_entries);
00108 }
00109 }
00110
00111
00112
00113
00114
00115 static inline struct ddekit_pcache *_try_from_cache(int contig)
00116 {
00117 struct ddekit_pcache *head = NULL;
00118 struct ddekit_pcache *the_cache = contig ? pcache_used_contig : pcache_used;
00119
00120 do {
00121 head = the_cache;
00122 if (!head) break;
00123 } while (!l4util_cmpxchg32((l4_uint32_t*)&the_cache, (l4_uint32_t)head,
00124 (l4_uint32_t)head->next));
00125
00126 return head;
00127 }
00128
00129
00130 static inline void _add_to_cache(struct ddekit_pcache *entry, int contig)
00131 {
00132 struct ddekit_pcache *the_cache = contig ? pcache_used_contig : pcache_used;
00133 do {
00134 entry->next = the_cache;
00135 } while (! l4util_cmpxchg32((l4_uint32_t*)&the_cache, (l4_uint32_t)entry->next,
00136 (l4_uint32_t)entry));
00137 }
00138
00139
00140
00141
00142 static inline void _free_cache_entry(struct ddekit_pcache *entry, int contig)
00143 {
00144 struct ddekit_pcache *the_cache = contig ? pcache_free_contig : pcache_free;
00145 do {
00146 entry->next = the_cache;
00147 } while (!l4util_cmpxchg32((l4_uint32_t*)&the_cache, (l4_uint32_t)entry->next,
00148 (l4_uint32_t)entry));
00149 }
00150
00151
00152 static inline struct ddekit_pcache *_get_free_cache_entry(int contig)
00153 {
00154 struct ddekit_pcache *the_cache = contig ? pcache_free_contig : pcache_free;
00155 struct ddekit_pcache *head = NULL;
00156
00157 do {
00158 head = the_cache;
00159 if (!head) break;
00160 } while (!l4util_cmpxchg32((l4_uint32_t*)&the_cache, (l4_uint32_t)head,
00161 (l4_uint32_t) head->next));
00162
00163 return head;
00164 }
00165
00166
00167
00168
00169
00170
00171
00172 struct ddekit_slab
00173 {
00174 l4slab_cache_t cache;
00175
00176
00177
00178
00179 l4lock_t lock;
00180 int contiguous;
00181 };
00182
00183
00184
00185
00186
00187
00188
00189
00190 static inline struct ddekit_slab *ddekit_slab_from_l4slab(l4slab_cache_t *s)
00191 {
00192 return (struct ddekit_slab *)s;
00193 }
00194
00195
00196
00197
00198 static void *_slab_grow(l4slab_cache_t *cache, void **data)
00199 {
00200
00201 void *res = NULL;
00202
00203 int is_contig = ddekit_slab_from_l4slab(cache)->contiguous;
00204
00205
00206 struct ddekit_pcache *head = NULL;
00207
00208
00209
00210 if (cache->slab_size <= L4_PAGESIZE)
00211
00212 head = _try_from_cache(is_contig);
00213
00214 if (head) {
00215
00216 res = head->page;
00217
00218 _free_cache_entry(head, is_contig);
00219 } else {
00220
00221 int err;
00222 l4_size_t tmp;
00223 l4dm_mem_addr_t dm_paddr;
00224 int num_pages = cache->slab_size / L4_PAGESIZE;
00225 int flags = L4DM_PINNED | L4RM_MAP | L4RM_LOG2_ALIGNED;
00226
00227 if (is_contig)
00228 flags |= L4DM_CONTIGUOUS;
00229
00230
00231 res = l4dm_mem_allocate_named(num_pages * L4_PAGESIZE,
00232 flags,
00233 "ddekit slab");
00234 if (res == NULL)
00235 ddekit_debug("__grow: error allocating a new page");
00236
00237
00238 if (is_contig) {
00239 err = l4dm_mem_phys_addr(res, num_pages, &dm_paddr, 1, &tmp);
00240 if (err != 1)
00241 ddekit_debug("__grow: error getting physical address of new page!");
00242
00243 ddekit_pgtab_set_region(res, dm_paddr.addr, num_pages, PTE_TYPE_UMA);
00244 }
00245 }
00246
00247
00248 *data = cache;
00249
00250 return res;
00251 }
00252
00253
00254
00255
00256 static void _slab_shrink(l4slab_cache_t *cache, void *page, void *data)
00257 {
00258
00259 struct ddekit_pcache *head = NULL;
00260
00261 int is_contig = ddekit_slab_from_l4slab(cache)->contiguous;
00262
00263
00264 if (cache->slab_size <= L4_PAGESIZE)
00265
00266 head = _get_free_cache_entry(is_contig);
00267
00268 if (head) {
00269
00270
00271
00272 head->page = page;
00273
00274
00275 _add_to_cache(head, is_contig);
00276 } else {
00277
00278
00279 if (is_contig)
00280
00281 ddekit_pgtab_clear_region(page, PTE_TYPE_UMA);
00282
00283
00284 l4dm_mem_release(page);
00285 }
00286 }
00287
00288
00289
00290
00291
00292 void *ddekit_slab_alloc(struct ddekit_slab * slab)
00293 {
00294 void *ret = NULL;
00295 l4lock_lock(&slab->lock);
00296 ret = l4slab_alloc(&slab->cache);
00297 l4lock_unlock(&slab->lock);
00298
00299 return ret;
00300 }
00301
00302
00303
00304
00305
00306 void ddekit_slab_free(struct ddekit_slab * slab, void *objp)
00307 {
00308 l4lock_lock(&slab->lock);
00309 l4slab_free(&slab->cache, objp);
00310 l4lock_unlock(&slab->lock);
00311 }
00312
00313
00314
00315
00316
00317 void ddekit_slab_set_data(struct ddekit_slab * slab, void *data)
00318 {
00319 l4slab_set_data(&slab->cache, data);
00320 }
00321
00322
00323
00324
00325
00326 void *ddekit_slab_get_data(struct ddekit_slab * slab)
00327 {
00328 return l4slab_get_data(&slab->cache);
00329 }
00330
00331
00332
00333
00334
00335
00336
00337 void ddekit_slab_destroy (struct ddekit_slab * slab)
00338 {
00339 l4slab_destroy(&slab->cache);
00340 ddekit_simple_free(slab);
00341 }
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352 struct ddekit_slab * ddekit_slab_init(unsigned size, int contiguous)
00353 {
00354 struct ddekit_slab * slab;
00355 int err;
00356
00357 slab = (struct ddekit_slab *) ddekit_simple_malloc(sizeof(*slab));
00358 slab->lock = L4LOCK_UNLOCKED;
00359 err = l4slab_cache_init(&slab->cache, size, 0, _slab_grow, _slab_shrink);
00360 if (err) {
00361 ddekit_debug("error initializing cache");
00362 ddekit_simple_free(slab);
00363 return 0;
00364 }
00365
00366 slab->contiguous = contiguous;
00367
00368 return slab;
00369 }
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381 void ddekit_large_free(void *objp)
00382 {
00383
00384 ddekit_pgtab_clear_region(objp, PTE_TYPE_LARGE);
00385
00386
00387 l4dm_mem_release(objp);
00388 }
00389
00390
00391
00392
00393
00394
00395
00396 void *ddekit_large_malloc(int size)
00397 {
00398 void *res;
00399 int err;
00400 l4_size_t tmp;
00401 int pages;
00402 l4dm_mem_addr_t dm_paddr;
00403
00404 size = l4_round_page(size);
00405 pages = size >> L4_PAGESHIFT;
00406
00407 res = l4dm_mem_allocate_named(size,
00408 L4DM_CONTIGUOUS | L4DM_PINNED |
00409 L4RM_MAP | L4RM_LOG2_ALIGNED,
00410 "ddekit mem");
00411 if (! res)
00412 return NULL;
00413
00414 err = l4dm_mem_phys_addr(res, 1, &dm_paddr, 1, &tmp);
00415 if (err != 1)
00416 ddekit_debug("ddekit_large_malloc: error getting physical address of new memory!\n");
00417
00418 ddekit_pgtab_set_region(res, dm_paddr.addr, pages, PTE_TYPE_LARGE);
00419
00420 return res;
00421 }
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431 void *ddekit_contig_malloc(unsigned long size,
00432 unsigned long low, unsigned long high,
00433 unsigned long alignment, unsigned long boundary)
00434 {
00435 #if 0
00436 void *res;
00437 int err;
00438 int pages;
00439 l4_size_t tmp;
00440 l4dm_mem_addr_t dm_paddr;
00441
00442 size = l4_round_page(size);
00443 pages = size >> L4_PAGESHIFT;
00444
00445 res = l4dm_mem_allocate_named(size, L4DM_CONTIGUOUS | L4DM_PINNED | L4RM_MAP | L4RM_LOG2_ALIGNED);
00446
00447 if (res) {
00448
00449
00450
00451
00452
00453
00454 err = l4dm_mem_phys_addr(res, 1, &dm_paddr, 1, &tmp);
00455 if (err != 1)
00456 ddekit_debug("contigmalloc: error getting physical address of new page!\n");
00457
00458
00459 ddekit_set_ptes(res, dm_paddr.addr, pages, PTE_TYPE_CONTIG);
00460 }
00461
00462 return res;
00463 #else
00464 ddekit_debug("%s: not implemented\n", __func__);
00465 return 0;
00466 #endif
00467 }