2018-08-06 18:41:45 +02:00
|
|
|
#include "mem.h"
|
2020-04-27 00:14:37 +02:00
|
|
|
#include "klibc.h"
|
2018-08-09 22:19:34 +02:00
|
|
|
#include "list.h"
|
2018-11-09 22:32:21 +01:00
|
|
|
#include "types.h"
|
2018-08-06 18:41:45 +02:00
|
|
|
|
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-14 14:28:06 +01:00
|
|
|
static unsigned long allocatedPage = 0;
|
|
|
|
|
|
|
|
int memSetup(paddr_t upperMem, paddr_t *lastUsedOut)
|
2018-08-06 18:41:45 +02:00
|
|
|
{
|
2020-04-27 00:14:37 +02:00
|
|
|
// Align upper mem (in kB) on page size even if it does loose a page
|
|
|
|
upperMem = ALIGN_DOWN(upperMem, PAGE_SIZE / 1024);
|
2018-11-09 22:32:21 +01:00
|
|
|
|
2020-04-27 00:14:37 +02:00
|
|
|
printf("Available Mem from 0x%x to 0x%x: %dMB \n", &__ld_kernel_end, upperMem * 1024,
|
|
|
|
(upperMem * 1024 - (uint32_t)&__ld_kernel_end) / (1024 * 1024));
|
|
|
|
// Memory description is stored after the kernel. We need some place to store it
|
|
|
|
unsigned long memdesc_end =
|
|
|
|
(unsigned long)page_desc + ((upperMem) / (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;
|
|
|
|
*lastUsedOut = memdesc_end;
|
|
|
|
top_mem = upperMem * 1024;
|
|
|
|
for (uint i = 0; i < (upperMem / (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;
|
2018-08-06 18:41:45 +02:00
|
|
|
}
|
2018-08-09 22:19:34 +02:00
|
|
|
|
2018-11-09 21:49:23 +01:00
|
|
|
struct mem_desc *addr2memDesc(paddr_t addr)
|
2018-08-09 22:19:34 +02:00
|
|
|
{
|
2020-04-27 00:14:37 +02:00
|
|
|
if (addr > top_mem || addr < bottom_mem)
|
|
|
|
return NULL;
|
2018-11-09 16:30:42 +01:00
|
|
|
|
2020-04-27 00:14:37 +02:00
|
|
|
int idx = addr >> PAGE_SHIFT;
|
|
|
|
return page_desc + idx;
|
2018-08-09 22:19:34 +02:00
|
|
|
}
|
|
|
|
|
2018-11-09 21:49:23 +01:00
|
|
|
paddr_t allocPhyPage(void)
|
2018-08-09 22:19:34 +02:00
|
|
|
{
|
2020-04-27 00:14:37 +02:00
|
|
|
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);
|
|
|
|
allocatedPage++;
|
|
|
|
return mem->phy_addr;
|
2018-08-09 22:19:34 +02:00
|
|
|
}
|
|
|
|
|
2018-11-09 21:49:23 +01:00
|
|
|
int unrefPhyPage(paddr_t addr)
|
2018-08-09 22:19:34 +02:00
|
|
|
{
|
2020-04-27 00:14:37 +02:00
|
|
|
struct mem_desc *mem = addr2memDesc(addr);
|
|
|
|
if (!mem) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
mem->ref--;
|
|
|
|
if (mem->ref == 0) {
|
|
|
|
allocatedPage--;
|
|
|
|
list_delete(used_page, mem);
|
|
|
|
list_add_tail(free_page, mem);
|
|
|
|
}
|
2018-08-09 22:19:34 +02:00
|
|
|
|
2020-04-27 00:14:37 +02:00
|
|
|
return mem->ref;
|
2018-08-09 22:19:34 +02:00
|
|
|
}
|
2018-11-09 17:07:39 +01:00
|
|
|
|
2018-11-09 21:49:23 +01:00
|
|
|
int refPhyPage(paddr_t addr)
|
2018-11-09 17:07:39 +01:00
|
|
|
{
|
2020-04-27 00:14:37 +02:00
|
|
|
struct mem_desc *mem = addr2memDesc(addr);
|
|
|
|
if (!mem) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
mem->ref++;
|
|
|
|
if (mem->ref == 1) {
|
|
|
|
allocatedPage++;
|
|
|
|
list_add_tail(used_page, mem);
|
|
|
|
list_delete(free_page, mem);
|
|
|
|
}
|
2018-11-09 17:07:39 +01:00
|
|
|
|
2020-04-27 00:14:37 +02:00
|
|
|
return 0;
|
2018-11-09 17:07:39 +01:00
|
|
|
}
|
2018-11-14 14:28:06 +01:00
|
|
|
|
|
|
|
unsigned long getNbAllocatedPage(void)
|
|
|
|
{
|
2020-04-27 00:14:37 +02:00
|
|
|
return allocatedPage;
|
2018-11-14 14:28:06 +01:00
|
|
|
}
|