Changeset 84dd253 in mainline for src/mm/frame.c
- Timestamp:
- 2005-09-21T13:37:50Z (20 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- aed4eca
- Parents:
- fcacfb7
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/mm/frame.c
rfcacfb7 r84dd253 27 27 */ 28 28 29 #include <typedefs.h> 29 30 #include <arch/types.h> 30 #include <func.h>31 32 31 #include <mm/heap.h> 33 32 #include <mm/frame.h> 34 #include <mm/page.h>35 33 #include <mm/vm.h> 36 #include <arch/mm/page.h>37 38 #include <config.h>39 #include <memstr.h>40 41 34 #include <panic.h> 42 35 #include <debug.h> 43 36 #include <list.h> 44 37 #include <synch/spinlock.h> 45 46 38 #include <arch/asm.h> 47 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 41 spinlock_t zone_head_lock; /**< this lock protects zone_head list */ 58 42 link_t zone_head; /**< list of all zones in the system */ 59 43 60 44 /** Initialize physical memory management 45 * 46 * Initialize physical memory managemnt. 47 */ 61 48 void frame_init(void) 62 49 { 63 50 if (config.cpu_active == 1) { 64 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 } 82 83 /* 84 * No frame allocations/reservations prior this point. 85 */ 52 } 86 53 87 54 frame_arch_init(); 88 55 89 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); 95 } 96 } 97 98 /* 99 * Allocate a frame. 57 frame_region_not_free(config.base, config.base + config.kernel_size + CONFIG_STACK_SIZE); 58 } 59 } 60 61 /** Allocate a frame 62 * 63 * Allocate a frame of physical memory. 64 * 65 * @param flags Flags for host zone selection and address processing. 66 * 67 * @return Allocated frame. 100 68 */ 101 69 __address frame_alloc(int flags) 102 70 { 103 int i;104 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 78 loop: 107 79 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); 80 spinlock_lock(&zone_head_lock); 81 82 /* 83 * First, find suitable frame zone. 84 */ 85 for (cur = zone_head.next; cur != &zone_head; cur = cur->next) { 86 z = list_get_instance(cur, zone_t, link); 87 88 spinlock_lock(&z->lock); 89 /* 90 * Check if the zone has any free frames. 91 */ 92 if (z->free_count) { 93 zone = z; 94 break; 95 } 96 spinlock_unlock(&z->lock); 97 } 98 99 if (!zone) { 100 if (flags & FRAME_PANIC) 101 panic("Can't allocate frame.\n"); 102 103 /* 104 * TODO: Sleep until frames are available again. 105 */ 106 spinlock_unlock(&zone_head_lock); 107 cpu_priority_restore(pri); 108 109 panic("Sleep not implemented.\n"); 110 goto loop; 111 } 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; 123 124 if (flags & FRAME_KA) 125 v = PA2KA(v); 126 127 spinlock_unlock(&zone->lock); 128 129 spinlock_unlock(&zone_head_lock); 128 130 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. 131 132 return v; 133 } 134 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 143 void frame_free(__address addr) 143 144 { 144 145 pri_t pri; 145 __u32 frame; 146 146 link_t *cur; 147 zone_t *z; 148 zone_t *zone = NULL; 149 frame_t *frame; 150 151 ASSERT(addr % FRAME_SIZE == 0); 152 147 153 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); 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); 161 162 spinlock_lock(&z->lock); 163 164 if (IS_KA(addr)) 165 addr = KA2PA(addr); 166 167 /* 168 * Check if addr belongs to z. 169 */ 170 if ((addr >= z->base) && (addr <= z->base + (z->free_count + z->busy_count) * FRAME_SIZE)) { 171 zone = z; 172 break; 173 } 174 spinlock_unlock(&z->lock); 175 } 176 177 ASSERT(zone != NULL); 178 179 frame = &zone->frames[(addr - zone->base)/FRAME_SIZE]; 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--; 187 } 188 189 spinlock_unlock(&zone->lock); 190 191 spinlock_unlock(&zone_head_lock); 167 192 cpu_priority_restore(pri); 168 193 } 169 194 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. 195 /** Mark frame not free. 196 * 197 * Find respective frame structrue for supplied addr. 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 202 void frame_not_free(__address addr) 175 203 { 176 204 pri_t pri; 177 __u32 frame; 205 link_t *cur; 206 zone_t *z; 207 zone_t *zone = NULL; 208 frame_t *frame; 209 210 ASSERT(addr % FRAME_SIZE == 0); 178 211 179 212 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); 213 spinlock_lock(&zone_head_lock); 214 215 /* 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 221 spinlock_lock(&z->lock); 222 223 if (IS_KA(addr)) 224 addr = KA2PA(addr); 225 226 /* 227 * Check if addr belongs to z. 228 */ 229 if ((addr >= z->base) && (addr <= z->base + (z->free_count + z->busy_count) * FRAME_SIZE)) { 230 zone = z; 231 break; 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++; 247 } 248 249 spinlock_unlock(&zone->lock); 250 251 spinlock_unlock(&zone_head_lock); 195 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 262 void frame_region_not_free(__address start, __address stop) 199 263 { 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 } 264 __address a; 265 266 start /= FRAME_SIZE; 267 stop /= FRAME_SIZE; 268 for (a = start; a <= stop; a++) 269 frame_not_free(a * FRAME_SIZE); 270 } 271 207 272 208 273 /** Initialize zonekeeping … … 297 362 frame->refcount = 0; 298 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 }
Note:
See TracChangeset
for help on using the changeset viewer.