[MEMORY] Process memory management

This commit is contained in:
Thomas Lovén 2016-12-19 12:06:24 +01:00
parent ba2ecd725f
commit 0101440894
4 changed files with 154 additions and 10 deletions

View File

@ -35,12 +35,12 @@ int kmain(uint64_t multiboot_magic, void *multiboot_data)
uint64_t addr = 0x200000;
thread_t *th = new_thread((void *)addr, 1);
uintptr_t page = pmm_alloc();
// Write thread code to address
vmm_set_page(p1->P4, addr, page, PAGE_PRESENT | PAGE_WRITE | PAGE_USER);
memcpy(P2V(page), thread_function, PAGE_SIZE);
// Map a user stack space
vmm_set_page(p1->P4, USERSPACE_TOP-PAGE_SIZE, pmm_alloc(), PAGE_PRESENT | PAGE_WRITE | PAGE_USER);
procmm_map(p1->mmap, addr, addr+PAGE_SIZE, 0);
vmm_p4_memcpy(p1->mmap->P4, (void *)addr, 0, thread_function, PAGE_SIZE);
procmm_setup(p1);
procmm_print_map(p1->mmap);
process_attach(p1, th);
scheduler_insert(th);

View File

@ -5,7 +5,9 @@ typedef struct process_st process_t;
#include <mem.h>
#include <cpu.h>
#include <sync.h>
#include <mem.h>
struct procmm_mmap_st;
typedef struct process_st
{
uint64_t pid;
@ -13,7 +15,7 @@ typedef struct process_st
uint64_t status;
lock_t lock;
struct process_st *parent;
page_table *P4;
struct procmm_mmap_st *mmap;
LIST(struct process_st, children);
LIST(struct process_st, siblings);
LIST(thread_t, threads);
@ -29,8 +31,34 @@ typedef struct process_st
#define get_current_process() (get_cpu()->current_process)
#define set_current_process(proc) (get_cpu()->current_process = (proc))
typedef struct procmm_area_st
{
uintptr_t start;
uintptr_t end;
uint64_t flags;
struct procmm_mmap_st *map;
LIST(struct procmm_area_st, areas);
} procmm_area_t;
typedef struct procmm_mmap_st
{
process_t *proc;
page_table *P4;
LIST(struct procmm_area_st, areas);
procmm_area_t *brk;
procmm_area_t *stack;
} procmm_mmap_t;
process_t *process_spawn(process_t *parent);
void process_attach(process_t *proc, thread_t *th);
void switch_process(process_t *proc);
void process_exit(process_t *proc, uint64_t status);
void process_free(process_t *proc);
procmm_mmap_t *procmm_new_map(process_t *proc, procmm_mmap_t *src);
void procmm_free_map(process_t *proc);
void procmm_print_map(procmm_mmap_t *map);
procmm_area_t *procmm_map(procmm_mmap_t *map, uintptr_t start, uintptr_t end, uint64_t flags);
void procmm_unmap(procmm_area_t *a);
uintptr_t procmm_setup(process_t *proc);

View File

@ -12,7 +12,6 @@ process_t *process_spawn(process_t *parent)
process_t *proc = kcalloc(1, sizeof(process_t));
proc->pid = pid++;
proc->parent = parent;
proc->P4 = vmm_new_P4();
proc->state = PROC_STATE_READY;
LIST_INIT(proc, children);
@ -23,7 +22,10 @@ process_t *process_spawn(process_t *parent)
{
spin_lock(&parent->lock);
LIST_APPEND(parent->children, proc, siblings);
proc->mmap = procmm_new_map(proc, parent->mmap);
spin_unlock(&parent->lock);
} else {
proc->mmap = procmm_new_map(proc, 0);
}
if(proc->pid == 1)
@ -55,7 +57,7 @@ void switch_process(process_t *proc)
if(proc)
{
proc->state = PROC_STATE_RUNNING;
vmm_set_P4(proc->P4);
vmm_set_P4(proc->mmap->P4);
}
else
{
@ -91,8 +93,8 @@ void process_free(process_t *proc)
free_thread(th);
}
LIST_REMOVE(proc->parent->children, proc, siblings);
// Free page directory
vmm_free_P4(proc->P4);
// Free memory mappings
procmm_free_map(proc);
// Free process structure
kfree(proc);
}

114
kernel/proc/procmm.c Normal file
View 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;
}