1#include <console/printf.h>
2#include <limine.h>
3#include <math/align.h>
4#include <mem/alloc.h>
5#include <mem/bitmap.h>
6#include <mem/buddy.h>
7#include <mem/domain.h>
8#include <mem/pmm.h>
9#include <smp/domain.h>
10#include <stdbool.h>
11#include <stdint.h>
12#include <string.h>
13
14struct limine_memmap_response *memmap;
15typedef paddr_t (*alloc_fn)(size_t pages, enum alloc_flags f);
16
17typedef void (*free_fn)(paddr_t addr, size_t pages);
18
19static alloc_fn current_alloc_fn = bitmap_alloc_pages;
20static free_fn current_free_fn = bitmap_free_pages;
21
22void pmm_early_init(struct limine_memmap_request m) {
23 bitmap = boot_bitmap;
24 memmap = m.response;
25
26 if (memmap == NULL || memmap->entries == NULL) {
27 panic("Failed to retrieve Limine memory map");
28 return;
29 }
30
31 uint64_t total_phys = 0;
32 for (uint64_t i = 0; i < memmap->entry_count; i++) {
33 struct limine_memmap_entry *entry = memmap->entries[i];
34
35 if (entry->type == LIMINE_MEMMAP_USABLE) {
36 total_phys += entry->length;
37 uint64_t start = ALIGN_DOWN(entry->base, PAGE_SIZE);
38 uint64_t end = ALIGN_UP(entry->base + entry->length, PAGE_SIZE);
39
40 for (uint64_t addr = start; addr < end; addr += PAGE_SIZE) {
41 uint64_t index = addr / PAGE_SIZE;
42 if (index < BOOT_BITMAP_SIZE * 8) {
43 clear_bit(index);
44 }
45 }
46 }
47 }
48
49 uint64_t last_usable_pfn = 0;
50
51 for (uint64_t i = 0; i < memmap->entry_count; i++) {
52 struct limine_memmap_entry *entry = memmap->entries[i];
53 if (entry->type != LIMINE_MEMMAP_USABLE)
54 continue;
55
56 uint64_t end =
57 ALIGN_UP(entry->base + entry->length, PAGE_SIZE) / PAGE_SIZE;
58
59 if (end > last_usable_pfn)
60 last_usable_pfn = end;
61 }
62
63 global.last_pfn = last_usable_pfn;
64 global.total_pages = total_phys / PAGE_SIZE;
65}
66
67void pmm_mid_init() {
68 buddy_init();
69 current_alloc_fn = buddy_alloc_pages_global;
70 current_free_fn = buddy_free_pages_global;
71}
72
73void pmm_late_init(void) {
74 domain_buddies_init();
75 current_alloc_fn = domain_alloc;
76 current_free_fn = domain_free;
77}
78
79paddr_t pmm_alloc_page_internal(enum alloc_flags f) {
80 return pmm_alloc_pages_internal(count: 1, flags: f);
81}
82
83void pmm_free_page(paddr_t addr) {
84 pmm_free_pages(addr, count: 1);
85}
86
87paddr_t pmm_alloc_pages_internal(uint64_t count, enum alloc_flags f) {
88 return current_alloc_fn(count, f);
89}
90
91void pmm_free_pages(paddr_t addr, uint64_t count) {
92 if (!addr)
93 return;
94
95 current_free_fn(addr, count);
96}
97
98uint64_t pmm_get_usable_ram(void) {
99 return global.total_pages * PAGE_SIZE;
100}
101