3 * Copyright (C) 2007 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
4 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
5 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
29 #ifdef CONFIG_MEM_ZALLOC
31 #define KMEM_HEAP_ADDR 0x200000 // MEMORY HEAP is placed on 2MB address
32 #define KMEM_MALLOC_MAGIC 0xebc9 // MALLOC STRUCTURE signature
34 #define KMEM_MALLOC_STATE_FREE 0xaa // MEMORY is FREE at moment
35 #define KMEM_MALLOC_STATE_USED 0xcc // MEMORY is USED at moment
42 } __attribute__ ((__packed__
)) malloc_t
;
45 void *addr
; /* heap structure is covered by own heap structure address */
46 void *first
; /* first malloc structure */
47 void *last
; /* last malloc structure - usefully for calculate memory usage */
48 void *curr
; /* current malloc structure */
49 } __attribute__ ((__packed__
)) heap_t
;
52 heap_t
*heap
; /* heap structure of memory */
53 MUTEX_CREATE (mutex_malloc
);
54 MUTEX_CREATE (mutex_free
);
56 void *kmalloc (size_t size
)
61 mutex_lock (&mutex_malloc
);
63 unsigned malloc_len
= sizeof (malloc_t
); /* check malloc structure size */
64 unsigned need_alloc
= 0;
66 /* let's find new or free malloc structure in memory */
68 malloc_t
*malloc
= (malloc_t
*) heap
->first
;
71 malloc
= (malloc_t
*) malloc
->next
;
73 //DPRINT ("malloc: 0x%x\n", malloc);
76 DPRINT (DBG_MM
| DBG_KMEM
, "!malloc");
81 if (malloc
->magic
!= KMEM_MALLOC_MAGIC
) {
82 DPRINT (DBG_MM
| DBG_KMEM
, "malloc->magic != KMEM_MALLOC_MAGIC");
87 if (malloc
->state
== KMEM_MALLOC_STATE_USED
) { /* It's OK */
88 //DPRINT ("DBG_MM | DBG_KMEM, malloc->state == KMEM_MALLOC_STATE_USED");
93 /* we've found FREE memory block, at moment it is not used */
94 if (malloc
->state
== KMEM_MALLOC_STATE_FREE
) {
95 /* read next malloc structure, right behind free block */
96 malloc_t
*next
= (malloc_t
*) malloc
;
98 DPRINT (DBG_MM
| DBG_KMEM
, "malloc->state == KMEM_MALLOC_STATE_FREE");
101 //kprintf ("hhhe\n");
102 next
= (malloc_t
*) next
->next
;
104 if (next
->magic
!= KMEM_MALLOC_MAGIC
) {
105 DPRINT (DBG_MM
| DBG_KMEM
, "next->magic != KMEM_MALLOC_MAGIC");
110 if (next
->state
== KMEM_MALLOC_STATE_USED
)
113 if (next
->state
!= KMEM_MALLOC_STATE_FREE
)
120 unsigned diff
= (unsigned) ((void *) next
- (void *) malloc
);
122 DPRINT (DBG_MM
| DBG_KMEM
, "diff: %d", diff
);
132 /* when old malloc structures are full, let's grab new block of memory */
135 malloc
->magic
= KMEM_MALLOC_MAGIC
;
137 malloc
->next
= (void *) ((void *) malloc
+ malloc_len
+ size
);
140 malloc
->state
= KMEM_MALLOC_STATE_USED
;
142 heap
->curr
= malloc
->next
;
144 /* save last malloc structure pointer to heap */
145 if ((unsigned) heap
->curr
> (unsigned) heap
->last
)
146 heap
->last
= heap
->curr
;
148 DPRINT (DBG_MM
| DBG_KMEM
, "malloc: 0x%x", malloc
);
150 //kprintf ("kmalloc: 0x%x : %d\n", ((void *) malloc + malloc_len), size);
152 mutex_unlock (&mutex_malloc
);
154 return (void *) ((void *) malloc
+ malloc_len
);
157 void *krealloc (void *ptr
, size_t size
)
162 void kfree (void *ptr
)
167 mutex_lock (&mutex_free
);
169 /* we need find malloc structure - it could be risk working with lower memory address */
170 malloc_t
*malloc
= (void *) ((void *) ptr
- sizeof (malloc_t
));
172 /* check malloc signature, when not agree, ptr pointing to wrong memory address */
173 if (malloc
->magic
!= KMEM_MALLOC_MAGIC
) {
174 kprintf ("free: malloc->magic != KMEM_MALLOC_MAGIC\n");
178 if (malloc
->state
== KMEM_MALLOC_STATE_FREE
) {
179 kprintf ("kfree () - memory is FREE - double free !\n");
183 if (malloc
->state
!= KMEM_MALLOC_STATE_USED
) {
184 kprintf ("malloc->state != KMEM_MALLOC_STATE_USED\n");
188 /* match malloc as FREE */
189 malloc
->state
= KMEM_MALLOC_STATE_FREE
;
191 mutex_unlock (&mutex_free
);
194 unsigned kmem_init ()
196 heap
= (heap_t
*) KMEM_HEAP_ADDR
;
198 /* we rather clear heap structure */
199 heap
->addr
= (void *) heap
;
200 heap
->first
= (void *) ((void *) heap
+ sizeof (heap_t
)); /* first malloc structure should be right behind heap structure */
201 heap
->last
= heap
->first
; /* last malloc structure - it is first at init */
202 heap
->curr
= heap
->first
; /* point to first malloc structure - well, it is clear and not used yet */
208 unsigned short kmem_get ()
211 register unsigned long *mem
;
212 unsigned long mem_count
, a
, mem_end
, bse_end
;
213 unsigned short memkb
;
214 unsigned char irq1
, irq2
;
228 // store a copy of CR0
229 asm volatile ("movl %%cr0, %%eax;" : "=a"(cr0
));
231 // invalidate the cache
232 // write-back and invalidate the cache
233 asm volatile ("wbinvd;");
235 // plug cr0 with just PE/CD/NW
236 // cache disable(486+), no-writeback(486+), 32bit mode(386+)
237 asm volatile ("movl %%eax, %%cr0;" ::
238 "a" (cr0
| 0x00000001 | 0x40000000 | 0x20000000));
242 mem_count
+= 1024*1024;
243 mem
= (unsigned long *) mem_count
;
249 /* the empty asm calls tell gcc not to rely on whats in its registers
250 as saved variables (this gets us around GCC optimisations) */
251 asm (";" ::: "memory");
252 if (*mem
!= 0x55AA55AA)
258 if (*mem
!=0xAA55AA55)
262 asm (";":::"memory");
264 } while (memkb
< 4096 && mem_count
!= 0);
266 asm volatile ("movl %%eax, %%cr0;" :: "a" (cr0
));
268 mem_end
= memkb
<< 20;
269 mem
= (unsigned long *) 0x413;
270 bse_end
= ((*mem
) &0xFFFF) << 6;
282 unsigned used
= (unsigned) heap
->last
- (unsigned) heap
->first
;
283 used
/= 1024; // convert value to kB size
285 printf ("\ttotal\tused\tfree\tshared\tbuffers\tcached\n");
286 printf ("Mem: \t%u\t%u\t%u\t%u\t%u\t%u\n",
287 mem_ext
* 1024, used
, mem_ext
* 1024 - used
, 0, 0, 0);
290 /*****************************************************************************
291 *****************************************************************************/
292 unsigned int init_mm ()
297 //mem_ext = kmem_get (); // get extended memory (in Mb)