/* * Node manipulation */ static struct palloc_node *get_node_by_paddr(ulong paddr) { if (paddr >= hal->paddr_space_end) { return NULL; } return &nodes[ADDR_TO_PFN(paddr)]; }
static struct palloc_node *get_node_by_pfn(ulong pfn) { if (pfn >= ADDR_TO_PFN(hal->paddr_space_end)) { return NULL; } return &nodes[pfn]; }
/* * Initialization */ static void init_bucket(ulong start, ulong len, int tag) { kprintf("\tInitializing bucket, start: %p, len: %p, tag: %d\n", start, len, tag); assert(tag < PALLOC_BUCKET_COUNT && tag != PALLOC_DUMMY_BUCKET); // Update page count ulong page_count = len / PAGE_SIZE; buckets[tag].total_pages += page_count; buckets[tag].avail_pages += page_count; // Setup the buddy system int order; ulong cur_addr = start; ulong end = start + len; while (cur_addr < end) { for (order = PALLOC_MAX_ORDER; order >= PALLOC_MIN_ORDER; order--) { ulong order_size = ((ulong)0x1 << order) * PAGE_SIZE; // We found the correct buddy size if ( 0 == cur_addr % order_size && cur_addr + order_size <= end ) { // Obtain the node struct palloc_node *node = get_node_by_paddr(cur_addr); node->order = order; node->alloc = 0; node->tag = tag; node->avail = 1; node->next = 0; node->has_next = 0; // Insert the chunk into the buddy list insert_node(ADDR_TO_PFN(cur_addr), tag, order); kprintf("\t\tBuddy inserted, addr: %p, size: %p, order: %d\n", cur_addr, order_size, order); cur_addr += order_size; break; } } } }
void pmm_free_frame(page_t *p) { pfn_t frame = ADDR_TO_PFN(PAGE_FRAME(*p)); pmm_clear_frame(frame); SET_PAGE_FRAME(*p, 0); }