[MEMORY] Process memory management
This commit is contained in:
114
kernel/proc/procmm.c
Normal file
114
kernel/proc/procmm.c
Normal file
@@ -0,0 +1,114 @@
|
||||
#include <scheduler.h>
|
||||
#include <list.h>
|
||||
#include <debug.h>
|
||||
|
||||
procmm_mmap_t *procmm_new_map(process_t *proc, procmm_mmap_t *src)
|
||||
{
|
||||
procmm_mmap_t *map = kcalloc(1, sizeof(procmm_mmap_t));
|
||||
map->proc = proc;
|
||||
map->P4 = vmm_new_P4();
|
||||
LIST_INIT(map, areas);
|
||||
|
||||
if(src)
|
||||
{
|
||||
LIST_FOREACH(src->areas, procmm_area_t, o, areas)
|
||||
{
|
||||
procmm_map(map, o->start, o->end, o->flags);
|
||||
vmm_p4_memcpy(map->P4, (void *)o->start, src->P4, (void *)o->start, o->end-o->start);
|
||||
}
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
void procmm_free_map(process_t *proc)
|
||||
{
|
||||
procmm_mmap_t *map = proc->mmap;
|
||||
procmm_area_t *o = map->areas.next;
|
||||
while(o)
|
||||
{
|
||||
procmm_area_t *next = o->areas.next;
|
||||
procmm_unmap(o);
|
||||
o = next;
|
||||
}
|
||||
map->brk = 0;
|
||||
map->stack = 0;
|
||||
vmm_free_P4(map->P4);
|
||||
kfree(map);
|
||||
}
|
||||
|
||||
void procmm_print_map(procmm_mmap_t *map)
|
||||
{
|
||||
debug_info("Procmm map (process:%d)\n", map->proc->pid);
|
||||
LIST_FOREACH(map->areas, procmm_area_t, o, areas)
|
||||
{
|
||||
debug(" %x->%x (%x)", o->start, o->end, o->flags);
|
||||
if(o == map->brk)
|
||||
debug(" BRK");
|
||||
if(o == map->stack)
|
||||
debug(" STACK");
|
||||
debug("\n");
|
||||
}
|
||||
}
|
||||
|
||||
procmm_area_t *procmm_map(procmm_mmap_t *map, uintptr_t start, uintptr_t end, uint64_t flags)
|
||||
{
|
||||
procmm_area_t *a = kcalloc(1, sizeof(procmm_area_t));
|
||||
a->start = start;
|
||||
a->end = end;
|
||||
a->flags = flags;
|
||||
a->map = map;
|
||||
LIST_INIT(a, areas);
|
||||
|
||||
LIST_FOREACH(map->areas, procmm_area_t, o, areas)
|
||||
{
|
||||
if(!((o->end < start) || (o->start > a->end)))
|
||||
{
|
||||
// Overlapping areas
|
||||
debug_error("PROCMM - Overlapping areas (unsupported for now)\n");
|
||||
kfree(a);
|
||||
return 0;
|
||||
}
|
||||
if(o->start > a->end)
|
||||
{
|
||||
LIST_INSERT_BEFORE(map->areas, a, areas, o);
|
||||
}
|
||||
}
|
||||
if(LIST_EMPTY(a->areas))
|
||||
LIST_APPEND(map->areas, a, areas);
|
||||
|
||||
uintptr_t p = a->start;
|
||||
while(p < a->end)
|
||||
{
|
||||
vmm_set_page(map->P4, p, pmm_alloc(), PAGE_PRESENT | PAGE_WRITE | PAGE_USER);
|
||||
p += PAGE_SIZE;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
void procmm_unmap(procmm_area_t *a)
|
||||
{
|
||||
uintptr_t p = a->start;
|
||||
while(p < a->end)
|
||||
{
|
||||
uintptr_t ph = vmm_get_page(a->map->P4, p);
|
||||
pmm_free(ph);
|
||||
vmm_set_page(a->map->P4, p, 0, 0);
|
||||
p += PAGE_SIZE;
|
||||
}
|
||||
LIST_REMOVE(a->map->areas, a, areas);
|
||||
kfree(a);
|
||||
}
|
||||
|
||||
uintptr_t procmm_setup(process_t *proc)
|
||||
{
|
||||
procmm_mmap_t *map = proc->mmap;
|
||||
procmm_area_t *last_a = map->areas.prev;
|
||||
|
||||
uintptr_t brk_start = (last_a->end + PAGE_SIZE) & ~(PAGE_SIZE-1);
|
||||
map->brk = procmm_map(map, brk_start, brk_start, 0);
|
||||
|
||||
map->stack = procmm_map(map, USERSPACE_TOP, USERSPACE_TOP, 0);
|
||||
|
||||
return brk_start;
|
||||
}
|
||||
Reference in New Issue
Block a user