]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/dde/linux26/lib/src/arch/l4/kmalloc.c
update
[l4.git] / l4 / pkg / dde / linux26 / lib / src / arch / l4 / kmalloc.c
1 /*
2  * This file is part of DDE/Linux2.6.
3  *
4  * (c) 2006-2010 Bjoern Doebel <doebel@os.inf.tu-dresden.de>
5  *               Christian Helmuth <ch12@os.inf.tu-dresden.de>
6  *     economic rights: Technische Universitaet Dresden (Germany)
7  *
8  * This file is part of TUD:OS and distributed under the terms of the
9  * GNU General Public License 2.
10  * Please see the COPYING-GPL-2 file for details.
11  */
12
13 /*
14  * \brief   kmalloc() implementation
15  *
16  * In Linux 2.6 this resides in mm/slab.c.
17  *
18  * This implementation of kmalloc() stays with Linux's and uses kmem_caches for
19  * some power of two bytes. For larger allocations ddedkit_large_malloc() is
20  * used. This way, we optimize for speed and potentially waste memory
21  * resources.
22  */
23
24 /* Linux */
25 #include <linux/slab.h>
26 #include <linux/types.h>
27 #include <linux/bootmem.h>
28 #include <linux/module.h>
29 #include <linux/pci.h>
30 #include <linux/mm.h>
31 #include <asm/io.h>
32
33 /* DDEKit */
34 #include <l4/dde/ddekit/debug.h>
35 #include <l4/dde/ddekit/memory.h>
36
37 #include <l4/dde/linux26/dde26.h>
38
39 /* dummy */
40 int forbid_dac;
41
42 /* This stuff is needed by some drivers, e.g. for ethtool.
43  * XXX: This is a fake, implement it if you really need ethtool stuff.
44  */
45 struct page* mem_map = NULL;
46 static bootmem_data_t contig_bootmem_data;
47 struct pglist_data contig_page_data = { .bdata = &contig_bootmem_data };
48
49 int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,
50                     unsigned long pfn, unsigned long size, pgprot_t prot)
51 {
52         return 0;
53 }
54 EXPORT_SYMBOL(remap_pfn_range);
55
56 /*******************
57  ** Configuration **
58  *******************/
59
60 #define DEBUG_MALLOC 0
61
62 /********************
63  ** Implementation **
64  ********************/
65
66 /*
67  * These are the default caches for kmalloc. Custom caches can have other sizes.
68  */
69 static struct cache_sizes malloc_sizes[] = {
70 #define CACHE(x) { .cs_size = (x) },
71 #include <linux/kmalloc_sizes.h>
72         CACHE(ULONG_MAX)
73 #undef CACHE
74 };
75
76
77 /*
78  * kmalloc() cache names
79  */
80 static const char *malloc_names[] = {
81 #define CACHE(x) "size-" #x,
82 #include <linux/kmalloc_sizes.h>
83         NULL
84 #undef CACHE
85 };
86
87
88 /**
89  * Find kmalloc() cache for size
90  */
91 static struct kmem_cache *find_cache(size_t size)
92 {
93         struct cache_sizes *sizes;
94
95         for (sizes = malloc_sizes; size > sizes->cs_size; ++sizes) ;
96
97         return sizes->cs_cachep;
98 }
99
100
101 /**
102  * Free previously allocated memory
103  * @objp: pointer returned by kmalloc.
104  *
105  * If @objp is NULL, no operation is performed.
106  *
107  * Don't free memory not originally allocated by kmalloc()
108  * or you will run into trouble.
109  */
110 void kfree(const void *objp)
111 {
112         if (!objp) return;
113
114         /* find cache back-pointer */
115         void **p = (void **)objp - 1;
116
117         ddekit_log(DEBUG_MALLOC, "objp=%p cache=%p (%d)",
118                    p, *p, *p ? kmem_cache_size(*p) : 0);
119
120         if (*p)
121                 /* free from cache */
122                 kmem_cache_free(*p, p);
123         else
124                 /* no cache for this size - use ddekit free */
125                 ddekit_large_free(p);
126 }
127
128
129 /**
130  * Allocate memory
131  * @size: how many bytes of memory are required.
132  * @flags: the type of memory to allocate.
133  *
134  * kmalloc is the normal method of allocating memory
135  * in the kernel.
136  */
137 void *__kmalloc(size_t size, gfp_t flags)
138 {
139         /* add space for back-pointer */
140         size += sizeof(void *);
141
142         /* find appropriate cache */
143         struct kmem_cache *cache = find_cache(size);
144
145         void **p;
146         if (cache)
147                 /* allocate from cache */
148                 p = kmem_cache_alloc(cache, flags);
149         else
150                 /* no cache for this size - use ddekit malloc */
151                 p = ddekit_large_malloc(size);
152
153         ddekit_log(DEBUG_MALLOC, "size=%d, cache=%p (%d) => %p",
154                    size, cache, cache ? kmem_cache_size(cache) : 0, p);
155
156         /* return pointer to actual chunk */
157         if (p) {
158                 *p = cache;
159                 p++;
160         }
161
162         /* Need to zero out mem? */
163         if (p && (flags & __GFP_ZERO)) {
164                 size -= sizeof(void*);
165                 memset(p, 0, size);
166         }
167
168         return p;
169 }
170
171
172 size_t ksize(const void *p)
173 {
174         struct kmem_cache *cache = (struct kmem_cache *)*((void**)p - 1);
175         if (cache)
176                 return kmem_cache_size(cache);
177         return -1;
178 }
179
180
181 void *dma_alloc_coherent(struct device *dev, size_t size, 
182                          dma_addr_t *dma_handle, gfp_t flag)
183 {
184         void *ret = (void *)__get_free_pages(flag, get_order(size));
185
186         if (ret != NULL) {
187                 memset(ret, 0, size);
188                 *dma_handle = virt_to_bus(ret);
189         }
190         return ret;
191 }
192
193
194 void dma_free_coherent(struct device *dev, size_t size,
195                        void *vaddr, dma_addr_t dma_handle)
196 {
197         free_pages((unsigned long)vaddr, get_order(size));
198 }
199
200 #ifdef ARCH_arm
201 #include <l4/sys/cache.h>
202 void dma_cache_maint(const void *start, size_t size, int direction)
203 {
204         l4_cache_dma_coherent((unsigned long)start, (unsigned long)start + size);
205 }
206 #endif
207
208
209 /********************
210  ** Initialization **
211  ********************/
212
213 /**
214  * dde_linux kmalloc initialization
215  */
216 void l4dde26_kmalloc_init(void)
217 {
218         struct cache_sizes  *sizes = malloc_sizes;
219         const char         **names = malloc_names;
220
221         /* init malloc sizes array */
222         for (; sizes->cs_size != ULONG_MAX; ++sizes, ++names)
223                 sizes->cs_cachep = kmem_cache_create(*names, sizes->cs_size, 0, 0, 0);
224 }