source: mainline/src/mm/frame.c@ fcacfb7

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since fcacfb7 was fcacfb7, checked in by Jakub Jermar <jakub@…>, 20 years ago

Physical memory management work.
Implement zone_*() and some frame_*() functions.

  • Property mode set to 100644
File size: 7.1 KB
Line 
1/*
2 * Copyright (C) 2001-2004 Jakub Jermar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
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
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <arch/types.h>
30#include <func.h>
31
32#include <mm/heap.h>
33#include <mm/frame.h>
34#include <mm/page.h>
35#include <mm/vm.h>
36#include <arch/mm/page.h>
37
38#include <config.h>
39#include <memstr.h>
40
41#include <panic.h>
42#include <debug.h>
43
44#include <synch/spinlock.h>
45
46#include <arch/asm.h>
47#include <arch.h>
48
49count_t frames = 0;
50count_t frames_free;
51
52__u8 *frame_bitmap;
53count_t frame_bitmap_octets;
54
55static spinlock_t framelock;
56
57spinlock_t zone_head_lock; /**< this lock protects zone_head list */
58link_t zone_head; /**< list of all zones in the system */
59
60
61void frame_init(void)
62{
63 if (config.cpu_active == 1) {
64 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 }
82
83 /*
84 * No frame allocations/reservations prior this point.
85 */
86
87 frame_arch_init();
88
89 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);
95 }
96}
97
98/*
99 * Allocate a frame.
100 */
101__address frame_alloc(int flags)
102{
103 int i;
104 pri_t pri;
105
106loop:
107 pri = cpu_priority_high();
108 spinlock_lock(&framelock);
109 if (frames_free) {
110 for (i=0; i < frames; i++) {
111 int m, n;
112
113 m = i / 8;
114 n = i % 8;
115
116 if ((frame_bitmap[m] & (1<<n)) == 0) {
117 frame_bitmap[m] |= (1<<n);
118 frames_free--;
119 spinlock_unlock(&framelock);
120 cpu_priority_restore(pri);
121 if (flags & FRAME_KA) return PA2KA(i*FRAME_SIZE);
122 return i*FRAME_SIZE;
123 }
124 }
125 panic("frames_free inconsistent (%d)\n", frames_free);
126 }
127 spinlock_unlock(&framelock);
128 cpu_priority_restore(pri);
129
130 if (flags & FRAME_PANIC)
131 panic("unable to allocate frame\n");
132
133 /* TODO: implement sleeping logic here */
134 panic("sleep not supported\n");
135
136 goto loop;
137}
138
139/*
140 * Free a frame.
141 */
142void frame_free(__address addr)
143{
144 pri_t pri;
145 __u32 frame;
146
147 pri = cpu_priority_high();
148 spinlock_lock(&framelock);
149
150 frame = IS_KA(addr) ? KA2PA(addr) : addr;
151 frame /= FRAME_SIZE;
152 if (frame < frames) {
153 int m, n;
154
155 m = frame / 8;
156 n = frame % 8;
157
158 if (frame_bitmap[m] & (1<<n)) {
159 frame_bitmap[m] &= ~(1<<n);
160 frames_free++;
161 }
162 else panic("frame already free\n");
163 }
164 else panic("frame number too big\n");
165
166 spinlock_unlock(&framelock);
167 cpu_priority_restore(pri);
168}
169
170/*
171 * Don't use this function for normal allocation. Use frame_alloc() instead.
172 * Use this function to declare that some special frame is not free.
173 */
174void frame_not_free(__address addr)
175{
176 pri_t pri;
177 __u32 frame;
178
179 pri = cpu_priority_high();
180 spinlock_lock(&framelock);
181 frame = IS_KA(addr) ? KA2PA(addr) : addr;
182 frame /= FRAME_SIZE;
183 if (frame < frames) {
184 int m, n;
185
186 m = frame / 8;
187 n = frame % 8;
188
189 if ((frame_bitmap[m] & (1<<n)) == 0) {
190 frame_bitmap[m] |= (1<<n);
191 frames_free--;
192 }
193 }
194 spinlock_unlock(&framelock);
195 cpu_priority_restore(pri);
196}
197
198void frame_region_not_free(__address start, __address stop)
199{
200 __address a;
201
202 start /= FRAME_SIZE;
203 stop /= FRAME_SIZE;
204 for (a = start; a <= stop; a++)
205 frame_not_free(a * FRAME_SIZE);
206}
207
208/** Initialize zonekeeping
209 *
210 * Initialize zonekeeping.
211 */
212void zone_init(void)
213{
214 spinlock_initialize(&zone_head_lock);
215 list_initialize(&zone_head);
216}
217
218/** Create frame zone
219 *
220 * Create new frame zone.
221 *
222 * @param start Physical address of the first frame within the zone.
223 * @param size Size of the zone. Must be a multiple of FRAME_SIZE.
224 * @param flags Zone flags.
225 *
226 * @return Initialized zone.
227 */
228zone_t *zone_create(__address start, size_t size, int flags)
229{
230 zone_t *z;
231 count_t cnt;
232 int i;
233
234 ASSERT(start % FRAME_SIZE == 0);
235 ASSERT(size % FRAME_SIZE == 0);
236
237 cnt = size / FRAME_SIZE;
238
239 z = (zone_t *) malloc(sizeof(zone_t));
240 if (z) {
241 link_initialize(&z->link);
242 spinlock_initialize(&z->lock);
243
244 z->base = start;
245 z->flags = flags;
246
247 z->free_count = cnt;
248 list_initialize(&z->free_head);
249
250 z->busy_count = 0;
251 list_initialize(&z->busy_head);
252
253 z->frames = (frame_t *) malloc(cnt * sizeof(frame_t));
254 if (!z->frames) {
255 free(z);
256 return NULL;
257 }
258
259 for (i = 0; i<cnt; i++) {
260 frame_initialize(&z->frames[i], z);
261 list_append(&z->frames[i].link, &z->free_head);
262 }
263
264 }
265
266 return z;
267}
268
269/** Attach frame zone
270 *
271 * Attach frame zone to zone list.
272 *
273 * @param zone Zone to be attached.
274 */
275void zone_attach(zone_t *zone)
276{
277 pri_t pri;
278
279 pri = cpu_priority_high();
280 spinlock_lock(&zone_head_lock);
281
282 list_append(&zone->link, &zone_head);
283
284 spinlock_unlock(&zone_head_lock);
285 cpu_priority_restore(pri);
286}
287
288/** Initialize frame structure
289 *
290 * Initialize frame structure.
291 *
292 * @param frame Frame structure to be initialized.
293 * @param zone Host frame zone.
294 */
295void frame_initialize(frame_t *frame, zone_t *zone)
296{
297 frame->refcount = 0;
298 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}
Note: See TracBrowser for help on using the repository browser.