diff --git a/include/l4/generic/scheduler.h b/include/l4/generic/scheduler.h index 9470a59..217035f 100644 --- a/include/l4/generic/scheduler.h +++ b/include/l4/generic/scheduler.h @@ -12,7 +12,7 @@ /* Ticks per second, try ticks = 1000 + timeslice = 1 for regressed preemption test. */ #define HZ 10 -#define TASK_TIMESLICE_DEFAULT 100 +#define TASK_TIMESLICE_DEFAULT 500 /* #define TASK_TIMESLICE_DEFAULT (HZ/100)*/ static inline struct ktcb *current_task(void) diff --git a/include/l4/macros.h b/include/l4/macros.h index e00475d..dc35805 100644 --- a/include/l4/macros.h +++ b/include/l4/macros.h @@ -77,7 +77,8 @@ /* Functions who may either return a pointer or an error code can use these: */ #define PTR_ERR(x) ((void *)(x)) -#define IS_ERR(x) (((int)(x)) < 0) +/* checks up to -1000, the rest might be valid pointers!!! E.g. 0xE0000000 */ +#define IS_ERR(x) ((((int)(x)) < 0) && (((int)(x) > -1000))) /* TEST: Is this type of printk well tested? */ #define BUG() {do { \ diff --git a/src/arch/arm/exception.c b/src/arch/arm/exception.c index b4c1847..9e92534 100644 --- a/src/arch/arm/exception.c +++ b/src/arch/arm/exception.c @@ -82,22 +82,22 @@ int check_aborts(u32 faulted_pc, u32 fsr, u32 far) int ret = 0; if (is_prefetch_abort(fsr)) { - // dprintk("Prefetch abort @ ", faulted_pc); + dprintk("Prefetch abort @ ", faulted_pc); return 0; } switch (fsr & ARM_FSR_MASK) { /* Aborts that are expected on page faults: */ case DABT_PERM_PAGE: -// dprintk("Page permission fault @ ", far); + dprintk("Page permission fault @ ", far); ret = 0; break; case DABT_XLATE_PAGE: -// dprintk("Page translation fault @ ", far); + dprintk("Page translation fault @ ", far); ret = 0; break; case DABT_XLATE_SECT: -// dprintk("Section translation fault @ ", far); + dprintk("Section translation fault @ ", far); ret = 0; break; @@ -166,7 +166,7 @@ int check_aborts(u32 faulted_pc, u32 fsr, u32 far) void data_abort_handler(u32 faulted_pc, u32 fsr, u32 far) { set_abort_type(fsr, ARM_DABT); - // dprintk("Data abort @ PC: ", faulted_pc); + dprintk("Data abort @ PC: ", faulted_pc); if (check_aborts(faulted_pc, fsr, far) < 0) { printascii("This abort can't be handled by any pager.\n"); goto error; diff --git a/tasks/fs0/include/linker.lds b/tasks/fs0/include/linker.lds index 0471090..684b13a 100644 --- a/tasks/fs0/include/linker.lds +++ b/tasks/fs0/include/linker.lds @@ -14,7 +14,7 @@ */ /* USER_AREA_START, see memlayout.h */ virtual_base = 0x10000000; -__stack = 0x20000000; +__stack = (0x20000000 - 0x1000 - 8); /* First page before env/args page */ INCLUDE "include/physical_base.lds" /* physical_base = 0x228000; */ diff --git a/tasks/libl4/src/init.c b/tasks/libl4/src/init.c index afdd027..61ae4d5 100644 --- a/tasks/libl4/src/init.c +++ b/tasks/libl4/src/init.c @@ -4,6 +4,9 @@ * Copyright (C) 2007 Bahadir Balban */ #include +#include +#include +#include INC_GLUE(memlayout.h) __l4_ipc_t __l4_ipc = 0; __l4_map_t __l4_map = 0; @@ -22,22 +25,32 @@ struct kip *kip; /* UTCB address of this task. */ struct utcb *utcb; +#include void __l4_init(void) { - kip = l4_kernel_interface(0, 0, 0); + kip = l4_kernel_interface(0, 0, 0); + + __l4_ipc = (__l4_ipc_t)kip->ipc; + __l4_map = (__l4_map_t)kip->map; + __l4_unmap = (__l4_unmap_t)kip->unmap; + __l4_kread = (__l4_kread_t)kip->kread; + __l4_getid = (__l4_getid_t)kip->getid; + __l4_thread_switch = (__l4_thread_switch_t)kip->thread_switch; + __l4_thread_control= (__l4_thread_control_t)kip->thread_control; + __l4_ipc_control= (__l4_ipc_control_t)kip->ipc_control; + __l4_space_control= (__l4_space_control_t)kip->space_control; + __l4_exchange_registers = + (__l4_exchange_registers_t)kip->exchange_registers; + __l4_kmem_grant = (__l4_kmem_grant_t)kip->kmem_grant; + __l4_kmem_reclaim = (__l4_kmem_reclaim_t)kip->kmem_reclaim; + + /* Initialise utcb only if we're not the pager */ + if (self_tid() != PAGER_TID) { + utcb = *(struct utcb **)(USER_AREA_END - 8); + printf("UTCB Read from userspace as: 0x%x\n", + (unsigned long)utcb); + } - __l4_ipc = (__l4_ipc_t)kip->ipc; - __l4_map = (__l4_map_t)kip->map; - __l4_unmap = (__l4_unmap_t)kip->unmap; - __l4_kread = (__l4_kread_t)kip->kread; - __l4_getid = (__l4_getid_t)kip->getid; - __l4_thread_switch =(__l4_thread_switch_t)kip->thread_switch; - __l4_thread_control=(__l4_thread_control_t)kip->thread_control; - __l4_ipc_control= (__l4_ipc_control_t)kip->ipc_control; - __l4_space_control=(__l4_space_control_t)kip->space_control; - __l4_exchange_registers =(__l4_exchange_registers_t)kip->exchange_registers; - __l4_kmem_grant =(__l4_kmem_grant_t)kip->kmem_grant; - __l4_kmem_reclaim =(__l4_kmem_reclaim_t)kip->kmem_reclaim; } diff --git a/tasks/libposix/shm.c b/tasks/libposix/shm.c index 69ded18..fcc7a5f 100644 --- a/tasks/libposix/shm.c +++ b/tasks/libposix/shm.c @@ -11,9 +11,7 @@ #include #include #include - -#define PTR_ERR(x) ((void *)(x)) -#define IS_ERR(x) (((int)(x)) < 0) +#include int l4_shmget(l4id_t key, int size, int shmflg) { diff --git a/tasks/mm0/include/env.h b/tasks/mm0/include/env.h new file mode 100644 index 0000000..9926d74 --- /dev/null +++ b/tasks/mm0/include/env.h @@ -0,0 +1,6 @@ +#ifndef __MM0_ENV__ +#define __MM0_ENV__ + +int task_prepare_env_file(struct tcb *t); + +#endif diff --git a/tasks/mm0/include/file.h b/tasks/mm0/include/file.h index 6af1e97..9330d69 100644 --- a/tasks/mm0/include/file.h +++ b/tasks/mm0/include/file.h @@ -5,6 +5,7 @@ #include void vmfile_init(void); + struct vm_file *vmfile_alloc_init(void); int vfs_receive_sys_open(l4id_t sender, l4id_t opener, int fd, unsigned long vnum, unsigned long size); @@ -16,4 +17,5 @@ int sys_read(l4id_t sender, int fd, void *buf, int count); int sys_write(l4id_t sender, int fd, void *buf, int count); int sys_lseek(l4id_t sender, int fd, off_t offset, int whence); +extern struct list_head vm_file_list; #endif /* __MM0_FILE_H__ */ diff --git a/tasks/mm0/include/lib/addr.h b/tasks/mm0/include/lib/addr.h new file mode 100644 index 0000000..c58bc49 --- /dev/null +++ b/tasks/mm0/include/lib/addr.h @@ -0,0 +1,23 @@ +/* + * Address allocation pool + * + * Copyright (C) 2007 Bahadir Balban + */ +#ifndef __ADDR_H__ +#define __ADDR_H__ + +#include + +/* Address pool to allocate from a range of addresses */ +struct address_pool { + struct id_pool *idpool; + unsigned long start; + unsigned long end; +}; + +int address_pool_init(struct address_pool *pool, unsigned long start, + unsigned long end); +void *address_new(struct address_pool *pool, int npages); +int address_del(struct address_pool *, void *addr, int npages); + +#endif /* __ADDR_H__ */ diff --git a/tasks/mm0/include/lib/vaddr.h b/tasks/mm0/include/lib/vaddr.h deleted file mode 100644 index d26d8af..0000000 --- a/tasks/mm0/include/lib/vaddr.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Virtual address allocation pool (for shm) - * - * Copyright (C) 2007 Bahadir Balban - */ -#ifndef __VADDR_H__ -#define __VADDR_H__ - -#include - -void vaddr_pool_init(struct id_pool *pool, unsigned long start, - unsigned long end); -void *vaddr_new(struct id_pool *pool, int npages); -int vaddr_del(struct id_pool *, void *vaddr, int npages); - -#endif /* __VADDR_H__ */ - diff --git a/tasks/mm0/include/task.h b/tasks/mm0/include/task.h index 87de34a..e6e8883 100644 --- a/tasks/mm0/include/task.h +++ b/tasks/mm0/include/task.h @@ -12,6 +12,7 @@ #include #include #include +#include #define __TASKNAME__ __PAGERNAME__ @@ -43,7 +44,7 @@ struct tcb { /* Related task ids */ unsigned int pagerid; /* Task's pager */ - /* Program segment marks */ + /* Program segment marks, ends exclusive as usual */ unsigned long text_start; unsigned long text_end; unsigned long data_start; @@ -51,9 +52,9 @@ struct tcb { unsigned long bss_start; unsigned long bss_end; unsigned long stack_start; - unsigned long stack_end; /* Exclusive of last currently mapped page */ + unsigned long stack_end; unsigned long heap_start; - unsigned long heap_end; /* Exclusive of last currently mapped page */ + unsigned long heap_end; unsigned long env_start; unsigned long env_end; unsigned long args_start; @@ -62,17 +63,24 @@ struct tcb { /* UTCB address */ unsigned long utcb_address; + /* Temporary storage for environment data */ + void *env_data; + unsigned long env_size; + + /* Per-task environment file */ + struct vm_file *env_file; + /* Virtual memory areas */ struct list_head vm_area_list; - /* Per-task swap file for now */ - struct vm_file *swap_file; - /* File descriptors for this task */ struct file_descriptor fd[TASK_OFILES_MAX]; + /* Per-task swap file for now */ + struct vm_file *swap_file; + /* Pool to generate swap file offsets for fileless anonymous regions */ - struct id_pool *swap_file_offset_pool; + struct address_pool swap_file_offset_pool; }; struct tcb *find_task(int tid); diff --git a/tasks/mm0/include/utcb.h b/tasks/mm0/include/utcb.h new file mode 100644 index 0000000..677b6ff --- /dev/null +++ b/tasks/mm0/include/utcb.h @@ -0,0 +1,7 @@ +#ifndef __MM0_UTCB_H__ +#define __MM0_UTCB_H__ + +void *utcb_vaddr_new(void); +int utcb_pool_init(void); + +#endif diff --git a/tasks/mm0/src/env.c b/tasks/mm0/src/env.c new file mode 100644 index 0000000..03a3e70 --- /dev/null +++ b/tasks/mm0/src/env.c @@ -0,0 +1,80 @@ +/* + * This implements a per-process virtual private file + * server to store environment variables. + * + * Using a per-process private file for the environment + * gives the impression as if a file-backed env/arg area + * is mapped on every process. By this means the env/arg + * pages dont need special processing and are abstracted + * away as files. Same idea can be applied to other + * private regions of a process such as the stack, so + * that debuggers can use file-based process inspection + * methods. + * + * Copyright (C) 2008 Bahadir Balban + */ +#include +#include +#include +#include +#include +#include +#include +#include + +/* Copies environment data into provided page. */ +int task_env_pager_read_page(struct vm_file *f, unsigned long f_off_pfn, + void *dest_page) +{ + struct tcb *t = find_task(f->vnum); + + if (!t) { + printf("%s: No such task tid: %d, to copy environment for.\n", + __TASKNAME__, f->vnum); + return -EINVAL; + } + + if (f_off_pfn != 0) { + printf("%s: Environments currently have a single page.\n"); + return -EINVAL; + } + + memset(dest_page, 0, PAGE_SIZE); + memcpy(dest_page, t->env_data, t->env_size); + + return 0; +} + +/* Pager for environment files */ +struct vm_pager task_env_pager = { + .ops = { + .read_page = task_env_pager_read_page, + .write_page= 0, + }, +}; + + +/* + * For a task that is about to execute, this dynamically + * generates its environment file. + */ +int task_prepare_env_file(struct tcb *t) +{ + /* Allocate a new vmfile for this task's environment */ + if (IS_ERR(t->env_file = vmfile_alloc_init())) + return (int)t->env_file; + + /* Initialise and add it to global vmfile list */ + + /* + * NOTE: Temporarily we can use tid as the vnum because + * this is the only per-task file. + */ + t->env_file->vnum = t->tid; + t->env_file->length = PAGE_SIZE; + t->env_file->pager = &task_env_pager; + list_add(&t->env_file->list, &vm_file_list); + + return 0; +} + diff --git a/tasks/mm0/src/fault.c b/tasks/mm0/src/fault.c index 122551a..dfeae5a 100644 --- a/tasks/mm0/src/fault.c +++ b/tasks/mm0/src/fault.c @@ -108,8 +108,10 @@ int do_file_page(struct fault_data *fault) * Read the page. (Simply read into the faulty area that's * now mapped using a newly allocated page.) */ - fault->vma->owner->pager->ops.read_page(fault->vma->owner, - f_offset, vaddr); + if (fault->vma->owner->pager->ops.read_page(fault->vma->owner, + f_offset, + vaddr) < 0) + BUG(); /* Remove temporary mapping */ l4_unmap(vaddr, 1, self_tid()); @@ -221,8 +223,10 @@ int do_file_page(struct fault_data *fault) * Read the page. (Simply read into the faulty area that's * now mapped using a newly allocated page.) */ - fault->vma->owner->pager->ops.read_page(fault->vma->owner, - f_offset, vaddr); + if (fault->vma->owner->pager->ops.read_page(fault->vma->owner, + f_offset, + vaddr) < 0) + BUG(); /* Unmap from self */ l4_unmap(vaddr, 1, self_tid()); @@ -252,26 +256,6 @@ int do_file_page(struct fault_data *fault) return 0; } -/* Check if faulty page has environment and argument information */ -int is_env_arg_page(struct fault_data *fault) -{ - return fault->address >= page_align(fault->task->stack_end); -} - -int fill_env_arg_info(struct fault_data *fault, void *vaddr) -{ - /* Get the env start offset in the page */ - unsigned long env_offset = fault->task->env_start & PAGE_MASK; - - /* Write the environment information */ - *(unsigned long *)(vaddr + env_offset) = fault->task->utcb_address; - printf("%s: Written env value 0x%x, to task address 0x%x\n", - __TASKNAME__, fault->task->utcb_address, - page_align(fault->address) + env_offset); - - return 0; -} - /* * Handles any page allocation or file ownership change for anonymous pages. * For read accesses initialises a wired-in zero page and for write accesses @@ -303,7 +287,7 @@ int do_anon_page(struct fault_data *fault) /* For non-existant pages just map the zero page, unless it is the * beginning of stack which requires environment and argument data. */ - if (fault->reason & VM_READ && is_env_arg_page(fault)) { + if (fault->reason & VM_READ) { /* * Zero page is a special wired-in page that is mapped * many times in many tasks. Just update its count field. @@ -315,7 +299,7 @@ int do_anon_page(struct fault_data *fault) } /* Write faults require a real zero initialised page */ - if (fault->reason & VM_WRITE || is_env_arg_page(fault)) { + if (fault->reason & VM_WRITE) { paddr = alloc_page(1); vaddr = phys_to_virt(paddr); page = phys_to_page(paddr); @@ -333,10 +317,6 @@ int do_anon_page(struct fault_data *fault) /* Clear the page */ memset((void *)vaddr, 0, PAGE_SIZE); - /* If its the env/arg page on stack, fill that information */ - if (is_env_arg_page(fault)) - fill_env_arg_info(fault, vaddr); - /* Remove temporary mapping */ l4_unmap((void *)vaddr, 1, self_tid()); diff --git a/tasks/mm0/src/file.c b/tasks/mm0/src/file.c index 4984b0d..f45ffcb 100644 --- a/tasks/mm0/src/file.c +++ b/tasks/mm0/src/file.c @@ -340,5 +340,3 @@ int sys_lseek(l4id_t sender, int fd, off_t offset, int whence) return 0; } - - diff --git a/tasks/mm0/src/init.c b/tasks/mm0/src/init.c index 6f2cf18..a97ef49 100644 --- a/tasks/mm0/src/init.c +++ b/tasks/mm0/src/init.c @@ -11,22 +11,31 @@ #include #include #include +#include #include #include #include #include #include -/* Initialise the utcb virtual address pool and its own utcb */ +/* + * Initialise the utcb virtual address pool and its own utcb. + * NOTE: This allocates memory so kmalloc must be initialised first. + */ void init_utcb(void) { void *utcb_virt, *utcb_page; /* Allocate and map one for self */ + if (utcb_pool_init() < 0) + printf("UTCB initialisation failed.\n"); utcb_virt = utcb_vaddr_new(); printf("%s: Mapping 0x%x as utcb to self.\n", __TASKNAME__, utcb_virt); utcb_page = alloc_page(1); l4_map(utcb_page, utcb_virt, 1, MAP_USR_RW_FLAGS, self_tid()); + + /* Also initialise the utcb reference that is used in l4lib. */ + utcb = utcb_virt; } void init_mm(struct initdata *initdata) @@ -43,9 +52,6 @@ void init_mm(struct initdata *initdata) init_devzero(); printf("%s: Initialised devzero.\n", __TASKNAME__); - init_utcb(); - printf("%s: Initialised own utcb.\n", __TASKNAME__); - /* Initialise the pager's memory allocator */ kmalloc_init(); printf("%s: Initialised kmalloc.\n", __TASKNAME__); @@ -53,6 +59,9 @@ void init_mm(struct initdata *initdata) shm_init(); printf("%s: Initialised shm structures.\n", __TASKNAME__); + init_utcb(); + printf("%s: Initialised own utcb.\n", __TASKNAME__); + vmfile_init(); /* Give the kernel some memory to use for its allocators */ diff --git a/tasks/mm0/src/lib/addr.c b/tasks/mm0/src/lib/addr.c new file mode 100644 index 0000000..e610fc6 --- /dev/null +++ b/tasks/mm0/src/lib/addr.c @@ -0,0 +1,44 @@ +/* + * This module allocates an unused address range from + * a given memory region defined as the pool range. + * + * Copyright (C) 2007 Bahadir Balban + */ +#include +#include +#include +#include INC_GLUE(memory.h) +#include +#include + +int address_pool_init(struct address_pool *pool, unsigned long start, unsigned long end) +{ + if ((pool->idpool = id_pool_new_init(__pfn(end - start))) < 0) + return (int)pool->idpool; + pool->start = start; + pool->end = end; + return 0; +} + +void *address_new(struct address_pool *pool, int npages) +{ + unsigned int pfn; + + if ((int)(pfn = ids_new_contiguous(pool->idpool, npages)) < 0) + return 0; + + return (void *)__pfn_to_addr(pfn) + pool->start; +} + +int address_del(struct address_pool *pool, void *addr, int npages) +{ + unsigned long pfn = __pfn(page_align(addr) - pool->start); + + if (ids_del_contiguous(pool->idpool, pfn, npages) < 0) { + printf("%s: Invalid address range returned to " + "virtual address pool.\n", __FUNCTION__); + return -1; + } + return 0; +} + diff --git a/tasks/mm0/src/lib/idpool.c b/tasks/mm0/src/lib/idpool.c index f10d4e4..9fc0d98 100644 --- a/tasks/mm0/src/lib/idpool.c +++ b/tasks/mm0/src/lib/idpool.c @@ -7,12 +7,15 @@ #include #include INC_GLUE(memory.h) #include +#include struct id_pool *id_pool_new_init(int totalbits) { int nwords = BITWISE_GETWORD(totalbits); struct id_pool *new = kzalloc((nwords * SZ_WORD) + sizeof(struct id_pool)); + if (!new) + return PTR_ERR(-ENOMEM); new->nwords = nwords; return new; } diff --git a/tasks/mm0/src/lib/vaddr.c b/tasks/mm0/src/lib/vaddr.c deleted file mode 100644 index 8a847a7..0000000 --- a/tasks/mm0/src/lib/vaddr.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * This module allocates an unused virtual address range for shm segments. - * - * Copyright (C) 2007 Bahadir Balban - */ -#include -#include -#include -#include INC_GLUE(memory.h) -#include -#include - -void vaddr_pool_init(struct id_pool *pool, unsigned long start, unsigned long end) -{ - pool = id_pool_new_init(__pfn(end - start)); -} - -void *vaddr_new(struct id_pool *pool, int npages) -{ - unsigned int shm_vpfn; - - if ((int)(shm_vpfn = ids_new_contiguous(pool, npages)) < 0) - return 0; - - return (void *)__pfn_to_addr(shm_vpfn + SHM_AREA_START); -} - -int vaddr_del(struct id_pool *pool, void *vaddr, int npages) -{ - unsigned long idpfn = __pfn(page_align(vaddr) - SHM_AREA_START); - - if (ids_del_contiguous(pool, idpfn, npages) < 0) { - printf("%s: Invalid address range returned to " - "virtual address pool.\n", __FUNCTION__); - return -1; - } - return 0; -} - diff --git a/tasks/mm0/src/mmap.c b/tasks/mm0/src/mmap.c index 74a063f..5f56ce5 100644 --- a/tasks/mm0/src/mmap.c +++ b/tasks/mm0/src/mmap.c @@ -361,6 +361,8 @@ pgtable_unmap: * - If refcount is zero (they could be shared!), either add pages to some page * cache, or simpler the better, free the actual pages back to the page allocator. * - l4_unmap() the corresponding virtual region from the page tables. + * + * -- These are all done -- */ #endif return 0; diff --git a/tasks/mm0/src/shm.c b/tasks/mm0/src/shm.c index 4ea1007..951260c 100644 --- a/tasks/mm0/src/shm.c +++ b/tasks/mm0/src/shm.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include @@ -33,7 +33,7 @@ static struct list_head shm_desc_list; static struct id_pool *shm_ids; /* Globally disjoint shm virtual address pool */ -static struct id_pool *shm_vaddr_pool; +static struct address_pool shm_vaddr_pool; void shm_init() { @@ -43,7 +43,7 @@ void shm_init() shm_ids = id_pool_new_init(SHM_AREA_MAX); /* Initialise the global shm virtual address pool */ - vaddr_pool_init(shm_vaddr_pool, SHM_AREA_START, SHM_AREA_END); + address_pool_init(&shm_vaddr_pool, SHM_AREA_START, SHM_AREA_END); } /* @@ -74,7 +74,7 @@ static int do_shmat(struct shm_descriptor *shm, void *shm_addr, int shmflg, if (shm->shm_addr) shm_addr = shm->shm_addr; else - shm_addr = vaddr_new(shm_vaddr_pool, __pfn(shm->size)); + shm_addr = address_new(&shm_vaddr_pool, __pfn(shm->size)); BUG_ON(!is_page_aligned(shm_addr)); diff --git a/tasks/mm0/src/task.c b/tasks/mm0/src/task.c index 8256f04..8271c82 100644 --- a/tasks/mm0/src/task.c +++ b/tasks/mm0/src/task.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include @@ -22,6 +22,7 @@ #include #include #include +#include struct tcb_head { struct list_head list; @@ -63,8 +64,8 @@ struct tcb *create_init_tcb(struct tcb_head *tcbs) task->spid = TASK_ID_INVALID; task->swap_file = kzalloc(sizeof(struct vm_file)); task->swap_file->pager = &swap_pager; - vaddr_pool_init(task->swap_file_offset_pool, 0, - __pfn(TASK_SWAPFILE_MAXSIZE)); + address_pool_init(&task->swap_file_offset_pool, 0, + __pfn(TASK_SWAPFILE_MAXSIZE)); INIT_LIST_HEAD(&task->swap_file->page_cache_list); INIT_LIST_HEAD(&task->list); INIT_LIST_HEAD(&task->vm_area_list); @@ -119,26 +120,37 @@ int start_boot_tasks(struct initdata *initdata, struct tcb_head *tcbs) file->pager = &boot_file_pager; list_add(&file->list, &initdata->boot_file_list); - /* - * Setup task's regions so that they are taken into account - * during page faults. - */ - task->stack_start = USER_AREA_END - PAGE_SIZE * 4; - - /* Next address after 8 spaces, and 8-byte alignment */ - task->stack_end = align(USER_AREA_END - 8, 8) + sizeof(int); - - /* No argument space, but 8 bytes for utcb address environment */ - task->env_start = task->stack_end; + /* Prepare environment boundaries. Posix minimum is 4Kb */ task->env_end = USER_AREA_END; + task->env_start = task->env_end - PAGE_SIZE; task->args_start = task->env_start; task->args_end = task->env_start; + /* + * Prepare the task environment file and data. + * Currently it only has the utcb address. The env pager + * when faulted, simply copies the task env data to the + * allocated page. + */ + if (task_prepare_env_file(task) < 0) { + printf("Could not create environment file.\n"); + goto error; + } + task->env_data = &task->utcb_address; + task->env_size = sizeof(task->utcb_address); + + /* + * Task stack starts right after the environment, + * and is of 4 page size. + */ + task->stack_end = task->env_start; + task->stack_start = task->stack_end - PAGE_SIZE * 4; + /* Only text start is valid */ task->text_start = USER_AREA_START; /* Set up task's registers */ - sp = align(task->stack_end - 1, sizeof(int)); + sp = align(task->stack_end - 1, 8); pc = task->text_start; /* mmap each task's physical image to task's address space. */ @@ -149,9 +161,19 @@ int start_boot_tasks(struct initdata *initdata, struct tcb_head *tcbs) goto error; } + /* mmap each task's environment from its env file. */ + if ((err = do_mmap(task->env_file, 0, task, task->env_start, + VM_READ | VM_WRITE, + __pfn(task->env_end - task->env_start)) < 0)) { + printf("do_mmap: Mapping environment failed with %d.\n", + err); + goto error; + } + /* mmap each task's stack as 4-page anonymous memory. */ if ((err = do_mmap(0, 0, task, task->stack_start, - VM_READ | VM_WRITE | VMA_ANON, 4) < 0)) { + VM_READ | VM_WRITE | VMA_ANON, + __pfn(task->stack_end - task->stack_start)) < 0)) { printf("do_mmap: Mapping stack failed with %d.\n", err); goto error; } diff --git a/tasks/mm0/src/utcb.c b/tasks/mm0/src/utcb.c new file mode 100644 index 0000000..e70a3ad --- /dev/null +++ b/tasks/mm0/src/utcb.c @@ -0,0 +1,32 @@ +/* + * Utcb address allocation for user tasks. + * + * Copyright (C) 2008 Bahadir Balban + */ + +#include +#include +#include +#include +#include INC_GLUE(memlayout.h) + +static struct address_pool utcb_vaddr_pool; + +int utcb_pool_init() +{ + int err; + if ((err = address_pool_init(&utcb_vaddr_pool, + UTCB_AREA_START, + UTCB_AREA_END)) < 0) { + printf("UTCB address pool initialisation failed: %d\n", err); + return err; + } + return 0; +} + +void *utcb_vaddr_new(void) +{ + return address_new(&utcb_vaddr_pool, 1); +} + + diff --git a/tasks/test0/include/linker.lds b/tasks/test0/include/linker.lds index 163e367..d27b00d 100644 --- a/tasks/test0/include/linker.lds +++ b/tasks/test0/include/linker.lds @@ -14,7 +14,7 @@ */ /* USER_AREA_START, see memlayout.h */ virtual_base = 0x10000000; -__stack = 0x20000000; +__stack = (0x20000000 - 0x1000 - 8); /* First page before the env/args */ INCLUDE "include/physical_base.lds" /* physical_base = 0x228000; */