1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
#define KERNEL_HEAP_SIZE 0x100000 extern struct limine_memmap_response *memmap_response; uint64_t kernel_heap_start = 0; uint64_t kernel_heap_end = 0; uint64_t kernel_heap_counter = 0; /* Freelist implementation */ uint64_t *heap_free_list = NULL; uint64_t heap_free_page_count = 0; extern uint64_t hhdmoffset; void kernel_heap_init(){ bool suitable_place_found = false; struct limine_memmap_entry **entries = memmap_response->entries; /* Place the heap at the first usable address */ for(uint64_t i = 0; i < memmap_response->entry_count; i++){ if(entries[i]->type == LIMINE_MEMMAP_USABLE){ if(entries[i]->length < KERNEL_HEAP_SIZE){ continue; } suitable_place_found = true; kernel_heap_start = entries[i]->base; kernel_heap_end = kernel_heap_start + KERNEL_HEAP_SIZE; break; } } if(!suitable_place_found){ klog(LOG_ERROR, __func__, "Failed to find a suitable place for the kernel heap"); } /* Set the heap as used in the PMM */ for(uint64_t j = 0; j < KERNEL_HEAP_SIZE; j++){ pmm_alloc(); } for(uint64_t j = 0; j < KERNEL_HEAP_SIZE; j += 4096){ heap_free((uint64_t*)(kernel_heap_start + hhdmoffset + j)); } kprintf("Free heap pages: {dn}", heap_free_page_count); kprintf("Done!\n"); } /* Allocates n number of continous pages, returns the address of the first one */ void *kmalloc(uint64_t size){ /* How many pages to allocate */ uint64_t pages_to_alloc = size / PAGE_SIZE; /* Get the first page, which we will return to the callee */ uint64_t *ret = heap_alloc(); if(!ret){ klog(LOG_ERROR, __func__, "kmalloc: Failed to allocate memory"); kkill(); } /* Allocate the rest of the pages */ for(uint64_t i = 0; i < pages_to_alloc; i++){ if(!heap_alloc()){ klog(LOG_ERROR, __func__, "kmalloc: Failed to allocate memory"); kkill(); } } return ret; } void heap_free(uint64_t *addr){ /* Make the given page point to the previous free page */ *addr = (uint64_t)heap_free_list; /* Make the free_list point to the newly freed page */ heap_free_list = addr; heap_free_page_count++; return; } uint64_t *heap_alloc(){ if(heap_free_page_count <= 0){ return NULL; } /* Fetch the address of the free page in free_list and make it point to the next free page */ heap_free_list = (uint64_t*)(*heap_free_list); heap_free_page_count--; memset(heap_free_list, 0, 4096); return heap_free_list; }