#include "mem.h" #include "list.h" #include "types.h" #include "vga.h" static struct mem_desc *page_desc = (struct mem_desc *)&__ld_kernel_end; static struct mem_desc *free_page; static struct mem_desc *used_page; static unsigned long bottom_mem; static unsigned long top_mem; int memSetup(unsigned long upper_mem) { // Align upper mem (in kB) on page size even if it does loose a page upper_mem = ALIGN_DOWN(upper_mem, PAGE_SIZE / 1024); printf("Available Mem from %d to %d \n", &__ld_kernel_end, upper_mem * 1024); // Memory description is stored after the kernel. We need some place to store it unsigned long memdesc_end = (unsigned long)page_desc + ((upper_mem) / (PAGE_SIZE / 1024)) * sizeof(struct mem_desc); uint lastUsed = (memdesc_end >> PAGE_SHIFT) + 1; list_init(free_page); list_init(used_page); bottom_mem = lastUsed; top_mem = upper_mem * 1024; for (uint i = 0; i < (upper_mem / (PAGE_SIZE / 1024)); i++) { struct mem_desc *mem = &page_desc[i]; if (i < lastUsed) { mem->ref = 1; list_add_tail(used_page, mem); } else { mem->ref = 0; list_add_tail(free_page, mem); } mem->phy_addr = i * PAGE_SIZE; } return 0; } struct mem_desc *addr2memDesc(paddr_t addr) { if (addr > top_mem || addr < bottom_mem) return NULL; int idx = addr >> PAGE_SHIFT; return page_desc + idx; } paddr_t allocPhyPage(void) { if (list_is_empty(free_page)) { return (unsigned long)NULL; } struct mem_desc *mem = list_pop_head(free_page); mem->ref = 1; list_add_tail(used_page, mem); return mem->phy_addr; } int unrefPhyPage(paddr_t addr) { struct mem_desc *mem = addr2memDesc(addr); if (!mem) { return -1; } mem->ref--; if (mem->ref == 0) { list_delete(used_page, mem); list_add_tail(free_page, mem); } return 0; } int refPhyPage(paddr_t addr) { struct mem_desc *mem = addr2memDesc(addr); if (!mem) { return -1; } mem->ref++; if (mem->ref == 1) { list_add_tail(used_page, mem); list_delete(free_page, mem); } return 0; }