209 lines
4.6 KiB
C
209 lines
4.6 KiB
C
#include "alloc.h"
|
|
#include "../include/limine.h"
|
|
#include "common.h"
|
|
#include "print.h"
|
|
#include "lib/stdio.h"
|
|
|
|
#ifdef DBG
|
|
#define dprint(x) print(x)
|
|
#define dprint8(x) print8(x)
|
|
#define dprint16(x) print16(x)
|
|
#define dprint32(x) print32(x)
|
|
#define dprint64(x) print64(x)
|
|
#else
|
|
#define dprint(x)
|
|
#define dprint8(x)
|
|
#define dprint16(x)
|
|
#define dprint32(x)
|
|
#define dprint64(x)
|
|
#endif
|
|
__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] |= (1ULL << bit);
|
|
}
|
|
|
|
static void usepagerange(size_t page, size_t len) {
|
|
for (size_t i = 0; i < len; i++) {
|
|
usepage(i + page);
|
|
}
|
|
}
|
|
|
|
static void unusepage(size_t page) {
|
|
size_t idx = page / 64;
|
|
size_t bit = page & 63;
|
|
alloc_bitmap[idx] &= ~(1ULL << bit);
|
|
}
|
|
|
|
static void unusepagerange(size_t page, size_t len) {
|
|
for (size_t i = 0; i < len; i++) {
|
|
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) {
|
|
print("Too many or too few pages: ");
|
|
print8(pages);
|
|
print("\n");
|
|
return NULL;
|
|
}
|
|
|
|
|
|
dprint("Attempting to find ");
|
|
dprint64(pages);
|
|
dprint(" consecutive pages.....");
|
|
size_t consecutive = 0;
|
|
|
|
for (size_t i = 0; i < total_pages / 64; i++) {
|
|
u64 word = alloc_bitmap[i];
|
|
if (word == 0) {
|
|
if (!consecutive)
|
|
page = i * 64;
|
|
consecutive += 64;
|
|
if (consecutive >= pages) {
|
|
usepagerange(page, pages);
|
|
dprint("succeeded!\n");
|
|
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);
|
|
dprint("succeeded!\n");
|
|
|
|
return addr(page);
|
|
}
|
|
} else {
|
|
consecutive = 0;
|
|
page = -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
dprint("failed :(!\n");
|
|
|
|
return NULL;
|
|
}
|
|
|