Annotation of funnyos/kern/kern_mem.c, Revision 1.8
1.1 init 1: /*
1.8 ! init 2: * $Id: kern_mem.c,v 1.7 2007/10/26 13:15:20 init Exp $
1.1 init 3: */
4: #include <sys/types.h>
5: #include <sys/mem.h>
6: #include <libkern/printf.h>
7:
1.5 init 8: /* #define KMEM_DEBUG */
1.1 init 9:
10: #ifdef KMEM_DEBUG
11: #define DPRINTF(x...) do { printf(x); } while (0)
12: #else
13: #define DPRINTF(x...) { }
14: #endif
15:
16: /*
17: * Kernel memory.
18: *
19: * Our memory map looks like that (at least for testarm with 32MB):
20: * (0MB) 0x00000000 | interrupt vectors (actually kernel text)
21: * ...
22: * 0x00000020 | kernel text (continue)
23: * ...
24: * 0x000fffff | END of kernel text
25: *
26: * (1MB) 0x00100000 | kernel data
27: * ... (1MB of kernel data)
28: * 0x001fffff | END of kernel data
29: *
30: * (2MB) 0x00200000 | heap start (grows downwards)
31: * ... (28MB of heap)
32: *
33: * (30MB) 0x01e00000 <---- brk address
34: *
35: * ... (2MB of stack)
36: * (32MB) 0x01ffffff | stack pointer (grows upwards)
37: *
38: * XXX very-very tiny memory model for my at91sam7s64
39: */
40:
41: /* config.c exports us ammount of available physical memory. */
42: extern uint32_t physmem;
43:
44: /* break address */
45: //uint32_t brkaddr = (KMEM_HEAPBEGIN + (physmem - KMEM_HEAPBEGIN) / 2)
46: // + (physmem - KMEM_HEAPBEGIN)
47: uint32_t brkaddr;
48:
49: /* from where to allocate memory in kmalloc() */
50: uint32_t allocbase;
51:
52: /* stack pointer */
53: uint32_t sp;
54:
55: /* memory bit map pointer and its length */
56: uint8_t *membmap;
57: uint32_t membmaplen;
58:
59: /* pages statistics */
60: uint32_t totalpages;
61: uint32_t freepages;
62:
63:
64: void
65: kmem_init(void)
66: {
67: /*
68: * Initialize kernel memory (de)allocation subsystem.
69: * This allocates bit map, each BIT of it represents one kmem page.
70: * kmem page is KMEM_PAGESIZE bytes length and may be 0 (free) or 1 (not free) in membmap.
71: */
72: int32_t n;
73: uint8_t *bytep;
74:
1.8 ! init 75: #ifdef ARCH_SAM7S64
! 76: /* XXX UGLY HACK */
! 77: brkaddr = 0x00203800;
! 78: #else
1.1 init 79: /* set break address */
80: brkaddr = physmem - (physmem / 16); /* XXX top 2MB in testarm */
1.8 ! init 81: #endif
1.1 init 82: /* bytes needed to hold bitmap */
83: membmaplen = ((brkaddr - KMEM_HEAPBEGIN) / KMEM_PAGESIZE) / 8;
84:
85: /* total pages that will be available to kernel */
86: totalpages = (brkaddr - (KMEM_HEAPBEGIN + membmaplen)) / KMEM_PAGESIZE; /* XXX what about potential modulo? */
87: freepages = totalpages;
88:
89: /* allocate space for membmap in the beginning of KMEM_HEAPBEGIN */
90: bytep = (uint8_t *) KMEM_HEAPBEGIN;
91: n = membmaplen;
92:
93: while(n) {
94: /* XXX what about errors? */
95: *bytep = 0;
96: bytep++;
97:
98: n--;
99: }
100:
101: membmap = (uint8_t *)KMEM_HEAPBEGIN;
102:
103: /* skip our map; all allocations will be done starting from this */
104: allocbase = KMEM_HEAPBEGIN + membmaplen;
105:
106: printf("kmem_init: membmap @0x%x size=%d pagesize=%d; %d total pages available starting from 0x%x\n",
107: membmap, membmaplen, KMEM_PAGESIZE, totalpages, allocbase);
108: }
109:
110:
111: void
112: *kmalloc(uint32_t nbytes)
113: {
114: /*
115: * Allocate nbytes bytes of memory
116: */
117: uint32_t pagesfound, npages, nmbmbytes, firstmbmbit;
118: uint8_t *mbmbyte, mask, nmbmbits, i, offbits;
119: uint32_t *firstpageptr, *lastpageptr, mbmbit, offbytes;
120:
121:
122: /* kmalloc(0) should return NULL */
123: if (! nbytes)
124: return(NULL);
125:
126: /* pages needed to hold requested bytes */
127: npages = nbytes / KMEM_PAGESIZE + (nbytes % KMEM_PAGESIZE != 0 ? 1 : 0);
128:
129: DPRINTF("kmalloc: requested %d bytes (%d pages) of %d free pages; ", nbytes, npages, freepages);
130:
131: /* check if we have enough free pages */
1.6 init 132: if (npages > freepages) {
1.1 init 133: DPRINTF("not enough free pages\n");
134: return(NULL);
135: }
136:
137: pagesfound = 0;
138: nmbmbytes = 0;
139: /* look for contiguously available pages in memory bit map */
140: for (mbmbyte = membmap; nmbmbytes < membmaplen; nmbmbytes++) {
141:
142: mask = 0x01;
143: nmbmbits = 0; /* counts "free page" bits inside mbmbyte */
144:
145: /* check all 8 bits in mbmbyte */
146: while(mask != 0) {
147:
148: // printf("0x%x @ 0x%x & %x\n", *mbmbyte, mbmbyte, mask);
149: if ((mbmbyte[nmbmbytes] & mask) == 0) {
150: /* page is free */
151: pagesfound++;
152:
153: /* see if we need not to search more */
154: if (pagesfound == npages) {
155: /*
156: * Requested amount of pages have been found.
157: */
158:
159: /* calculate pointer to this (last) page */
160: lastpageptr = (uint32_t *)((allocbase + (8 * nmbmbytes * KMEM_PAGESIZE)) + (KMEM_PAGESIZE * nmbmbits));
161:
162: /* rewind pointer to the first byte */
163: firstpageptr = lastpageptr - ((npages - 1));
164:
165: /* fill this (npages pages) region with zeroes */
166: while(firstpageptr <= lastpageptr) {
167:
168: /* TODO invalidate page in membmap */
169: offbytes = ((uint32_t)firstpageptr - (uint32_t)allocbase) / (KMEM_PAGESIZE * 8);
1.7 init 170: offbits = ((uint32_t)firstpageptr - (uint32_t)allocbase) / (KMEM_PAGESIZE);
171:
172: if (offbits > 7)
173: offbits -= 8 * (offbits / 8);
174:
1.1 init 175: // printf("membmap[%d] |= 1 << %d\n", offbytes, offbits);
176: membmap[offbytes] |= 1 << offbits;
177:
178: /* zerofy page */
179: for (i = 0; i < KMEM_PAGESIZE; i++) {
1.3 init 180: *(uint8_t *)firstpageptr = KMEM_FILLBYTE;
1.1 init 181: ((uint8_t *)firstpageptr)++;
182: }
183: /* TODO rework offbits calculation */
184: offbits++;
185: if(offbits == 8)
186: /* reset to the first bit */
187: offbits = 0;
188: }
189:
190: /* rewind pointer again */
191: firstpageptr = lastpageptr - ((npages - 1));
192:
193: /* got it */
1.7 init 194: DPRINTF("allocated, addr=0x%x len=%d [0x%x-0x%x]\n", firstpageptr, npages * KMEM_PAGESIZE, firstpageptr, lastpageptr);
1.1 init 195:
196: /* decrement system free pages */
197: freepages -= npages;
198:
199: /* return pointer to the first byte of the allocated region */
200: return(firstpageptr);
201: }
202: } else {
203: /* encountered non-free page; reset pagesfound */
204: pagesfound = 0;
205: }
206:
207: /* shift to check next bit */
208: mask <<= 1;
209: nmbmbits++;
210: }
211:
212: }
213:
214: /* free pages haven't been found */
215: DPRINTF("not found contiguous region\n");
216:
217: return(NULL);
218: }
219:
220:
221: void
222: kfree(void *p, uint32_t nbytes)
223: {
224: /*
225: * XXX Free nbytes bytes
226: */
227: }
228:
CVSweb