From b95868d6ea0455974f18930188c9088d67931642 Mon Sep 17 00:00:00 2001 From: TunaCici <36923239+TunaCici@users.noreply.github.com> Date: Wed, 10 Jan 2024 19:07:21 +0300 Subject: [PATCH] pmm: Housekeeping. Signed-off-by: TunaCici <36923239+TunaCici@users.noreply.github.com> --- Kernel/Include/Memory/Physical.h | 4 +- Kernel/Memory/Physical.c | 206 ++++++++++++++----------------- 2 files changed, 97 insertions(+), 113 deletions(-) diff --git a/Kernel/Include/Memory/Physical.h b/Kernel/Include/Memory/Physical.h index 28b3d62..cf0c8d8 100644 --- a/Kernel/Include/Memory/Physical.h +++ b/Kernel/Include/Memory/Physical.h @@ -39,13 +39,13 @@ typedef struct free_area_struct { uint8_t *map; } free_area_t; -uint64_t init_allocator(const uint8_t *startAddr, const uint8_t *endAddr); +uint64_t init_allocator(const uint8_t *start, const uint8_t *end); /* Allocate a single page / 2^order number of pages */ void* alloc_page(); void* alloc_pages(const uint32_t order); -void free_page(void *targetAddr); +void free_page(void *addr); void free_pages(void *targetAddr, const uint32_t order); /* START DEBUG ONLY */ diff --git a/Kernel/Memory/Physical.c b/Kernel/Memory/Physical.c index 7148ab9..ede98a7 100644 --- a/Kernel/Memory/Physical.c +++ b/Kernel/Memory/Physical.c @@ -26,40 +26,52 @@ static volatile free_area_t buddyPmm[MAX_ORDER] = {0}; static volatile void *baseAddr = 0; -void __clear_page_area(uint8_t *startAddr, uint32_t count) +void __clear_page_area(uint8_t *addr, uint32_t size) { - uint8_t *iter = startAddr; - for (uint32_t i = 0; i < count; i += 8) { + uint8_t *iter = addr; + for (uint32_t i = 0; i < size; i += 8) { *iter = 0x00; iter++; } } /* Assumes the memory pool is contiguous */ -uint64_t __addr_to_idx(const uint8_t *targetAddr, const uint32_t blockSize) +uint64_t __block_to_idx(const list_head_t *block, const uint32_t order) { - return (targetAddr - (uint8_t*) baseAddr) / blockSize; + return ((uint8_t*) block - (uint8_t*) baseAddr) / SIZEOF_BLOCK(order); } -list_head_t* __buddy(const uint8_t* reference, const unsigned int order) +list_head_t* __buddy(const list_head_t *block, const uint32_t order) { list_head_t *retValue = 0; - retValue = (list_head_t*) ((uint64_t) reference ^ (PAGE_SIZE << order)); + retValue = (list_head_t*) ((uint64_t) block ^ (PAGE_SIZE << order)); return retValue; } -void __append_to_order(const unsigned int order, list_head_t *targetBlock) +void __try_to_mark(list_head_t *block, const uint32_t order) { - if (!targetBlock || MAX_ORDER <= order) { + /* Mark the allocated block as USED (if possible) */ + if (order < MAX_ORDER - 1) { + uint64_t idx = __block_to_idx(block, order); + + KLOG("[pmm] mark idx %lu in 2^%u as USED\n", idx, order); + + BUDDY_MARK_USED(buddyPmm[order].map, idx); + } +} + +void __append_to_order(list_head_t *block, const uint32_t order) +{ + if (!block || MAX_ORDER <= order) { return; } /* Append to head */ if (buddyPmm[order].listHead.next == 0) { - buddyPmm[order].listHead.next = targetBlock; - targetBlock->prev = 0; + buddyPmm[order].listHead.next = block; + block->prev = 0; return; } @@ -68,45 +80,46 @@ void __append_to_order(const unsigned int order, list_head_t *targetBlock) while(iter->next) { iter = iter->next; } - iter->next = targetBlock; + iter->next = block; - targetBlock->next = 0; - targetBlock->prev = iter; + block->next = 0; + block->prev = iter; } -void __remove_from_order(const unsigned int order, list_head_t *targetBlock) +void __remove_from_order(list_head_t *block, const uint32_t order) { - if (!targetBlock || MAX_ORDER <= order) { + if (!block || MAX_ORDER <= order) { return; } /* Remove from head */ - if (!targetBlock->prev) { + if (!block->prev) { buddyPmm[order].listHead.next = 0; return; } /* Or somewhere else */ - targetBlock->prev->next = targetBlock->next; - if (targetBlock->next) { - targetBlock->next->prev = targetBlock->prev; + block->prev->next = block->next; + if (block->next) { + block->next->prev = block->prev; } - targetBlock->next = 0; - targetBlock->prev = 0; + block->next = 0; + block->prev = 0; } -uint64_t init_allocator(const uint8_t *startAddr, const uint8_t *endAddr) +uint64_t init_allocator(const uint8_t *start, const uint8_t *end) { uint64_t retValue = 0; /* number of available MAX_ORDER - 1 blocks */ - void *alignedStart = (void*) PALIGN(startAddr); - void *alignedEnd = (void*) PALIGN(endAddr - PAGE_SIZE + 1); + list_head_t *alignedStart = (void*) PALIGN(start); + list_head_t *alignedEnd = (void*) PALIGN(end - PAGE_SIZE + 1); /* Align to MAX_ORDER block */ - alignedStart = (void*) CUSTOM_ALIGN(alignedStart, (PAGE_SIZE << (MAX_ORDER - 1))); + alignedStart = (list_head_t*) CUSTOM_ALIGN(alignedStart, + (PAGE_SIZE << (MAX_ORDER - 1))); baseAddr = alignedStart; - const uint32_t moveBy = SIZEOF_BLOCK(MAX_ORDER - 1) / 8; /* pointer arithmetics */ + const uint32_t moveBy = SIZEOF_BLOCK(MAX_ORDER - 1) / 8; /* ptr arith */ /* Initialize 2^(MAX_ORDER - 1) blocks */ buddyPmm[MAX_ORDER - 1].listHead.next = alignedStart; @@ -114,14 +127,14 @@ uint64_t init_allocator(const uint8_t *startAddr, const uint8_t *endAddr) buddyPmm[MAX_ORDER - 1].map = 0; /* Add blocks to freeList */ - uint32_t maxOrderBlockCount = 1; + uint64_t blockCount = 1; list_head_t *prevBlock = 0; - for (list_head_t *i = alignedStart; i < (list_head_t*) alignedEnd; i += moveBy) { - if ((i + moveBy) < (list_head_t*) alignedEnd) { + for (list_head_t *i = alignedStart; i < alignedEnd; i += moveBy) { + if ((i + moveBy) < alignedEnd) { i->next = (i + moveBy); i->prev = prevBlock; - maxOrderBlockCount++; + blockCount++; prevBlock = i; } } @@ -130,7 +143,7 @@ uint64_t init_allocator(const uint8_t *startAddr, const uint8_t *endAddr) for (uint32_t i = 0; i < MAX_ORDER - 1; i++) { uint32_t bitmapSize = 0; /* Bytes */ - bitmapSize = maxOrderBlockCount << (MAX_ORDER - 1 - i); /* Bit */ + bitmapSize = blockCount << (MAX_ORDER - 1 - i); /* Bit */ bitmapSize = (bitmapSize + 7) & ~7; /* Align to uint8_t */ bitmapSize = bitmapSize / 8; /* To bytes */ @@ -143,26 +156,24 @@ uint64_t init_allocator(const uint8_t *startAddr, const uint8_t *endAddr) __clear_page_area(buddyPmm[i].map, reqPages); } - retValue = maxOrderBlockCount; + retValue = blockCount; return retValue; } void* alloc_page() { - void *retAddr = 0; - - return retAddr; + return alloc_pages(0); } void* alloc_pages(const uint32_t order) { if (MAX_ORDER <= order) { - klog("[pmm] can't allocate blocks larger than 2^(MAX_ORDER - 1)\n"); + KLOG("[pmm] can't allocate blocks larger than 2^(MAX_ORDER - 1)\n"); return 0; } - klog("[pmm] allocate an 2^%u order block (%u bytes)\n", order, SIZEOF_BLOCK(order)); + KLOG("[pmm] allocate an 2^%u order block (%u bytes)\n", order, SIZEOF_BLOCK(order)); void *retAddr = 0; @@ -170,142 +181,115 @@ void* alloc_pages(const uint32_t order) uint32_t startOrder = 0; for (; startOrder < MAX_ORDER; startOrder++) { if (SIZEOF_BLOCK(startOrder) < SIZEOF_BLOCK(order)) { - klog("[pmm] order 2^%u size not enough. skip\n", startOrder); + KLOG("[pmm] order 2^%u size not enough. skip\n", startOrder); continue; } else if (!buddyPmm[startOrder].listHead.next) { - klog("[pmm] order 2^%u doesn't have free blocks. skip\n", startOrder); + KLOG("[pmm] order 2^%u doesn't have free blocks. skip\n", startOrder); continue; } - klog("[pmm] order 2^%u has free blocks. start here\n", startOrder); + KLOG("[pmm] order 2^%u has free blocks. start here\n", startOrder); break; } if (MAX_ORDER <= startOrder) { - klog("[pmm] no available free blocks. fail\n"); + KLOG("[pmm] no available free blocks. fail\n"); return 0; } /* Remove from list */ - list_head_t *targetBlock = buddyPmm[startOrder].listHead.next; - buddyPmm[startOrder].listHead.next = targetBlock->next; + list_head_t *block = buddyPmm[startOrder].listHead.next; + buddyPmm[startOrder].listHead.next = block->next; if (buddyPmm[startOrder].listHead.next) { buddyPmm[startOrder].listHead.next->prev = 0; } - targetBlock->next = 0; - targetBlock->prev = 0; + block->next = 0; + block->prev = 0; - uint64_t targetBlockIdx = __addr_to_idx( - (uint8_t*) targetBlock, SIZEOF_BLOCK(startOrder) - ); + uint64_t idx = __block_to_idx(block, startOrder); - klog("[pmm] target block: 0x%p (idx: %lu)\n", - targetBlock, - targetBlockIdx - ); + KLOG("[pmm] choosen block: 0x%p (idx: %lu)\n", block, idx); uint32_t currOrder; for (currOrder = startOrder; 0 <= currOrder; currOrder--) { - klog("[pmm] currOrder: %u\n", currOrder); + KLOG("[pmm] currOrder: %u\n", currOrder); if (SIZEOF_BLOCK(currOrder) == SIZEOF_BLOCK(order)) { /* Perfect fit. allocate here */ - klog("[pmm] perfect fit for 2^%u. allocate\n", currOrder); - - /* Mark the allocated block as USED (if possible) */ - if (currOrder < MAX_ORDER - 1) { - uint64_t targetBlockIdx = __addr_to_idx( - (uint8_t*) targetBlock, SIZEOF_BLOCK(currOrder) - ); + KLOG("[pmm] perfect fit for 2^%u. allocate\n", currOrder); - klog("[pmm] mark idx %lu in 2^%u as USED\n", targetBlockIdx, currOrder); + __try_to_mark(block, currOrder); - BUDDY_MARK_USED(buddyPmm[currOrder].map, targetBlockIdx); - } - - retAddr = (void*) targetBlock; + retAddr = (void*) block; break; } else { /* Split */ - list_head_t *buddy = __buddy( - (uint8_t*) targetBlock, currOrder - 1); - klog("[pmm] split. targetBlock: 0x%p, it's buddy: 0x%p\n", targetBlock, buddy); + list_head_t *buddy = __buddy(block, currOrder - 1); + KLOG("[pmm] split. targetBlock: 0x%p, it's buddy: 0x%p\n", block, buddy); - /* Mark the split block as USED (if possible) */ - if (currOrder < MAX_ORDER - 1) { - uint64_t targetBlockIdx = __addr_to_idx( - (uint8_t*) targetBlock, SIZEOF_BLOCK(currOrder) - ); - - BUDDY_MARK_USED(buddyPmm[currOrder].map, targetBlockIdx); - } - - /* Add buddy to ONE BELOW freelist */ - __append_to_order(currOrder - 1, buddy); + __try_to_mark(block, currOrder); + __append_to_order(buddy, currOrder - 1); } } - targetBlockIdx = __addr_to_idx( - (uint8_t*) retAddr, SIZEOF_BLOCK(currOrder) - ); + idx = __block_to_idx(retAddr, currOrder); - if (BUDDY_GET_MARK(buddyPmm[currOrder].map, targetBlockIdx)) { - klog("[pmm] allocate block 0x%p on 2^%u OK\n", retAddr, currOrder); + if (BUDDY_GET_MARK(buddyPmm[currOrder].map, idx)) { + KLOG("[pmm] allocate block 0x%p on 2^%u OK\n", retAddr, currOrder); } else { - klog("[pmm] allocate block 0x%p on 2^%u FAIL\n", retAddr, currOrder); + KLOG("[pmm] allocate block 0x%p on 2^%u FAIL\n", retAddr, currOrder); } return retAddr; } -void free_page(void *targetAddr) +void free_page(void *addr) { - return; + free_pages(addr, 0); } -void free_pages(void *targetAddr, const uint32_t order) +void free_pages(void *addr, const uint32_t order) { - if (!targetAddr || MAX_ORDER <= order) { - klog("[pmm] target is NULL or order is larger then 2^(MAX_ORDER - 1). fail\n"); + if (!addr || MAX_ORDER <= order) { + KLOG("[pmm] target is NULL or order is larger then 2^(MAX_ORDER - 1). fail\n"); return; } - uint64_t targetIdx = __addr_to_idx((uint8_t*) targetAddr, SIZEOF_BLOCK(order)); + uint64_t idx = __block_to_idx(addr, order); - if (!BUDDY_GET_MARK(buddyPmm[order].map, targetIdx)) { - klog("[pmm] trying to free an empty area. fail\n"); + if (!BUDDY_GET_MARK(buddyPmm[order].map, idx)) { + KLOG("[pmm] trying to free an empty area. fail\n"); return; } - /* Mark as free */ - BUDDY_MARK_FREE(buddyPmm[order].map, targetIdx); + BUDDY_MARK_FREE(buddyPmm[order].map, idx); /* 2^(MAX_ORDER - 1) block don't coalese */ if (order == (MAX_ORDER - 1)) { - klog("[pmm] 2^(MAX_ORDER - 1) block don't coalese. append\n"); - __append_to_order(order, targetAddr); + KLOG("[pmm] 2^(MAX_ORDER - 1) block don't coalese. append\n"); + __append_to_order(addr, idx); return; } /* Coalese? */ - for (uint32_t currOrder = order; currOrder < MAX_ORDER - 1; currOrder++) { - list_head_t *buddy = __buddy(targetAddr, currOrder); - uint64_t buddyIdx = __addr_to_idx((uint8_t*) buddy, SIZEOF_BLOCK(currOrder)); + for (uint32_t curr = order; curr < MAX_ORDER - 1; curr++) { + list_head_t *buddy = __buddy(addr, curr); + uint64_t buddyIdx = __block_to_idx(addr, curr); - klog("[pmm] buddy 0x%p (idx: %lu, ord: %u)\n", buddy, buddyIdx, currOrder); + KLOG("[pmm] buddy 0x%p (idx: %lu, ord: %u)\n", buddy, buddyIdx, curr); /* Coalese */ - if (!BUDDY_GET_MARK(buddyPmm[currOrder].map, buddyIdx)) { - klog("[pmm] buddy is free. coalese\n"); + if (!BUDDY_GET_MARK(buddyPmm[curr].map, buddyIdx)) { + KLOG("[pmm] buddy is free. coalese\n"); - __remove_from_order(currOrder, buddy); - __append_to_order(currOrder + 1, targetAddr); + __remove_from_order(buddy, curr); + __append_to_order(addr, curr + 1); } else { - klog("[pmm] buddy is not free. append to list\n"); + KLOG("[pmm] buddy is not free. append to list\n"); - __append_to_order(currOrder, targetAddr); + __append_to_order(addr, curr); break; } } @@ -317,15 +301,15 @@ void pmm_klog_buddy(void) { for (uint32_t i = 0; i < MAX_ORDER; i++) { - klog("[pmm] buddyPmm[%u].listHead ", i); + KLOG("[pmm] buddyPmm[%u].listHead ", i); uint32_t maxPrint = 3; list_head_t *iter = buddyPmm[i].listHead.next; while (iter && 0 < maxPrint--) { - kprintf("0x%p -> 0x%p | ", iter, iter->next); + KPRINTF("0x%p -> 0x%p | ", iter, iter->next); iter = iter->next; } - kprintf("\n"); + KPRINTF("\n"); } }