Commit d7ffb14c authored by Léo Grange's avatar Léo Grange

integrate memory areas in process and MMU subsystems

parent 9e5ec46c
......@@ -13,6 +13,7 @@
#include <sys/memory.h>
#include <utils/log.h>
#include <sys/kdebug.h>
#include <sys/mem_area.h>
//void exception_handler() __attribute__ ((interrupt_handler, section(".handler.exception")));
......@@ -156,6 +157,39 @@ void tlbmiss_handler()
page = mem_find_page(curpr->dir_list,
(void*)(vpn << PM_PAGE_ORDER) );
// if page is not in dir list (or is invalid), maybe it exists in memory
// area (allocate it)
// FIXME not working for shared pages
if(page == NULL || !(page->private.flags & MEM_PAGE_VALID)) {
struct mem_area *area;
void *virtaddr;
virtaddr = PM_PHYSICAL_ADDR(vpn);
area = mem_area_find(curpr, virtaddr);
if(area != NULL) {
union pm_page pmpage;
void *pmaddr;
// 'major' page fault, create and fill it
// FIXME UNCACHED due to temporary hack to be sure nothing is retained in cache
pmaddr = arch_pm_get_free_page(MEM_PM_UNCACHED);
if(pmaddr != NULL) {
pmpage.private.ppn = PM_PHYSICAL_PAGE(pmaddr);
pmpage.private.flags = MEM_PAGE_PRIVATE | MEM_PAGE_VALID; // | MEM_PAGE_CACHED;
mem_insert_page(& curpr->dir_list, &pmpage, virtaddr);
// FIXME get min(PM_PAGE_BYTES, max allowed) bytes
mem_area_copy_raw(area, (virtaddr - area->address), pmaddr, PM_PAGE_BYTES);
// not optimized, but ensure page points to a valid page struct
page = mem_find_page(curpr->dir_list, virtaddr);
printk(LOG_DEBUG, "tlb major fault: page inserted (virt %p -> phy %p)\n",
virtaddr, PM_PHYSICAL_ADDR(page->private.ppn));
}
}
}
if(page != NULL) {
unsigned int flags;
uint32 ppn = 0;
......
......@@ -38,6 +38,7 @@
#include "sys/console.h"
#include "sys/sysctl.h"
#include "sys/mem_area.h"
extern char cmdargs_begin;
extern char cmdargs_end;
......@@ -131,6 +132,7 @@ void init() {
//DBG_WAIT;
// Initializing VFS and device sub-sytems, mount platform filesystems,
// register platform devices...
......@@ -215,6 +217,10 @@ void init() {
test_vfs();
*/
// memory area subsystem
mem_area_init();
process_init();
sched_init();
test_process();
......
......@@ -87,16 +87,36 @@ int mem_area_copy_raw(struct mem_area *area, size_t offset, void *dest, size_t s
if(area->flags & MEM_AREA_TYPE_ANON) {
// anonymous area, the current implementation do nothing...
ret = 0;
if(offset + size > area->max_size) {
printk(LOG_ERR, "mem_area: attempt to copy extra bytes (anon)\n");
}
else {
if(offset + size > area->anon.size && (area->flags & MEM_AREA_MAYGROW)) {
printk(LOG_DEBUG, "mem_area: extends area (%d->%d)\n",
area->anon.size, offset + size);
}
ret = 0;
}
}
else if(area->flags & MEM_AREA_TYPE_FILE) {
// file mapped to memory, for now use a generic way to handle them
// TODO improve this with map_area_ops struct to allow "override"
size_t nbread;
vfs_lseek(area->file.filep, SEEK_SET, offset);
vfs_lseek(area->file.filep, area->file.origin + offset, SEEK_SET);
nbread = vfs_read(area->file.filep, dest, size);
ret = nbread == size ? 0 : -1;
if(ret) {
printk(LOG_ERR, "mem_area: failed loading %d bytes from offset 0x%x"
" [absolute 0x%x] (read returns %d)\n",
size, offset, area->file.origin + offset, nbread);
}
else {
printk(LOG_DEBUG, "mem_area: loaded %d bytes @%p from file\n", size, dest);
}
//print_memory(LOG_DEBUG, dest, nbread);
}
return ret;
......
......@@ -196,6 +196,20 @@ void process_terminate(struct process *proc, int status) {
// FIXME controlling terminal is process was session leader
// remove all memory areas
struct list_head *cur_area;
cur_area = proc->mem_areas.next;
while(cur_area != & proc->mem_areas) {
struct list_head *next_area = cur_area->next;
struct mem_area *area = container_of(cur_area, struct mem_area, list);
mem_area_free(area);
cur_area = next_area;
}
INIT_LIST_HEAD(& proc->mem_areas);
// release the used address space, and free each allocated physical pages
arch_adrsp_release(& proc->addr_space);
for(curdir = proc->dir_list; curdir != NULL; curdir = nextdir) {
......@@ -263,6 +277,20 @@ pid_t sys_fork() {
newproc->ctty = cur->ctty;
// copy each memory area
struct list_head *area_list;
list_for_each(area_list, & cur->mem_areas) {
// duplicate it
// FIXME file should be duplicated? Or a counter need to be used?
struct mem_area *old_area = container_of(area_list, struct mem_area, list);
struct mem_area *new_area;
new_area = mem_area_alloc();
*new_area = *old_area;
mem_area_insert(newproc, new_area);
}
// copy each memory page with same virtual addresses
// TODO copy-on-write system!
for(dir = cur->dir_list; dir != NULL; dir = dir->next) {
......@@ -427,6 +455,20 @@ int sys_execve(const char *filename, char *const argv[], char *const envp[]) {
cur->sig_array[i].sa_handler = SIG_DFL;
}
// remove all memory areas
struct list_head *cur_area;
cur_area = cur->mem_areas.next;
while(cur_area != & cur->mem_areas) {
struct list_head *next_area = cur_area->next;
struct mem_area *area = container_of(cur_area, struct mem_area, list);
mem_area_free(area);
cur_area = next_area;
}
INIT_LIST_HEAD(& cur->mem_areas);
// use a new address space to avoid to use old TLB records
arch_adrsp_release(& cur->addr_space);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment