summaryrefslogtreecommitdiff
path: root/arch/i386/kernel/pmem.c
blob: 40e3400ead3af1541e71135a271a2697e893dfc2 (plain)
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
#include <kernel/pmem.h>
#include <kernel/asm.h>
#include <kernel/vmem.h>
#include <kernel/panic.h>
#include <kernel/paging.h>
#include <libk/io.h>
#include <libk/string.h>

static struct pfa_page freelist;

void pfa_init(struct mboot_info *header) {
        struct mboot_mmap_entry *mme;
        for (uintptr_t i = 0; i < header->mmap_length; i += sizeof(struct mboot_mmap_entry)) {
                mme = (struct mboot_mmap_entry*)(header->mmap_addr + i);
                if (mme->type == MBOOT_MEM_AVAILABLE)
                        pfa_free(mme->addr_low, mme->len_low / PAGE_SIZE);
        }
}

uintptr_t pfa_alloc(size_t num_pages) {
        struct pfa_page *temp = (struct pfa_page*)PAGE_TMP_MAP;
        map_page(freelist.next, PAGE_TMP_MAP, PD_PRES | PD_RW);
        uintptr_t ret = freelist.next;
        freelist.next = temp->next;
        memset(temp, 0, 32);
        unmap_page(PAGE_TMP_MAP);
        return ret;
}

void pfa_free(uintptr_t paddr, size_t num_pages) {
        uintptr_t addr;
        struct pfa_page *temp = (struct pfa_page*)PAGE_TMP_MAP;
        for (size_t i = 0; i < num_pages; i++) {
                addr = (i * PAGE_SIZE + paddr);
                if (addr >= KSTART && addr < KEND)
                        continue;
                if (addr == 0)
                        continue;
                map_page(addr, PAGE_TMP_MAP, PD_PRES | PD_RW);
                memset(PAGE_TMP_MAP, 1, 32);
                temp->next = freelist.next;
                freelist.next = addr;
                unmap_page(PAGE_TMP_MAP);
        }
}