[MEMORY] Process memory management
This commit is contained in:
parent
ba2ecd725f
commit
0101440894
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user