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

integrate memory areas in process and MMU subsystems

parent 9e5ec46c
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
@@ -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;
+6 −0
Original line number Diff line number Diff line
@@ -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();
+22 −2
Original line number Diff line number Diff line
@@ -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...
		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;
+42 −0
Original line number Diff line number Diff line
@@ -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);