197 lines
4.0 KiB
C
197 lines
4.0 KiB
C
#include "alloc.h"
|
|
#include "common.h"
|
|
#include "print.h"
|
|
#include "../include/limine.h"
|
|
|
|
|
|
__attribute__((used, section(".limine_requests")))
|
|
static volatile struct limine_memmap_request mem_req = {
|
|
.id = LIMINE_MEMMAP_REQUEST_ID,
|
|
.revision = 0,
|
|
};
|
|
|
|
extern u32 fg, bg;
|
|
|
|
static void print_memmap_entry(struct limine_memmap_entry* entry) {
|
|
u32 savefg = fg;
|
|
u32 savebg = bg;
|
|
static const char* type_strs[] = {
|
|
"Usable",
|
|
"Reserved",
|
|
"ACPI Reclaimable",
|
|
"ACPI NVS",
|
|
"BAD!!!",
|
|
"Bootloader Reclaimable",
|
|
"Executable and Modules",
|
|
"Framebuffer",
|
|
"ACPI Tables",
|
|
};
|
|
|
|
static u32 type_colors[] = {
|
|
0x00AF00,
|
|
0xAF1F00,
|
|
0x7f7f00,
|
|
0x7f7f00,
|
|
0xFF0000,
|
|
0x007f7f,
|
|
0x408000,
|
|
0x0000FF,
|
|
0x00FF00
|
|
};
|
|
|
|
bg = type_colors[entry->type];
|
|
fg = ~bg;
|
|
|
|
u64 addr = entry->base;
|
|
u64 end = addr + entry->length;
|
|
print("[");
|
|
print(type_strs[entry->type]);
|
|
print("]");
|
|
print64(addr);
|
|
print(" - ");
|
|
print64(end);
|
|
print("\n");
|
|
fg = savefg;
|
|
bg = savebg;
|
|
}
|
|
|
|
|
|
|
|
static size_t total_pages;
|
|
static u8* alloc_start;
|
|
static u8* alloc_end;
|
|
static u8* alloc_next;
|
|
static u64* alloc_bitmap;
|
|
|
|
void alloc_init() {
|
|
print("Initializing Page Allocator\n");
|
|
|
|
if(!mem_req.response) {
|
|
print("Failed to get memory map :(\n)");
|
|
hang();
|
|
}
|
|
|
|
u64 largest_base = 0;
|
|
size_t largest_size = 0;
|
|
|
|
for(size_t i = 0; i < mem_req.response->entry_count; i++) {
|
|
struct limine_memmap_entry* entry = mem_req.response->entries[i];
|
|
print_memmap_entry(entry);
|
|
|
|
if(entry->type == LIMINE_MEMMAP_USABLE) {
|
|
if(entry->length > largest_size) {
|
|
largest_base = entry->base;
|
|
largest_size = entry->length;
|
|
print("\t\\LARGEST USABLE: ");
|
|
print64(entry->length >> 20);
|
|
print("MiB\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!largest_size) {
|
|
print("Couldn't find a free page!!!\n");
|
|
hang();
|
|
}
|
|
|
|
|
|
total_pages = largest_size / PAGE_SIZE;
|
|
size_t usage_bitmap_size = (total_pages + 7) / 8;
|
|
total_pages -= (usage_bitmap_size + PAGE_SIZE-1) / PAGE_SIZE;
|
|
alloc_bitmap = (u64*)(phys_to_virt(largest_base));
|
|
alloc_start = (u8*)(phys_to_virt(largest_base + usage_bitmap_size));
|
|
alloc_next = alloc_start;
|
|
alloc_end = (u8*)(phys_to_virt(largest_base + largest_size));
|
|
}
|
|
|
|
static size_t page(void* addr) {
|
|
return ((u8*)addr - alloc_start) / PAGE_SIZE;
|
|
}
|
|
|
|
static void* addr(size_t page) {
|
|
return alloc_start + page*PAGE_SIZE;
|
|
}
|
|
|
|
static void usepage(size_t page) {
|
|
size_t idx = page / 64;
|
|
size_t bit = page & 63;
|
|
alloc_bitmap[idx] |= (1 << bit);
|
|
}
|
|
|
|
static void usepagerange(size_t page, size_t len) {
|
|
for(size_t i = 0; i < len; len++) {
|
|
usepage(i + page);
|
|
}
|
|
}
|
|
|
|
static void unusepage(size_t page) {
|
|
size_t idx = page / 64;
|
|
size_t bit = page & 63;
|
|
alloc_bitmap[idx] &= ~(1 << bit);
|
|
}
|
|
|
|
static void unusepagerange(size_t page, size_t len) {
|
|
for(size_t i = 0; i < len; len++) {
|
|
unusepage(i+page);
|
|
}
|
|
}
|
|
|
|
static u8 getpageusage(size_t page) {
|
|
return (alloc_bitmap[page / 8] >> (page & 7)) & 1;
|
|
}
|
|
|
|
void dealloc(void* addr, size_t size) {
|
|
// adjust to page size
|
|
size_t pages = (size+PAGE_SIZE-1) / PAGE_SIZE;
|
|
unusepagerange(page(addr), pages);
|
|
}
|
|
|
|
void* alloc(size_t size) {
|
|
size_t pages = (size + PAGE_SIZE - 1) / PAGE_SIZE;
|
|
size_t page = 0;
|
|
|
|
if(pages == 0 || pages >= total_pages) {
|
|
return NULL;
|
|
}
|
|
|
|
size_t consecutive = 0;
|
|
|
|
for(size_t i = 0; i < pages; i++) {
|
|
u64 word = alloc_bitmap[i];
|
|
if(word == 0) {
|
|
if(!consecutive)
|
|
page = i * 64;
|
|
consecutive += 64;
|
|
if(consecutive >= pages) {
|
|
usepagerange(page, pages);
|
|
return addr(page);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if(word == ~0ULL) {
|
|
consecutive = 0;
|
|
page = -1;
|
|
}
|
|
|
|
for(size_t bit = 0; bit < 64; bit++) {
|
|
if((word & (1ULL << bit)) == 0) {
|
|
if(!consecutive)
|
|
page = i * 64 + bit;
|
|
|
|
if(++consecutive >= pages) {
|
|
usepagerange(page, pages);
|
|
return addr(pages);
|
|
}
|
|
} else {
|
|
consecutive = 0;
|
|
page = -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
return NULL;
|
|
}
|
|
|