Annotation of funnyos/kern/kern_mem.c, Revision 1.7
1.1 init 1: /*
1.7 ! init 2: * $Id: kern_mem.c,v 1.6 2007/10/26 10:59:12 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:
75: /* set break address */
76: brkaddr = physmem - (physmem / 16); /* XXX top 2MB in testarm */
77:
78: /* bytes needed to hold bitmap */
79: membmaplen = ((brkaddr - KMEM_HEAPBEGIN) / KMEM_PAGESIZE) / 8;
80:
81: /* total pages that will be available to kernel */
82: totalpages = (brkaddr - (KMEM_HEAPBEGIN + membmaplen)) / KMEM_PAGESIZE; /* XXX what about potential modulo? */
83: freepages = totalpages;
84:
85: /* allocate space for membmap in the beginning of KMEM_HEAPBEGIN */
86: bytep = (uint8_t *) KMEM_HEAPBEGIN;
87: n = membmaplen;
88:
89: while(n) {
90: /* XXX what about errors? */
91: *bytep = 0;
92: bytep++;
93:
94: n--;
95: }
96:
97: membmap = (uint8_t *)KMEM_HEAPBEGIN;
98:
99: /* skip our map; all allocations will be done starting from this */
100: allocbase = KMEM_HEAPBEGIN + membmaplen;
101:
102: printf("kmem_init: membmap @0x%x size=%d pagesize=%d; %d total pages available starting from 0x%x\n",
103: membmap, membmaplen, KMEM_PAGESIZE, totalpages, allocbase);
104: }
105:
106:
107: void
108: *kmalloc(uint32_t nbytes)
109: {
110: /*
111: * Allocate nbytes bytes of memory
112: */
113: uint32_t pagesfound, npages, nmbmbytes, firstmbmbit;
114: uint8_t *mbmbyte, mask, nmbmbits, i, offbits;
115: uint32_t *firstpageptr, *lastpageptr, mbmbit, offbytes;
116:
117:
118: /* kmalloc(0) should return NULL */
119: if (! nbytes)
120: return(NULL);
121:
122: /* pages needed to hold requested bytes */
123: npages = nbytes / KMEM_PAGESIZE + (nbytes % KMEM_PAGESIZE != 0 ? 1 : 0);
124:
125: DPRINTF("kmalloc: requested %d bytes (%d pages) of %d free pages; ", nbytes, npages, freepages);
126:
127: /* check if we have enough free pages */
1.6 init 128: if (npages > freepages) {
1.1 init 129: DPRINTF("not enough free pages\n");
130: return(NULL);
131: }
132:
133: pagesfound = 0;
134: nmbmbytes = 0;
135: /* look for contiguously available pages in memory bit map */
136: for (mbmbyte = membmap; nmbmbytes < membmaplen; nmbmbytes++) {
137:
138: mask = 0x01;
139: nmbmbits = 0; /* counts "free page" bits inside mbmbyte */
140:
141: /* check all 8 bits in mbmbyte */
142: while(mask != 0) {
143:
144: // printf("0x%x @ 0x%x & %x\n", *mbmbyte, mbmbyte, mask);
145: if ((mbmbyte[nmbmbytes] & mask) == 0) {
146: /* page is free */
147: pagesfound++;
148:
149: /* see if we need not to search more */
150: if (pagesfound == npages) {
151: /*
152: * Requested amount of pages have been found.
153: */
154:
155: /* calculate pointer to this (last) page */
156: lastpageptr = (uint32_t *)((allocbase + (8 * nmbmbytes * KMEM_PAGESIZE)) + (KMEM_PAGESIZE * nmbmbits));
157:
158: /* rewind pointer to the first byte */
159: firstpageptr = lastpageptr - ((npages - 1));
160:
161: /* fill this (npages pages) region with zeroes */
162: while(firstpageptr <= lastpageptr) {
163:
164: /* TODO invalidate page in membmap */
165: offbytes = ((uint32_t)firstpageptr - (uint32_t)allocbase) / (KMEM_PAGESIZE * 8);
1.7 ! init 166: offbits = ((uint32_t)firstpageptr - (uint32_t)allocbase) / (KMEM_PAGESIZE);
! 167:
! 168: if (offbits > 7)
! 169: offbits -= 8 * (offbits / 8);
! 170:
1.1 init 171: // printf("membmap[%d] |= 1 << %d\n", offbytes, offbits);
172: membmap[offbytes] |= 1 << offbits;
173:
174: /* zerofy page */
175: for (i = 0; i < KMEM_PAGESIZE; i++) {
1.3 init 176: *(uint8_t *)firstpageptr = KMEM_FILLBYTE;
1.1 init 177: ((uint8_t *)firstpageptr)++;
178: }
179: /* TODO rework offbits calculation */
180: offbits++;
181: if(offbits == 8)
182: /* reset to the first bit */
183: offbits = 0;
184: }
185:
186: /* rewind pointer again */
187: firstpageptr = lastpageptr - ((npages - 1));
188:
189: /* got it */
1.7 ! init 190: DPRINTF("allocated, addr=0x%x len=%d [0x%x-0x%x]\n", firstpageptr, npages * KMEM_PAGESIZE, firstpageptr, lastpageptr);
1.1 init 191:
192: /* decrement system free pages */
193: freepages -= npages;
194:
195: /* return pointer to the first byte of the allocated region */
196: return(firstpageptr);
197: }
198: } else {
199: /* encountered non-free page; reset pagesfound */
200: pagesfound = 0;
201: }
202:
203: /* shift to check next bit */
204: mask <<= 1;
205: nmbmbits++;
206: }
207:
208: }
209:
210: /* free pages haven't been found */
211: DPRINTF("not found contiguous region\n");
212:
213: return(NULL);
214: }
215:
216:
217: void
218: kfree(void *p, uint32_t nbytes)
219: {
220: /*
221: * XXX Free nbytes bytes
222: */
223: }
224:
CVSweb