Rev 367 | Rev 373 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 367 | Rev 368 | ||
---|---|---|---|
Line 24... | Line 24... | ||
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | */ |
27 | */ |
28 | 28 | ||
- | 29 | #include <typedefs.h> |
|
29 | #include <arch/types.h> |
30 | #include <arch/types.h> |
30 | #include <func.h> |
- | |
31 | - | ||
32 | #include <mm/heap.h> |
31 | #include <mm/heap.h> |
33 | #include <mm/frame.h> |
32 | #include <mm/frame.h> |
34 | #include <mm/page.h> |
- | |
35 | #include <mm/vm.h> |
33 | #include <mm/vm.h> |
36 | #include <arch/mm/page.h> |
- | |
37 | - | ||
38 | #include <config.h> |
- | |
39 | #include <memstr.h> |
- | |
40 | - | ||
41 | #include <panic.h> |
34 | #include <panic.h> |
42 | #include <debug.h> |
35 | #include <debug.h> |
43 | - | ||
- | 36 | #include <list.h> |
|
44 | #include <synch/spinlock.h> |
37 | #include <synch/spinlock.h> |
45 | - | ||
46 | #include <arch/asm.h> |
38 | #include <arch/asm.h> |
47 | #include <arch.h> |
39 | #include <arch.h> |
48 | 40 | ||
49 | count_t frames = 0; |
- | |
50 | count_t frames_free; |
- | |
51 | - | ||
52 | __u8 *frame_bitmap; |
- | |
53 | count_t frame_bitmap_octets; |
- | |
54 | - | ||
55 | static spinlock_t framelock; |
- | |
56 | - | ||
57 | spinlock_t zone_head_lock; /**< this lock protects zone_head list */ |
41 | spinlock_t zone_head_lock; /**< this lock protects zone_head list */ |
58 | link_t zone_head; /**< list of all zones in the system */ |
42 | link_t zone_head; /**< list of all zones in the system */ |
59 | 43 | ||
- | 44 | /** Initialize physical memory management |
|
60 | 45 | * |
|
- | 46 | * Initialize physical memory managemnt. |
|
- | 47 | */ |
|
61 | void frame_init(void) |
48 | void frame_init(void) |
62 | { |
49 | { |
63 | if (config.cpu_active == 1) { |
50 | if (config.cpu_active == 1) { |
64 | zone_init(); |
51 | zone_init(); |
65 | - | ||
66 | /* |
- | |
67 | * The bootstrap processor will allocate all necessary memory for frame allocation. |
- | |
68 | */ |
- | |
69 | - | ||
70 | frames = config.memory_size / FRAME_SIZE; |
- | |
71 | frame_bitmap_octets = frames / 8 + (frames % 8 > 0); |
- | |
72 | frame_bitmap = (__u8 *) malloc(frame_bitmap_octets); |
- | |
73 | if (!frame_bitmap) |
- | |
74 | panic("malloc/frame_bitmap\n"); |
- | |
75 | - | ||
76 | /* |
- | |
77 | * Mark all frames free. |
- | |
78 | */ |
- | |
79 | memsetb((__address) frame_bitmap, frame_bitmap_octets, 0); |
- | |
80 | frames_free = frames; |
- | |
81 | } |
52 | } |
82 | 53 | ||
83 | /* |
- | |
84 | * No frame allocations/reservations prior this point. |
- | |
85 | */ |
- | |
86 | - | ||
87 | frame_arch_init(); |
54 | frame_arch_init(); |
88 | 55 | ||
89 | if (config.cpu_active == 1) { |
56 | if (config.cpu_active == 1) { |
90 | /* |
- | |
91 | * Create the memory address space map. Marked frames and frame |
- | |
92 | * regions cannot be used for allocation. |
- | |
93 | */ |
- | |
94 | frame_region_not_free(config.base, config.base + config.kernel_size); |
57 | frame_region_not_free(config.base, config.base + config.kernel_size + CONFIG_STACK_SIZE); |
95 | } |
58 | } |
96 | } |
59 | } |
97 | 60 | ||
- | 61 | /** Allocate a frame |
|
- | 62 | * |
|
- | 63 | * Allocate a frame of physical memory. |
|
98 | /* |
64 | * |
- | 65 | * @param flags Flags for host zone selection and address processing. |
|
- | 66 | * |
|
99 | * Allocate a frame. |
67 | * @return Allocated frame. |
100 | */ |
68 | */ |
101 | __address frame_alloc(int flags) |
69 | __address frame_alloc(int flags) |
102 | { |
70 | { |
103 | int i; |
- | |
104 | pri_t pri; |
71 | pri_t pri; |
- | 72 | link_t *cur, *tmp; |
|
- | 73 | zone_t *z; |
|
- | 74 | zone_t *zone = NULL; |
|
- | 75 | frame_t *frame = NULL; |
|
- | 76 | __address v; |
|
105 | 77 | ||
106 | loop: |
78 | loop: |
107 | pri = cpu_priority_high(); |
79 | pri = cpu_priority_high(); |
108 | spinlock_lock(&framelock); |
80 | spinlock_lock(&zone_head_lock); |
109 | if (frames_free) { |
- | |
110 | for (i=0; i < frames; i++) { |
- | |
111 | int m, n; |
- | |
112 | 81 | ||
113 | m = i / 8; |
82 | /* |
114 | n = i % 8; |
83 | * First, find suitable frame zone. |
115 | 84 | */ |
|
116 | if ((frame_bitmap[m] & (1<<n)) == 0) { |
85 | for (cur = zone_head.next; cur != &zone_head; cur = cur->next) { |
117 | frame_bitmap[m] |= (1<<n); |
86 | z = list_get_instance(cur, zone_t, link); |
118 | frames_free--; |
87 | |
119 | spinlock_unlock(&framelock); |
88 | spinlock_lock(&z->lock); |
- | 89 | /* |
|
120 | cpu_priority_restore(pri); |
90 | * Check if the zone has any free frames. |
- | 91 | */ |
|
121 | if (flags & FRAME_KA) return PA2KA(i*FRAME_SIZE); |
92 | if (z->free_count) { |
122 | return i*FRAME_SIZE; |
93 | zone = z; |
123 | } |
94 | break; |
124 | } |
95 | } |
125 | panic("frames_free inconsistent (%d)\n", frames_free); |
96 | spinlock_unlock(&z->lock); |
126 | } |
97 | } |
127 | spinlock_unlock(&framelock); |
- | |
128 | cpu_priority_restore(pri); |
- | |
129 | 98 | ||
- | 99 | if (!zone) { |
|
130 | if (flags & FRAME_PANIC) |
100 | if (flags & FRAME_PANIC) |
131 | panic("unable to allocate frame\n"); |
101 | panic("Can't allocate frame.\n"); |
132 | 102 | ||
- | 103 | /* |
|
133 | /* TODO: implement sleeping logic here */ |
104 | * TODO: Sleep until frames are available again. |
- | 105 | */ |
|
- | 106 | spinlock_unlock(&zone_head_lock); |
|
134 | panic("sleep not supported\n"); |
107 | cpu_priority_restore(pri); |
135 | 108 | ||
- | 109 | panic("Sleep not implemented.\n"); |
|
136 | goto loop; |
110 | goto loop; |
137 | } |
111 | } |
138 | 112 | ||
- | 113 | tmp = zone->free_head.next; |
|
- | 114 | frame = list_get_instance(tmp, frame_t, link); |
|
- | 115 | ||
- | 116 | frame->refcount++; |
|
- | 117 | list_remove(tmp); /* remove frame from free_head */ |
|
- | 118 | list_append(tmp, &zone->busy_head); /* append frame to busy_head */ |
|
- | 119 | zone->free_count--; |
|
- | 120 | zone->busy_count++; |
|
- | 121 | ||
- | 122 | v = zone->base + (frame - zone->frames) * FRAME_SIZE; |
|
139 | /* |
123 | |
- | 124 | if (flags & FRAME_KA) |
|
- | 125 | v = PA2KA(v); |
|
- | 126 | ||
- | 127 | spinlock_unlock(&zone->lock); |
|
- | 128 | ||
- | 129 | spinlock_unlock(&zone_head_lock); |
|
- | 130 | cpu_priority_restore(pri); |
|
- | 131 | ||
- | 132 | return v; |
|
- | 133 | } |
|
- | 134 | ||
140 | * Free a frame. |
135 | /** Free a frame. |
- | 136 | * |
|
- | 137 | * Find respective frame structrue for supplied addr. |
|
- | 138 | * Decrement frame reference count. |
|
- | 139 | * If it drops to zero, move the frame structure to free list. |
|
- | 140 | * |
|
- | 141 | * @param addr Address of the frame to be freed. It must be a multiple of FRAME_SIZE. |
|
141 | */ |
142 | */ |
142 | void frame_free(__address addr) |
143 | void frame_free(__address addr) |
143 | { |
144 | { |
144 | pri_t pri; |
145 | pri_t pri; |
- | 146 | link_t *cur; |
|
- | 147 | zone_t *z; |
|
- | 148 | zone_t *zone = NULL; |
|
145 | __u32 frame; |
149 | frame_t *frame; |
- | 150 | ||
- | 151 | ASSERT(addr % FRAME_SIZE == 0); |
|
146 | 152 | ||
147 | pri = cpu_priority_high(); |
153 | pri = cpu_priority_high(); |
148 | spinlock_lock(&framelock); |
154 | spinlock_lock(&zone_head_lock); |
- | 155 | ||
- | 156 | /* |
|
- | 157 | * First, find host frame zone for addr. |
|
- | 158 | */ |
|
- | 159 | for (cur = zone_head.next; cur != &zone_head; cur = cur->next) { |
|
- | 160 | z = list_get_instance(cur, zone_t, link); |
|
149 | 161 | ||
150 | frame = IS_KA(addr) ? KA2PA(addr) : addr; |
- | |
151 | frame /= FRAME_SIZE; |
- | |
152 | if (frame < frames) { |
162 | spinlock_lock(&z->lock); |
153 | int m, n; |
- | |
154 | 163 | ||
155 | m = frame / 8; |
164 | if (IS_KA(addr)) |
156 | n = frame % 8; |
165 | addr = KA2PA(addr); |
157 | 166 | ||
- | 167 | /* |
|
158 | if (frame_bitmap[m] & (1<<n)) { |
168 | * Check if addr belongs to z. |
- | 169 | */ |
|
- | 170 | if ((addr >= z->base) && (addr <= z->base + (z->free_count + z->busy_count) * FRAME_SIZE)) { |
|
159 | frame_bitmap[m] &= ~(1<<n); |
171 | zone = z; |
160 | frames_free++; |
172 | break; |
- | 173 | } |
|
- | 174 | spinlock_unlock(&z->lock); |
|
161 | } |
175 | } |
- | 176 | ||
- | 177 | ASSERT(zone != NULL); |
|
- | 178 | ||
- | 179 | frame = &zone->frames[(addr - zone->base)/FRAME_SIZE]; |
|
162 | else panic("frame already free\n"); |
180 | ASSERT(frame->refcount); |
- | 181 | ||
- | 182 | if (!--frame->refcount) { |
|
- | 183 | list_remove(&frame->link); /* remove frame from busy_head */ |
|
- | 184 | list_append(&frame->link, &zone->free_head); /* append frame to free_head */ |
|
- | 185 | zone->free_count++; |
|
- | 186 | zone->busy_count--; |
|
163 | } |
187 | } |
164 | else panic("frame number too big\n"); |
- | |
165 | 188 | ||
166 | spinlock_unlock(&framelock); |
189 | spinlock_unlock(&zone->lock); |
- | 190 | ||
- | 191 | spinlock_unlock(&zone_head_lock); |
|
167 | cpu_priority_restore(pri); |
192 | cpu_priority_restore(pri); |
168 | } |
193 | } |
169 | 194 | ||
- | 195 | /** Mark frame not free. |
|
170 | /* |
196 | * |
171 | * Don't use this function for normal allocation. Use frame_alloc() instead. |
197 | * Find respective frame structrue for supplied addr. |
172 | * Use this function to declare that some special frame is not free. |
198 | * Increment frame reference count and move the frame structure to busy list. |
- | 199 | * |
|
- | 200 | * @param addr Address of the frame to be marked. It must be a multiple of FRAME_SIZE. |
|
173 | */ |
201 | */ |
174 | void frame_not_free(__address addr) |
202 | void frame_not_free(__address addr) |
175 | { |
203 | { |
176 | pri_t pri; |
204 | pri_t pri; |
- | 205 | link_t *cur; |
|
- | 206 | zone_t *z; |
|
- | 207 | zone_t *zone = NULL; |
|
177 | __u32 frame; |
208 | frame_t *frame; |
- | 209 | ||
- | 210 | ASSERT(addr % FRAME_SIZE == 0); |
|
178 | 211 | ||
179 | pri = cpu_priority_high(); |
212 | pri = cpu_priority_high(); |
180 | spinlock_lock(&framelock); |
213 | spinlock_lock(&zone_head_lock); |
181 | frame = IS_KA(addr) ? KA2PA(addr) : addr; |
- | |
182 | frame /= FRAME_SIZE; |
- | |
183 | if (frame < frames) { |
- | |
184 | int m, n; |
- | |
185 | 214 | ||
- | 215 | /* |
|
186 | m = frame / 8; |
216 | * First, find host frame zone for addr. |
- | 217 | */ |
|
- | 218 | for (cur = zone_head.next; cur != &zone_head; cur = cur->next) { |
|
- | 219 | z = list_get_instance(cur, zone_t, link); |
|
- | 220 | ||
187 | n = frame % 8; |
221 | spinlock_lock(&z->lock); |
188 | 222 | ||
- | 223 | if (IS_KA(addr)) |
|
- | 224 | addr = KA2PA(addr); |
|
- | 225 | ||
- | 226 | /* |
|
189 | if ((frame_bitmap[m] & (1<<n)) == 0) { |
227 | * Check if addr belongs to z. |
- | 228 | */ |
|
- | 229 | if ((addr >= z->base) && (addr <= z->base + (z->free_count + z->busy_count) * FRAME_SIZE)) { |
|
190 | frame_bitmap[m] |= (1<<n); |
230 | zone = z; |
191 | frames_free--; |
231 | break; |
192 | } |
232 | } |
- | 233 | spinlock_unlock(&z->lock); |
|
- | 234 | } |
|
- | 235 | ||
- | 236 | ASSERT(zone != NULL); |
|
- | 237 | ||
- | 238 | frame = &zone->frames[(addr - zone->base)/FRAME_SIZE]; |
|
- | 239 | ||
- | 240 | if (!frame->refcount) { |
|
- | 241 | frame->refcount++; |
|
- | 242 | ||
- | 243 | list_remove(&frame->link); /* remove frame from free_head */ |
|
- | 244 | list_append(&frame->link, &zone->busy_head); /* append frame to busy_head */ |
|
- | 245 | zone->free_count--; |
|
- | 246 | zone->busy_count++; |
|
193 | } |
247 | } |
- | 248 | ||
194 | spinlock_unlock(&framelock); |
249 | spinlock_unlock(&zone->lock); |
- | 250 | ||
- | 251 | spinlock_unlock(&zone_head_lock); |
|
195 | cpu_priority_restore(pri); |
252 | cpu_priority_restore(pri); |
196 | } |
253 | } |
197 | 254 | ||
- | 255 | /** Mark frame region not free. |
|
- | 256 | * |
|
- | 257 | * Mark frame region not free. |
|
- | 258 | * |
|
- | 259 | * @param start First address. |
|
- | 260 | * @param stop Last address. |
|
- | 261 | */ |
|
198 | void frame_region_not_free(__address start, __address stop) |
262 | void frame_region_not_free(__address start, __address stop) |
199 | { |
263 | { |
200 | __address a; |
264 | __address a; |
201 | 265 | ||
202 | start /= FRAME_SIZE; |
266 | start /= FRAME_SIZE; |
203 | stop /= FRAME_SIZE; |
267 | stop /= FRAME_SIZE; |
204 | for (a = start; a <= stop; a++) |
268 | for (a = start; a <= stop; a++) |
205 | frame_not_free(a * FRAME_SIZE); |
269 | frame_not_free(a * FRAME_SIZE); |
206 | } |
270 | } |
207 | 271 | ||
- | 272 | ||
208 | /** Initialize zonekeeping |
273 | /** Initialize zonekeeping |
209 | * |
274 | * |
210 | * Initialize zonekeeping. |
275 | * Initialize zonekeeping. |
211 | */ |
276 | */ |
212 | void zone_init(void) |
277 | void zone_init(void) |
Line 294... | Line 359... | ||
294 | */ |
359 | */ |
295 | void frame_initialize(frame_t *frame, zone_t *zone) |
360 | void frame_initialize(frame_t *frame, zone_t *zone) |
296 | { |
361 | { |
297 | frame->refcount = 0; |
362 | frame->refcount = 0; |
298 | link_initialize(&frame->link); |
363 | link_initialize(&frame->link); |
299 | frame->zone = zone; |
- | |
300 | } |
- | |
301 | - | ||
302 | /** Get address of physical frame from its frame structure |
- | |
303 | * |
- | |
304 | * Get address of physical frame from its frame structure. |
- | |
305 | * |
- | |
306 | * @param frame Frame structure of the queried frame address. |
- | |
307 | * |
- | |
308 | * @return Address of frame associated with the argument. |
- | |
309 | */ |
- | |
310 | __address frame_get_address(frame_t *frame) |
- | |
311 | { |
- | |
312 | __address v; |
- | |
313 | zone_t *z; |
- | |
314 | pri_t pri; |
- | |
315 | - | ||
316 | z = frame->zone; |
- | |
317 | - | ||
318 | pri = cpu_priority_high(); |
- | |
319 | spinlock_lock(&z->lock); |
- | |
320 | - | ||
321 | v = z->base + (frame - z->frames) * FRAME_SIZE; |
- | |
322 | - | ||
323 | if (z->flags & FRAME_KA) |
- | |
324 | v = PA2KA(v); |
- | |
325 | - | ||
326 | spinlock_unlock(&z->lock); |
- | |
327 | cpu_priority_restore(pri); |
- | |
328 | - | ||
329 | return v; |
- | |
330 | } |
364 | } |