Changeset 085d973 in mainline for generic/src/mm/frame.c
- Timestamp:
- 2006-02-08T12:34:05Z (19 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 5e3757d
- Parents:
- eb1b8b6
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
generic/src/mm/frame.c
reb1b8b6 r085d973 28 28 */ 29 29 30 /* 31 * Locking order 32 * 33 * In order to access particular zone, the process must first lock 34 * the zones.lock, then lock the zone and then unlock the zones.lock. 35 * This insures, that we can fiddle with the zones in runtime without 36 * affecting the processes. 37 * 38 */ 39 30 40 #include <typedefs.h> 31 41 #include <arch/types.h> 32 #include <mm/heap.h>33 42 #include <mm/frame.h> 34 43 #include <mm/as.h> … … 41 50 #include <print.h> 42 51 #include <align.h> 43 44 SPINLOCK_INITIALIZE(zone_head_lock); /**< this lock protects zone_head list */ 45 LIST_INITIALIZE(zone_head); /**< list of all zones in the system */ 46 47 /** Blacklist containing non-available areas of memory. 48 * 49 * This blacklist is used to exclude frames that cannot be allocated 50 * (e.g. kernel memory) from available memory map. 51 */ 52 region_t zone_blacklist[ZONE_BLACKLIST_SIZE]; 53 count_t zone_blacklist_count = 0; 52 #include <mm/slab.h> 53 54 typedef struct { 55 count_t refcount; /**< tracking of shared frames */ 56 __u8 buddy_order; /**< buddy system block order */ 57 link_t buddy_link; /**< link to the next free block inside one order */ 58 void *parent; /**< If allocated by slab, this points there */ 59 }frame_t; 60 61 typedef struct { 62 SPINLOCK_DECLARE(lock); /**< this lock protects everything below */ 63 pfn_t base; /**< frame_no of the first frame in the frames array */ 64 pfn_t count; /**< Size of zone */ 65 66 frame_t *frames; /**< array of frame_t structures in this zone */ 67 count_t free_count; /**< number of free frame_t structures */ 68 count_t busy_count; /**< number of busy frame_t structures */ 69 70 buddy_system_t * buddy_system; /**< buddy system for the zone */ 71 int flags; 72 }zone_t; 73 74 /* 75 * The zoneinfo.lock must be locked when accessing zoneinfo structure. 76 * Some of the attributes in zone_t structures are 'read-only' 77 */ 78 79 struct { 80 SPINLOCK_DECLARE(lock); 81 int count; 82 zone_t *info[ZONES_MAX]; 83 }zones; 84 85 86 /*********************************/ 87 /* Helper functions */ 88 static inline index_t frame_index(zone_t *zone, frame_t *frame) 89 { 90 return (index_t)(frame - zone->frames); 91 } 92 static inline index_t frame_index_abs(zone_t *zone, frame_t *frame) 93 { 94 return (index_t)(frame - zone->frames) + zone->base; 95 } 96 static inline int frame_index_valid(zone_t *zone, index_t index) 97 { 98 return index >= 0 && index < zone->count; 99 } 100 101 /** Compute pfn_t from frame_t pointer & zone pointer */ 102 static pfn_t make_frame_index(zone_t *zone, frame_t *frame) 103 { 104 return frame - zone->frames; 105 } 106 107 /** Initialize frame structure 108 * 109 * Initialize frame structure. 110 * 111 * @param frame Frame structure to be initialized. 112 */ 113 static void frame_initialize(frame_t *frame) 114 { 115 frame->refcount = 1; 116 frame->buddy_order = 0; 117 } 118 119 /*************************************/ 120 /* Zoneinfo functions */ 121 122 /** 123 * Insert-sort zone into zones list 124 */ 125 static void zones_add_zone(zone_t *zone) 126 { 127 int i; 128 129 spinlock_lock(&zones.lock); 130 /* Try to merge */ 131 if (zone->flags & ZONE_JOIN) { 132 for (i=0; i < zones.count; i++) { 133 spinlock_lock(&zones.info[i]->lock); 134 135 /* Join forward, join backward */ 136 panic("Not implemented"); 137 138 spinlock_unlock(&zones.info[i]->lock); 139 } 140 spinlock_unlock(&zones.lock); 141 } else { 142 if (zones.count+1 == ZONES_MAX) 143 panic("Maximum zone(%d) count exceeded.", ZONES_MAX); 144 zones.info[zones.count++] = zone; 145 } 146 spinlock_unlock(&zones.lock); 147 } 148 149 /** 150 * Try to find a zone where can we find the frame 151 * 152 * @param hint Start searching in zone 'hint' 153 * @param lock Lock zone if true 154 * 155 * Assume interrupts disable 156 */ 157 static zone_t * find_zone_and_lock(pfn_t frame, int *pzone) 158 { 159 int i; 160 int hint = pzone ? *pzone : 0; 161 zone_t *z; 162 163 spinlock_lock(&zones.lock); 164 165 if (hint >= zones.count || hint < 0) 166 hint = 0; 167 168 i = hint; 169 do { 170 z = zones.info[i]; 171 spinlock_lock(&z->lock); 172 if (z->base <= frame && z->base + z->count > frame) { 173 spinlock_unlock(&zones.lock); /* Unlock the global lock */ 174 if (pzone) 175 *pzone = i; 176 return z; 177 } 178 spinlock_unlock(&z->lock); 179 180 i++; 181 if (i >= zones.count) 182 i = 0; 183 } while(i != hint); 184 185 spinlock_unlock(&zones.lock); 186 return NULL; 187 } 188 189 /** 190 * Find AND LOCK zone that can allocate order frames 191 * 192 * Assume interrupts are disabled!! 193 * 194 * @param pzone Pointer to preferred zone or NULL, on return contains zone number 195 */ 196 static zone_t * find_free_zone_lock(__u8 order, int *pzone) 197 { 198 int i; 199 zone_t *z; 200 int hint = pzone ? *pzone : 0; 201 202 spinlock_lock(&zones.lock); 203 if (hint >= zones.count) 204 hint = 0; 205 i = hint; 206 do { 207 z = zones.info[i]; 208 209 spinlock_lock(&z->lock); 210 211 /* Check if the zone has 2^order frames area available */ 212 if (buddy_system_can_alloc(z->buddy_system, order)) { 213 spinlock_unlock(&zones.lock); 214 if (pzone) 215 *pzone = i; 216 return z; 217 } 218 spinlock_unlock(&z->lock); 219 if (++i >= zones.count) 220 i = 0; 221 } while(i != hint); 222 spinlock_unlock(&zones.lock); 223 return NULL; 224 } 225 226 /********************************************/ 227 /* Buddy system functions */ 228 229 /** Buddy system find_block implementation 230 * 231 * Find block that is parent of current list. 232 * That means go to lower addresses, until such block is found 233 * 234 * @param order - Order of parent must be different then this parameter!! 235 */ 236 static link_t *zone_buddy_find_block(buddy_system_t *b, link_t *child, 237 __u8 order) 238 { 239 frame_t * frame; 240 zone_t * zone; 241 index_t index; 242 243 frame = list_get_instance(child, frame_t, buddy_link); 244 zone = (zone_t *) b->data; 245 246 index = frame_index(zone, frame); 247 do { 248 if (zone->frames[index].buddy_order != order) { 249 return &zone->frames[index].buddy_link; 250 } 251 } while(index-- > 0); 252 return NULL; 253 } 254 255 256 257 /** Buddy system find_buddy implementation 258 * 259 * @param b Buddy system. 260 * @param block Block for which buddy should be found 261 * 262 * @return Buddy for given block if found 263 */ 264 static link_t * zone_buddy_find_buddy(buddy_system_t *b, link_t * block) 265 { 266 frame_t * frame; 267 zone_t * zone; 268 index_t index; 269 bool is_left, is_right; 270 271 frame = list_get_instance(block, frame_t, buddy_link); 272 zone = (zone_t *) b->data; 273 ASSERT(IS_BUDDY_ORDER_OK(frame_index_abs(zone, frame), frame->buddy_order)); 274 275 is_left = IS_BUDDY_LEFT_BLOCK_ABS(zone, frame); 276 is_right = IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame); 277 278 ASSERT(is_left ^ is_right); 279 if (is_left) { 280 index = (frame_index(zone, frame)) + (1 << frame->buddy_order); 281 } else { // if (is_right) 282 index = (frame_index(zone, frame)) - (1 << frame->buddy_order); 283 } 284 285 286 if (frame_index_valid(zone, index)) { 287 if (zone->frames[index].buddy_order == frame->buddy_order && 288 zone->frames[index].refcount == 0) { 289 return &zone->frames[index].buddy_link; 290 } 291 } 292 293 return NULL; 294 } 295 296 /** Buddy system bisect implementation 297 * 298 * @param b Buddy system. 299 * @param block Block to bisect 300 * 301 * @return right block 302 */ 303 static link_t * zone_buddy_bisect(buddy_system_t *b, link_t * block) { 304 frame_t * frame_l, * frame_r; 305 306 frame_l = list_get_instance(block, frame_t, buddy_link); 307 frame_r = (frame_l + (1 << (frame_l->buddy_order - 1))); 308 309 return &frame_r->buddy_link; 310 } 311 312 /** Buddy system coalesce implementation 313 * 314 * @param b Buddy system. 315 * @param block_1 First block 316 * @param block_2 First block's buddy 317 * 318 * @return Coalesced block (actually block that represents lower address) 319 */ 320 static link_t * zone_buddy_coalesce(buddy_system_t *b, link_t * block_1, 321 link_t * block_2) { 322 frame_t *frame1, *frame2; 323 324 frame1 = list_get_instance(block_1, frame_t, buddy_link); 325 frame2 = list_get_instance(block_2, frame_t, buddy_link); 326 327 return frame1 < frame2 ? block_1 : block_2; 328 } 329 330 /** Buddy system set_order implementation 331 * 332 * @param b Buddy system. 333 * @param block Buddy system block 334 * @param order Order to set 335 */ 336 static void zone_buddy_set_order(buddy_system_t *b, link_t * block, __u8 order) { 337 frame_t * frame; 338 frame = list_get_instance(block, frame_t, buddy_link); 339 frame->buddy_order = order; 340 } 341 342 /** Buddy system get_order implementation 343 * 344 * @param b Buddy system. 345 * @param block Buddy system block 346 * 347 * @return Order of block 348 */ 349 static __u8 zone_buddy_get_order(buddy_system_t *b, link_t * block) { 350 frame_t * frame; 351 frame = list_get_instance(block, frame_t, buddy_link); 352 return frame->buddy_order; 353 } 354 355 /** Buddy system mark_busy implementation 356 * 357 * @param b Buddy system 358 * @param block Buddy system block 359 * 360 */ 361 static void zone_buddy_mark_busy(buddy_system_t *b, link_t * block) { 362 frame_t * frame; 363 frame = list_get_instance(block, frame_t, buddy_link); 364 frame->refcount = 1; 365 } 366 367 /** Buddy system mark_available implementation 368 * 369 * @param b Buddy system 370 * @param block Buddy system block 371 * 372 */ 373 static void zone_buddy_mark_available(buddy_system_t *b, link_t * block) { 374 frame_t * frame; 375 frame = list_get_instance(block, frame_t, buddy_link); 376 frame->refcount = 0; 377 } 54 378 55 379 static struct buddy_system_operations zone_buddy_system_operations = { … … 60 384 .get_order = zone_buddy_get_order, 61 385 .mark_busy = zone_buddy_mark_busy, 386 .mark_available = zone_buddy_mark_available, 387 .find_block = zone_buddy_find_block 62 388 }; 63 389 64 /** Initialize physical memory management 65 * 66 * Initialize physical memory managemnt. 67 */ 68 void frame_init(void) 69 { 70 if (config.cpu_active == 1) { 71 frame_region_not_free(KA2PA(config.base), config.kernel_size); 72 if (config.init_size > 0) 73 frame_region_not_free(KA2PA(config.init_addr), config.init_size); 74 } 75 76 frame_arch_init(); 77 } 78 79 /** 80 * Find AND LOCK zone that can allocate order frames 81 * 82 * Assume zone_head_lock is locked. 83 */ 84 static zone_t * find_free_zone(__u8 order) 85 { 86 link_t *cur; 390 /*************************************/ 391 /* Zone functions */ 392 393 /** Allocate frame in particular zone 394 * 395 * Assume zone is locked 396 * 397 * @return Frame index in zone 398 */ 399 static pfn_t zone_frame_alloc(zone_t *zone,__u8 order, int flags, int *status) 400 { 401 pfn_t v; 402 link_t *tmp; 403 frame_t *frame; 404 405 /* Allocate frames from zone buddy system */ 406 tmp = buddy_system_alloc(zone->buddy_system, order); 407 408 ASSERT(tmp); 409 410 /* Update zone information. */ 411 zone->free_count -= (1 << order); 412 zone->busy_count += (1 << order); 413 414 /* Frame will be actually a first frame of the block. */ 415 frame = list_get_instance(tmp, frame_t, buddy_link); 416 417 /* get frame address */ 418 v = make_frame_index(zone, frame); 419 return v; 420 } 421 422 /** Free frame from zone 423 * 424 * Assume zone is locked 425 */ 426 static void zone_frame_free(zone_t *zone, pfn_t frame_idx) 427 { 428 frame_t *frame; 429 __u8 order; 430 431 frame = &zone->frames[frame_idx]; 432 433 /* remember frame order */ 434 order = frame->buddy_order; 435 436 ASSERT(frame->refcount); 437 438 if (!--frame->refcount) { 439 buddy_system_free(zone->buddy_system, &frame->buddy_link); 440 } 441 442 /* Update zone information. */ 443 zone->free_count += (1 << order); 444 zone->busy_count -= (1 << order); 445 } 446 447 /** Return frame from zone */ 448 static frame_t * zone_get_frame(zone_t *zone, pfn_t frame_idx) 449 { 450 ASSERT(frame_idx < zone->count); 451 return &zone->frames[frame_idx]; 452 } 453 454 /** Mark frame in zone unavailable to allocation */ 455 static void zone_mark_unavailable(zone_t *zone, pfn_t frame_idx) 456 { 457 frame_t *frame; 458 link_t *link; 459 460 frame = zone_get_frame(zone, frame_idx); 461 link = buddy_system_alloc_block(zone->buddy_system, 462 &frame->buddy_link); 463 ASSERT(link); 464 zone->free_count--; 465 } 466 467 /** Create frame zone 468 * 469 * Create new frame zone. 470 * 471 * @param start Physical address of the first frame within the zone. 472 * @param size Size of the zone. Must be a multiple of FRAME_SIZE. 473 * @param conffram Address of configuration frame 474 * @param flags Zone flags. 475 * 476 * @return Initialized zone. 477 */ 478 static zone_t * zone_construct(pfn_t start, pfn_t count, 479 zone_t *z, int flags) 480 { 481 int i; 482 __u8 max_order; 483 484 spinlock_initialize(&z->lock, "zone_lock"); 485 z->base = start; 486 z->count = count; 487 z->flags = flags; 488 z->free_count = count; 489 z->busy_count = 0; 490 491 /* 492 * Compute order for buddy system, initialize 493 */ 494 for (max_order = 0; count >> max_order; max_order++) 495 ; 496 z->buddy_system = (buddy_system_t *)&z[1]; 497 498 buddy_system_create(z->buddy_system, max_order, 499 &zone_buddy_system_operations, 500 (void *) z); 501 502 /* Allocate frames _after_ the conframe */ 503 /* Check sizes */ 504 z->frames = (frame_t *)((void *)z->buddy_system+buddy_conf_size(max_order)); 505 506 for (i = 0; i<count; i++) { 507 frame_initialize(&z->frames[i]); 508 } 509 /* Stuffing frames */ 510 for (i = 0; i < count; i++) { 511 z->frames[i].refcount = 0; 512 buddy_system_free(z->buddy_system, &z->frames[i].buddy_link); 513 } 514 return z; 515 } 516 517 518 /** Compute configuration data size for zone */ 519 __address zone_conf_size(pfn_t start, pfn_t count) 520 { 521 int size = sizeof(zone_t) + count*sizeof(frame_t); 522 int max_order; 523 524 for (max_order = 0; count >> max_order; max_order++) 525 ; 526 size += buddy_conf_size(max_order); 527 return size; 528 } 529 530 /** Create and add zone to system 531 * 532 * @param confframe Where configuration frame is supposed to be. 533 * Always check, that we will not disturb kernel pages 534 * the kernel and possibly init. 535 * If confframe is given _outside_ this zone, it is expected, 536 * that the area is already marked BUSY and big enough 537 * to contain zone_conf_size() amount of data 538 */ 539 void zone_create(pfn_t start, pfn_t count, pfn_t confframe, int flags) 540 { 87 541 zone_t *z; 88 89 for (cur = zone_head.next; cur != &zone_head;cur = cur->next) { 90 z = list_get_instance(cur, zone_t, link); 91 92 spinlock_lock(&z->lock); 93 94 /* Check if the zone has 2^order frames area available */ 95 if (buddy_system_can_alloc(z->buddy_system, order)) 96 return z; 97 98 spinlock_unlock(&z->lock); 99 } 100 return NULL; 542 __address addr,endaddr; 543 pfn_t confcount; 544 int i; 545 546 /* Theoretically we could have here 0, practically make sure 547 * nobody tries to do that. If some platform requires, remove 548 * the assert 549 */ 550 ASSERT(confframe); 551 /* If conframe is supposed to be inside our zone, then make sure 552 * it does not span kernel & init 553 */ 554 confcount = SIZE2PFN(zone_conf_size(start,count)); 555 if (confframe >= start && confframe < start+count) { 556 for (;confframe < start+count;confframe++) { 557 addr = PFN2ADDR(confframe); 558 endaddr = PFN2ADDR (confframe + confcount); 559 if (overlaps(addr, endaddr, KA2PA(config.base), 560 KA2PA(config.base+config.kernel_size))) 561 continue; 562 if (config.init_addr) 563 if (overlaps(addr,endaddr, 564 KA2PA(config.init_addr), 565 KA2PA(config.init_addr+config.init_size))) 566 continue; 567 break; 568 } 569 if (confframe >= start+count) 570 panic("Cannot find configuration data for zone."); 571 } 572 573 z = zone_construct(start, count, (zone_t *)PA2KA(PFN2ADDR(confframe)), flags); 574 zones_add_zone(z); 575 576 /* If confdata in zone, mark as unavailable */ 577 if (confframe >= start && confframe < start+count) 578 for (i=confframe; i<confframe+confcount; i++) { 579 zone_mark_unavailable(z, i - z->base); 580 } 581 } 582 583 /***************************************/ 584 /* Frame functions */ 585 586 /** Set parent of frame */ 587 void frame_set_parent(pfn_t pfn, void *data, int hint) 588 { 589 zone_t *zone = find_zone_and_lock(pfn, &hint); 590 591 ASSERT(zone); 592 593 zone_get_frame(zone, pfn-zone->base)->parent = data; 594 spinlock_unlock(&zone->lock); 595 } 596 597 void * frame_get_parent(pfn_t pfn, int hint) 598 { 599 zone_t *zone = find_zone_and_lock(pfn, &hint); 600 void *res; 601 602 ASSERT(zone); 603 res = zone_get_frame(zone, pfn - zone->base)->parent; 604 605 spinlock_unlock(&zone->lock); 606 return res; 101 607 } 102 608 … … 105 611 * @param flags Flags for host zone selection and address processing. 106 612 * @param order Allocate exactly 2^order frames. 107 * @param pzone Pointer to preferred zone pointer, on output it changes 108 * to the zone that the frame was really allocated to 613 * @param pzone Preferred zone 109 614 * 110 615 * @return Allocated frame. 111 616 */ 112 __address frame_alloc_generic(__u8 order, int flags, int * status, zone_t **pzone)617 pfn_t frame_alloc_generic(__u8 order, int flags, int * status, int *pzone) 113 618 { 114 619 ipl_t ipl; 115 link_t *tmp;116 zone_t *zone = NULL;117 frame_t *frame = NULL;118 620 int freed; 119 __address v; 621 pfn_t v; 622 zone_t *zone; 120 623 121 624 loop: 122 625 ipl = interrupts_disable(); 123 spinlock_lock(&zone_head_lock);124 125 626 /* 126 627 * First, find suitable frame zone. 127 628 */ 128 if (pzone && *pzone) { 129 spinlock_lock(&(*pzone)->lock); 130 if (!buddy_system_can_alloc((*pzone)->buddy_system, order)) 131 spinlock_unlock(&(*pzone)->lock); 132 else 133 zone = *pzone; 134 } 135 if (!zone) { 136 zone = find_free_zone(order); 137 /* If no memory, reclaim some slab memory, 138 if it does not help, reclaim all */ 139 if (!zone && !(flags & FRAME_NO_RECLAIM)) { 140 spinlock_unlock(&zone_head_lock); 141 freed = slab_reclaim(0); 142 spinlock_lock(&zone_head_lock); 629 zone = find_free_zone_lock(order,pzone); 630 /* If no memory, reclaim some slab memory, 631 if it does not help, reclaim all */ 632 if (!zone && !(flags & FRAME_NO_RECLAIM)) { 633 freed = slab_reclaim(0); 634 if (freed) 635 zone = find_free_zone_lock(order,pzone); 636 if (!zone) { 637 freed = slab_reclaim(SLAB_RECLAIM_ALL); 143 638 if (freed) 144 zone = find_free_zone(order); 145 if (!zone) { 146 spinlock_unlock(&zone_head_lock); 147 freed = slab_reclaim(SLAB_RECLAIM_ALL); 148 spinlock_lock(&zone_head_lock); 149 if (freed) 150 zone = find_free_zone(order); 151 } 152 } 153 } 154 639 zone = find_free_zone_lock(order,pzone); 640 } 641 } 155 642 if (!zone) { 156 643 if (flags & FRAME_PANIC) … … 160 647 * TODO: Sleep until frames are available again. 161 648 */ 162 spinlock_unlock(&zone_head_lock);163 649 interrupts_restore(ipl); 164 650 165 651 if (flags & FRAME_ATOMIC) { 166 652 ASSERT(status != NULL); 167 *status = FRAME_NO_MEMORY; 653 if (status) 654 *status = FRAME_NO_MEMORY; 168 655 return NULL; 169 656 } … … 172 659 goto loop; 173 660 } 174 175 /* Allocate frames from zone buddy system */ 176 tmp = buddy_system_alloc(zone->buddy_system, order); 177 178 ASSERT(tmp); 179 180 /* Update zone information. */ 181 zone->free_count -= (1 << order); 182 zone->busy_count += (1 << order); 183 184 /* Frame will be actually a first frame of the block. */ 185 frame = list_get_instance(tmp, frame_t, buddy_link); 186 187 /* get frame address */ 188 v = FRAME2ADDR(zone, frame); 661 v = zone_frame_alloc(zone,order,flags,status); 662 v += zone->base; 189 663 190 664 spinlock_unlock(&zone->lock); 191 spinlock_unlock(&zone_head_lock);192 665 interrupts_restore(ipl); 193 666 194 ASSERT(v == ALIGN_UP(v, FRAME_SIZE << order));195 196 if (flags & FRAME_KA)197 v = PA2KA(v);198 199 667 if (status) 200 668 *status = FRAME_OK; 201 202 if (pzone)203 *pzone = zone;204 669 return v; 205 670 } 206 207 /** Convert address to zone pointer208 *209 * Assume zone_head_lock is held210 *211 * @param addr Physical address212 * @param lock If true, lock the zone213 */214 static zone_t * addr2zone(__address addr, int lock)215 {216 link_t *cur;217 zone_t *z = NULL;218 219 for (cur = zone_head.next; cur != &zone_head; cur = cur->next) {220 z = list_get_instance(cur, zone_t, link);221 222 spinlock_lock(&z->lock);223 224 /*225 * Check if addr belongs to z.226 */227 if ((addr >= z->base) && (addr <= z->base + (z->free_count + z->busy_count) * FRAME_SIZE)) {228 if (!lock)229 spinlock_unlock(&z->lock);230 return z;231 }232 233 spinlock_unlock(&z->lock);234 }235 236 panic("Cannot find addr2zone: 0x%X", addr);237 }238 239 /** Return frame_t structure corresponding to address240 *241 *242 */243 frame_t * frame_addr2frame(__address addr)244 {245 ipl_t ipl;246 frame_t *frame;247 zone_t *zone;248 249 if (IS_KA(addr))250 addr = KA2PA(addr);251 252 /* Disable interrupts to avoid deadlocks with interrupt handlers */253 ipl = interrupts_disable();254 spinlock_lock(&zone_head_lock);255 256 zone = addr2zone(addr,0);257 frame = ADDR2FRAME(zone, addr);258 259 spinlock_unlock(&zone_head_lock);260 interrupts_restore(ipl);261 262 return frame;263 }264 265 671 266 672 /** Free a frame. … … 270 676 * If it drops to zero, move the frame structure to free list. 271 677 * 272 * @param addr Address of the frame to be freed. It must be a multiple of FRAME_SIZE.273 */ 274 void frame_free( __address addr)678 * @param frame Frame no to be freed. 679 */ 680 void frame_free(pfn_t pfn) 275 681 { 276 682 ipl_t ipl; 277 683 zone_t *zone; 278 frame_t *frame;279 int order;280 281 ASSERT(addr % FRAME_SIZE == 0);282 283 if (IS_KA(addr))284 addr = KA2PA(addr);285 684 286 685 ipl = interrupts_disable(); 287 spinlock_lock(&zone_head_lock);288 686 289 687 /* 290 688 * First, find host frame zone for addr. 291 689 */ 292 zone = addr2zone(addr, 1); /* This locks the zone automatically */ 293 294 frame = ADDR2FRAME(zone, addr); 295 296 /* remember frame order */ 297 order = frame->buddy_order; 298 299 ASSERT(frame->refcount); 300 301 if (!--frame->refcount) { 302 buddy_system_free(zone->buddy_system, &frame->buddy_link); 303 } 304 305 /* Update zone information. */ 306 zone->free_count += (1 << order); 307 zone->busy_count -= (1 << order); 690 zone = find_zone_and_lock(pfn,NULL); 691 ASSERT(zone); 692 693 zone_frame_free(zone, pfn-zone->base); 308 694 309 695 spinlock_unlock(&zone->lock); 310 spinlock_unlock(&zone_head_lock);311 696 interrupts_restore(ipl); 312 697 } 313 698 314 /** Mark frame region not free. 315 * 316 * Mark frame region not free. 317 * 318 * @param base Base address of non-available region. 319 * @param size Size of non-available region. 320 */ 321 void frame_region_not_free(__address base, size_t size) 322 { 323 index_t index; 324 index = zone_blacklist_count++; 325 326 /* Force base to the nearest lower address frame boundary. */ 327 base = ALIGN_DOWN(base, FRAME_SIZE); 328 /* Align size to frame boundary. */ 329 size = ALIGN_UP(size, FRAME_SIZE); 330 331 ASSERT(index < ZONE_BLACKLIST_SIZE); 332 zone_blacklist[index].base = base; 333 zone_blacklist[index].size = size; 334 } 335 336 /** Create frame zones in region of available memory. 337 * 338 * Avoid any black listed areas of non-available memory. 339 * Assume that the black listed areas cannot overlap 340 * one another or cross available memory region boundaries. 341 * 342 * @param base Base address of available memory region. 343 * @param size Size of the region. 344 */ 345 void zone_create_in_region(__address base, size_t size) { 699 700 701 /** Mark given range unavailable in frame zones */ 702 void frame_mark_unavailable(pfn_t start, pfn_t count) 703 { 346 704 int i; 347 zone_t * z; 348 __address s; 349 size_t sz; 350 351 ASSERT(base % FRAME_SIZE == 0); 352 ASSERT(size % FRAME_SIZE == 0); 353 354 if (!size) 355 return; 356 357 for (i = 0; i < zone_blacklist_count; i++) { 358 if (zone_blacklist[i].base >= base && zone_blacklist[i].base < base + size) { 359 s = base; sz = zone_blacklist[i].base - base; 360 ASSERT(base != s || sz != size); 361 zone_create_in_region(s, sz); 362 363 s = zone_blacklist[i].base + zone_blacklist[i].size; 364 sz = (base + size) - (zone_blacklist[i].base + zone_blacklist[i].size); 365 ASSERT(base != s || sz != size); 366 zone_create_in_region(s, sz); 367 return; 368 369 } 370 } 371 372 z = zone_create(base, size, 0); 373 374 if (!z) { 375 panic("Cannot allocate zone (base=%P, size=%d).\n", base, size); 376 } 377 378 zone_attach(z); 379 } 380 381 382 /** Create frame zone 383 * 384 * Create new frame zone. 385 * 386 * @param start Physical address of the first frame within the zone. 387 * @param size Size of the zone. Must be a multiple of FRAME_SIZE. 388 * @param flags Zone flags. 389 * 390 * @return Initialized zone. 391 */ 392 zone_t * zone_create(__address start, size_t size, int flags) 393 { 394 zone_t *z; 395 count_t cnt; 396 int i; 397 __u8 max_order; 398 399 ASSERT(start % FRAME_SIZE == 0); 400 ASSERT(size % FRAME_SIZE == 0); 401 402 cnt = size / FRAME_SIZE; 403 404 z = (zone_t *) early_malloc(sizeof(zone_t)); 405 if (z) { 406 link_initialize(&z->link); 407 spinlock_initialize(&z->lock, "zone_lock"); 408 409 z->base = start; 410 z->base_index = start / FRAME_SIZE; 411 412 z->flags = flags; 413 414 z->free_count = cnt; 415 z->busy_count = 0; 416 417 z->frames = (frame_t *) early_malloc(cnt * sizeof(frame_t)); 418 if (!z->frames) { 419 early_free(z); 420 return NULL; 421 } 422 423 for (i = 0; i<cnt; i++) { 424 frame_initialize(&z->frames[i], z); 425 } 426 427 /* 428 * Create buddy system for the zone 429 */ 430 for (max_order = 0; cnt >> max_order; max_order++) 431 ; 432 z->buddy_system = buddy_system_create(max_order, &zone_buddy_system_operations, (void *) z); 433 434 /* Stuffing frames */ 435 for (i = 0; i<cnt; i++) { 436 z->frames[i].refcount = 0; 437 buddy_system_free(z->buddy_system, &z->frames[i].buddy_link); 438 } 439 440 } 441 return z; 442 } 443 444 /** Attach frame zone 445 * 446 * Attach frame zone to zone list. 447 * 448 * @param zone Zone to be attached. 449 */ 450 void zone_attach(zone_t *zone) 451 { 452 ipl_t ipl; 453 454 ipl = interrupts_disable(); 455 spinlock_lock(&zone_head_lock); 456 457 list_append(&zone->link, &zone_head); 458 459 spinlock_unlock(&zone_head_lock); 460 interrupts_restore(ipl); 461 } 462 463 /** Initialize frame structure 464 * 465 * Initialize frame structure. 466 * 467 * @param frame Frame structure to be initialized. 468 * @param zone Host frame zone. 469 */ 470 void frame_initialize(frame_t *frame, zone_t *zone) 471 { 472 frame->refcount = 1; 473 frame->buddy_order = 0; 474 } 475 476 477 /** Buddy system find_buddy implementation 478 * 479 * @param b Buddy system. 480 * @param block Block for which buddy should be found 481 * 482 * @return Buddy for given block if found 483 */ 484 link_t * zone_buddy_find_buddy(buddy_system_t *b, link_t * block) { 485 frame_t * frame; 486 zone_t * zone; 487 index_t index; 488 bool is_left, is_right; 489 490 frame = list_get_instance(block, frame_t, buddy_link); 491 zone = (zone_t *) b->data; 492 ASSERT(IS_BUDDY_ORDER_OK(FRAME_INDEX_ABS(zone, frame), frame->buddy_order)); 493 494 495 is_left = IS_BUDDY_LEFT_BLOCK_ABS(zone, frame); 496 is_right = IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame); 497 498 ASSERT(is_left ^ is_right); 499 500 if (is_left) { 501 index = (FRAME_INDEX(zone, frame)) + (1 << frame->buddy_order); 502 } else { // if (is_right) 503 index = (FRAME_INDEX(zone, frame)) - (1 << frame->buddy_order); 504 } 505 506 if (FRAME_INDEX_VALID(zone, index)) { 507 if ( zone->frames[index].buddy_order == frame->buddy_order && 508 zone->frames[index].refcount == 0) { 509 return &zone->frames[index].buddy_link; 510 } 511 } 512 513 return NULL; 514 } 515 516 /** Buddy system bisect implementation 517 * 518 * @param b Buddy system. 519 * @param block Block to bisect 520 * 521 * @return right block 522 */ 523 link_t * zone_buddy_bisect(buddy_system_t *b, link_t * block) { 524 frame_t * frame_l, * frame_r; 525 526 frame_l = list_get_instance(block, frame_t, buddy_link); 527 frame_r = (frame_l + (1 << (frame_l->buddy_order - 1))); 528 529 return &frame_r->buddy_link; 530 } 531 532 /** Buddy system coalesce implementation 533 * 534 * @param b Buddy system. 535 * @param block_1 First block 536 * @param block_2 First block's buddy 537 * 538 * @return Coalesced block (actually block that represents lower address) 539 */ 540 link_t * zone_buddy_coalesce(buddy_system_t *b, link_t * block_1, link_t * block_2) { 541 frame_t * frame1, * frame2; 542 543 frame1 = list_get_instance(block_1, frame_t, buddy_link); 544 frame2 = list_get_instance(block_2, frame_t, buddy_link); 545 546 return frame1 < frame2 ? block_1 : block_2; 547 } 548 549 /** Buddy system set_order implementation 550 * 551 * @param b Buddy system. 552 * @param block Buddy system block 553 * @param order Order to set 554 */ 555 void zone_buddy_set_order(buddy_system_t *b, link_t * block, __u8 order) { 556 frame_t * frame; 557 frame = list_get_instance(block, frame_t, buddy_link); 558 frame->buddy_order = order; 559 } 560 561 /** Buddy system get_order implementation 562 * 563 * @param b Buddy system. 564 * @param block Buddy system block 565 * 566 * @return Order of block 567 */ 568 __u8 zone_buddy_get_order(buddy_system_t *b, link_t * block) { 569 frame_t * frame; 570 frame = list_get_instance(block, frame_t, buddy_link); 571 return frame->buddy_order; 572 } 573 574 /** Buddy system mark_busy implementation 575 * 576 * @param b Buddy system 577 * @param block Buddy system block 578 * 579 */ 580 void zone_buddy_mark_busy(buddy_system_t *b, link_t * block) { 581 frame_t * frame; 582 frame = list_get_instance(block, frame_t, buddy_link); 583 frame->refcount = 1; 584 } 705 zone_t *zone; 706 int prefzone = 0; 707 708 for (i=0; i<count; i++) { 709 zone = find_zone_and_lock(start+i,&prefzone); 710 if (!zone) /* PFN not found */ 711 continue; 712 zone_mark_unavailable(zone, start+i-zone->base); 713 714 spinlock_unlock(&zone->lock); 715 } 716 } 717 718 /** Initialize physical memory management 719 * 720 * Initialize physical memory managemnt. 721 */ 722 void frame_init(void) 723 { 724 if (config.cpu_active == 1) { 725 zones.count = 0; 726 spinlock_initialize(&zones.lock,"zones_glob_lock"); 727 } 728 /* Tell the architecture to create some memory */ 729 frame_arch_init(); 730 if (config.cpu_active == 1) { 731 frame_mark_unavailable(ADDR2PFN(KA2PA(config.base)), 732 SIZE2PFN(config.kernel_size)); 733 if (config.init_size > 0) 734 frame_mark_unavailable(ADDR2PFN(KA2PA(config.init_addr)), 735 SIZE2PFN(config.init_size)); 736 } 737 } 738 739 585 740 586 741 /** Prints list of zones … … 589 744 void zone_print_list(void) { 590 745 zone_t *zone = NULL; 591 link_t *cur;746 int i; 592 747 ipl_t ipl; 593 748 594 749 ipl = interrupts_disable(); 595 spinlock_lock(&zone _head_lock);750 spinlock_lock(&zones.lock); 596 751 printf("Base address\tFree Frames\tBusy Frames\n"); 597 752 printf("------------\t-----------\t-----------\n"); 598 for ( cur = zone_head.next; cur != &zone_head; cur = cur->next) {599 zone = list_get_instance(cur, zone_t, link);753 for (i=0;i<zones.count;i++) { 754 zone = zones.info[i]; 600 755 spinlock_lock(&zone->lock); 601 printf("%L\t%d\t\t%d\n",zone->base, zone->free_count, zone->busy_count); 756 printf("%L\t%d\t\t%d\n",PFN2ADDR(zone->base), 757 zone->free_count, zone->busy_count); 602 758 spinlock_unlock(&zone->lock); 603 759 } 604 spinlock_unlock(&zone _head_lock);760 spinlock_unlock(&zones.lock); 605 761 interrupts_restore(ipl); 606 762 } … … 610 766 * @param base Zone base address 611 767 */ 612 void zone_print_one(__address base) { 613 zone_t *zone = NULL, *z ; 614 link_t *cur; 768 void zone_print_one(int znum) { 769 zone_t *zone = NULL; 615 770 ipl_t ipl; 616 771 617 772 ipl = interrupts_disable(); 618 spinlock_lock(&zone_head_lock); 619 620 for (cur = zone_head.next; cur != &zone_head; cur = cur->next) { 621 z = list_get_instance(cur, zone_t, link); 622 if (base == z->base) { 623 zone = z; 624 break; 625 } 626 } 627 628 if (!zone) { 629 spinlock_unlock(&zone_head_lock); 773 spinlock_lock(&zones.lock); 774 775 if (znum >= zones.count || znum < 0) { 776 printf("Zone number out of bounds.\n"); 777 spinlock_unlock(&zones.lock); 630 778 interrupts_restore(ipl); 631 printf("No zone with address %X\n", base);632 779 return; 633 780 } 781 782 zone = zones.info[znum]; 634 783 635 784 spinlock_lock(&zone->lock); 636 785 printf("Memory zone information\n\n"); 637 printf("Zone base address: %P\n", zone->base);638 printf("Zone size: %d frames (%dK)\n", zone-> free_count + zone->busy_count, ((zone->free_count + zone->busy_count) * FRAME_SIZE) >> 10);786 printf("Zone base address: %P\n", PFN2ADDR(zone->base)); 787 printf("Zone size: %d frames (%dK)\n", zone->count, ((zone->count) * FRAME_SIZE) >> 10); 639 788 printf("Allocated space: %d frames (%dK)\n", zone->busy_count, (zone->busy_count * FRAME_SIZE) >> 10); 640 789 printf("Available space: %d (%dK)\n", zone->free_count, (zone->free_count * FRAME_SIZE) >> 10); … … 644 793 645 794 spinlock_unlock(&zone->lock); 646 spinlock_unlock(&zone _head_lock);795 spinlock_unlock(&zones.lock); 647 796 interrupts_restore(ipl); 648 797 }
Note:
See TracChangeset
for help on using the changeset viewer.