matos/core/mem.c

91 lines
2.0 KiB
C
Raw Normal View History

2018-08-06 18:41:45 +02:00
#include "mem.h"
2018-08-09 22:19:34 +02:00
#include "list.h"
#include "types.h"
2018-08-06 18:41:45 +02:00
#include "vga.h"
2018-08-09 22:19:34 +02:00
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;
2018-11-11 23:04:23 +01:00
int memSetup(paddr_t upperMem, paddr_t * lastUsedOut)
2018-08-06 18:41:45 +02:00
{
// Align upper mem (in kB) on page size even if it does loose a page
2018-11-11 23:04:23 +01:00
upperMem = ALIGN_DOWN(upperMem, PAGE_SIZE / 1024);
2018-11-11 23:04:23 +01:00
printf("Available Mem from %d to %d \n", &__ld_kernel_end, upperMem * 1024);
// Memory description is stored after the kernel. We need some place to store it
2018-08-06 18:41:45 +02:00
unsigned long memdesc_end =
(unsigned long)page_desc +
2018-11-11 23:04:23 +01:00
((upperMem) / (PAGE_SIZE / 1024)) * sizeof(struct mem_desc);
2018-08-06 18:41:45 +02:00
uint lastUsed = (memdesc_end >> PAGE_SHIFT) + 1;
2018-08-09 22:19:34 +02:00
list_init(free_page);
list_init(used_page);
bottom_mem = lastUsed;
2018-11-11 23:04:23 +01:00
*lastUsedOut = memdesc_end;
top_mem = upperMem * 1024;
for (uint i = 0; i < (upperMem / (PAGE_SIZE / 1024)); i++) {
2018-08-06 18:41:45 +02:00
struct mem_desc *mem = &page_desc[i];
2018-08-09 22:19:34 +02:00
if (i < lastUsed) {
2018-08-06 18:41:45 +02:00
mem->ref = 1;
2018-08-09 22:19:34 +02:00
list_add_tail(used_page, mem);
} else {
2018-08-06 18:41:45 +02:00
mem->ref = 0;
2018-08-09 22:19:34 +02:00
list_add_tail(free_page, mem);
}
2018-08-06 18:41:45 +02:00
mem->phy_addr = i * PAGE_SIZE;
}
return 0;
}
2018-08-09 22:19:34 +02:00
struct mem_desc *addr2memDesc(paddr_t addr)
2018-08-09 22:19:34 +02:00
{
if (addr > top_mem || addr < bottom_mem)
return NULL;
2018-08-09 22:19:34 +02:00
int idx = addr >> PAGE_SHIFT;
return page_desc + idx;
}
paddr_t allocPhyPage(void)
2018-08-09 22:19:34 +02:00
{
if (list_is_empty(free_page)) {
2018-08-09 22:19:34 +02:00
return (unsigned long)NULL;
}
2018-08-09 22:19:34 +02:00
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)
2018-08-09 22:19:34 +02:00
{
struct mem_desc *mem = addr2memDesc(addr);
if (!mem) {
return -1;
}
mem->ref--;
if (mem->ref == 0) {
list_delete(used_page, mem);
2018-08-09 22:19:34 +02:00
list_add_tail(free_page, mem);
}
2018-11-12 23:01:55 +01:00
return mem->ref;
2018-08-09 22:19:34 +02:00
}
2018-11-09 17:07:39 +01:00
int refPhyPage(paddr_t addr)
2018-11-09 17:07:39 +01:00
{
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;
}