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