From cbe2690cd5d1b290633c466ebb4df7b64b09b037 Mon Sep 17 00:00:00 2001 From: Danny Holman Date: Thu, 28 Mar 2024 21:30:12 -0500 Subject: arch: i386: kernel: add mostly finished PFA and paging system Add the mostly finished physical memory allocator and expose its functions to the paging system. Signed-off-by: Danny Holman --- arch/i386/kernel/pmem.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 arch/i386/kernel/pmem.c (limited to 'arch/i386/kernel/pmem.c') diff --git a/arch/i386/kernel/pmem.c b/arch/i386/kernel/pmem.c new file mode 100644 index 0000000..851b085 --- /dev/null +++ b/arch/i386/kernel/pmem.c @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include + +static struct pfa_zone bios_area; +static struct pfa_zone himem; + +int pfa_init(struct mboot_info *header) { + bios_area.start = 0; + bios_area.size = 0; + bios_area.freelist = NULL; + + himem.start = HIMEM_START; + himem.size = 0; + himem.freelist = NULL; + + struct mboot_mmap_entry *mme = (struct mboot_mmap_entry*)(header->mmap_addr); + map_page(NULL, (uintptr_t)mme, (uintptr_t)mme, PD_PRES); + while ((uintptr_t)mme < (header->mmap_addr + header->mmap_length)) { + if (mme->addr_low >= KSTART && mme->addr_low <= KEND) + continue; + if (mme->type == MBOOT_MEM_AVAILABLE) { + if (mme->addr_low < HIMEM_START) + pfa_free_range(&bios_area, (uintptr_t)mme->addr_low, (uintptr_t)(mme->addr_low+mme->len_low)); + else + pfa_free_range(&himem, (uintptr_t)mme->addr_low, (uintptr_t)(mme->addr_low+mme->len_low)); + } + unmap_page(NULL, (uintptr_t)mme); + mme += sizeof(struct mboot_mmap_entry); + map_page(NULL, (uintptr_t)mme, (uintptr_t)mme, PD_PRES); + } + unmap_page(NULL, (uintptr_t)mme); + return 0; +} + +uintptr_t pfa_alloc(void) { + struct pfa_page *temp = bios_area.freelist; + map_page(NULL, (uintptr_t)temp, (uintptr_t)temp, PD_RW | PD_PRES); + if (temp == NULL) + return PFA_ALLOC_ERR; + + bios_area.freelist = temp->next; + memset(temp, PFA_BLOCK_ALLOC, 32); + unmap_page(NULL, (uintptr_t)temp); + return (uintptr_t)temp; +} + +void pfa_free(struct pfa_zone *zone, uintptr_t paddr) { + if (paddr % PAGE_SIZE != 0) + panic("Task attempted to free non-aligned memory"); + if (paddr >= KSTART && paddr < KEND) + panic("Task attempted to free kernel memory"); + + map_page(NULL, paddr, paddr, PD_PRES | PD_RW); + memset((void*)paddr, PFA_BLOCK_FREE, 32); + struct pfa_page *temp = (struct pfa_page*)paddr; + temp->next = zone->freelist; + zone->freelist = temp; + unmap_page(NULL, paddr); + zone->size += PAGE_SIZE; +} + +void pfa_free_range(struct pfa_zone *zone, uintptr_t pstart, uintptr_t pend) { + uintptr_t p = PGROUNDUP(pstart); + while (p <= pend) { + pfa_free(zone, p); + p += PAGE_SIZE; + } +} -- cgit v1.2.3