mirror of
https://github.com/drasko/codezero.git
synced 2026-05-04 17:41:30 +02:00
Modified task initialisation so that stack now comes beneath the environment
Environment is backed by a special per-task file maintained by mm0 for each task. This file is filled in by the env pager, by simple copying of env data into the faulty page upon a fault. UTCB and all anon regions (stack) could use the same scheme. Fixed IS_ERR(x) to accept negative values that are above -1000 for errors. This protects against false positives for pointers such as 0xE0000000. modified: include/l4/generic/scheduler.h modified: include/l4/macros.h modified: src/arch/arm/exception.c modified: tasks/fs0/include/linker.lds modified: tasks/libl4/src/init.c modified: tasks/libposix/shm.c new file: tasks/mm0/include/env.h modified: tasks/mm0/include/file.h new file: tasks/mm0/include/lib/addr.h deleted: tasks/mm0/include/lib/vaddr.h modified: tasks/mm0/include/task.h new file: tasks/mm0/include/utcb.h new file: tasks/mm0/src/env.c modified: tasks/mm0/src/fault.c modified: tasks/mm0/src/file.c modified: tasks/mm0/src/init.c new file: tasks/mm0/src/lib/addr.c modified: tasks/mm0/src/lib/idpool.c deleted: tasks/mm0/src/lib/vaddr.c modified: tasks/mm0/src/mmap.c modified: tasks/mm0/src/shm.c modified: tasks/mm0/src/task.c new file: tasks/mm0/src/utcb.c modified: tasks/test0/include/linker.lds
This commit is contained in:
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
/* Ticks per second, try ticks = 1000 + timeslice = 1 for regressed preemption test. */
|
/* Ticks per second, try ticks = 1000 + timeslice = 1 for regressed preemption test. */
|
||||||
#define HZ 10
|
#define HZ 10
|
||||||
#define TASK_TIMESLICE_DEFAULT 100
|
#define TASK_TIMESLICE_DEFAULT 500
|
||||||
/* #define TASK_TIMESLICE_DEFAULT (HZ/100)*/
|
/* #define TASK_TIMESLICE_DEFAULT (HZ/100)*/
|
||||||
|
|
||||||
static inline struct ktcb *current_task(void)
|
static inline struct ktcb *current_task(void)
|
||||||
|
|||||||
@@ -77,7 +77,8 @@
|
|||||||
|
|
||||||
/* Functions who may either return a pointer or an error code can use these: */
|
/* Functions who may either return a pointer or an error code can use these: */
|
||||||
#define PTR_ERR(x) ((void *)(x))
|
#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? */
|
/* TEST: Is this type of printk well tested? */
|
||||||
#define BUG() {do { \
|
#define BUG() {do { \
|
||||||
|
|||||||
@@ -82,22 +82,22 @@ int check_aborts(u32 faulted_pc, u32 fsr, u32 far)
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (is_prefetch_abort(fsr)) {
|
if (is_prefetch_abort(fsr)) {
|
||||||
// dprintk("Prefetch abort @ ", faulted_pc);
|
dprintk("Prefetch abort @ ", faulted_pc);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (fsr & ARM_FSR_MASK) {
|
switch (fsr & ARM_FSR_MASK) {
|
||||||
/* Aborts that are expected on page faults: */
|
/* Aborts that are expected on page faults: */
|
||||||
case DABT_PERM_PAGE:
|
case DABT_PERM_PAGE:
|
||||||
// dprintk("Page permission fault @ ", far);
|
dprintk("Page permission fault @ ", far);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
case DABT_XLATE_PAGE:
|
case DABT_XLATE_PAGE:
|
||||||
// dprintk("Page translation fault @ ", far);
|
dprintk("Page translation fault @ ", far);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
case DABT_XLATE_SECT:
|
case DABT_XLATE_SECT:
|
||||||
// dprintk("Section translation fault @ ", far);
|
dprintk("Section translation fault @ ", far);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
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)
|
void data_abort_handler(u32 faulted_pc, u32 fsr, u32 far)
|
||||||
{
|
{
|
||||||
set_abort_type(fsr, ARM_DABT);
|
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) {
|
if (check_aborts(faulted_pc, fsr, far) < 0) {
|
||||||
printascii("This abort can't be handled by any pager.\n");
|
printascii("This abort can't be handled by any pager.\n");
|
||||||
goto error;
|
goto error;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
*/
|
*/
|
||||||
/* USER_AREA_START, see memlayout.h */
|
/* USER_AREA_START, see memlayout.h */
|
||||||
virtual_base = 0x10000000;
|
virtual_base = 0x10000000;
|
||||||
__stack = 0x20000000;
|
__stack = (0x20000000 - 0x1000 - 8); /* First page before env/args page */
|
||||||
INCLUDE "include/physical_base.lds"
|
INCLUDE "include/physical_base.lds"
|
||||||
|
|
||||||
/* physical_base = 0x228000; */
|
/* physical_base = 0x228000; */
|
||||||
|
|||||||
@@ -4,6 +4,9 @@
|
|||||||
* Copyright (C) 2007 Bahadir Balban
|
* Copyright (C) 2007 Bahadir Balban
|
||||||
*/
|
*/
|
||||||
#include <l4lib/kip.h>
|
#include <l4lib/kip.h>
|
||||||
|
#include <l4lib/arch/syslib.h>
|
||||||
|
#include <l4/macros.h>
|
||||||
|
#include INC_GLUE(memlayout.h)
|
||||||
|
|
||||||
__l4_ipc_t __l4_ipc = 0;
|
__l4_ipc_t __l4_ipc = 0;
|
||||||
__l4_map_t __l4_map = 0;
|
__l4_map_t __l4_map = 0;
|
||||||
@@ -22,22 +25,32 @@ struct kip *kip;
|
|||||||
|
|
||||||
/* UTCB address of this task. */
|
/* UTCB address of this task. */
|
||||||
struct utcb *utcb;
|
struct utcb *utcb;
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
void __l4_init(void)
|
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,9 +11,7 @@
|
|||||||
#include <l4lib/arch/syscalls.h>
|
#include <l4lib/arch/syscalls.h>
|
||||||
#include <l4lib/arch/syslib.h>
|
#include <l4lib/arch/syslib.h>
|
||||||
#include <l4lib/ipcdefs.h>
|
#include <l4lib/ipcdefs.h>
|
||||||
|
#include <l4/macros.h>
|
||||||
#define PTR_ERR(x) ((void *)(x))
|
|
||||||
#define IS_ERR(x) (((int)(x)) < 0)
|
|
||||||
|
|
||||||
int l4_shmget(l4id_t key, int size, int shmflg)
|
int l4_shmget(l4id_t key, int size, int shmflg)
|
||||||
{
|
{
|
||||||
|
|||||||
6
tasks/mm0/include/env.h
Normal file
6
tasks/mm0/include/env.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef __MM0_ENV__
|
||||||
|
#define __MM0_ENV__
|
||||||
|
|
||||||
|
int task_prepare_env_file(struct tcb *t);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <posix/sys/types.h>
|
#include <posix/sys/types.h>
|
||||||
|
|
||||||
void vmfile_init(void);
|
void vmfile_init(void);
|
||||||
|
|
||||||
struct vm_file *vmfile_alloc_init(void);
|
struct vm_file *vmfile_alloc_init(void);
|
||||||
int vfs_receive_sys_open(l4id_t sender, l4id_t opener, int fd,
|
int vfs_receive_sys_open(l4id_t sender, l4id_t opener, int fd,
|
||||||
unsigned long vnum, unsigned long size);
|
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_write(l4id_t sender, int fd, void *buf, int count);
|
||||||
int sys_lseek(l4id_t sender, int fd, off_t offset, int whence);
|
int sys_lseek(l4id_t sender, int fd, off_t offset, int whence);
|
||||||
|
|
||||||
|
extern struct list_head vm_file_list;
|
||||||
#endif /* __MM0_FILE_H__ */
|
#endif /* __MM0_FILE_H__ */
|
||||||
|
|||||||
23
tasks/mm0/include/lib/addr.h
Normal file
23
tasks/mm0/include/lib/addr.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Address allocation pool
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 Bahadir Balban
|
||||||
|
*/
|
||||||
|
#ifndef __ADDR_H__
|
||||||
|
#define __ADDR_H__
|
||||||
|
|
||||||
|
#include <lib/idpool.h>
|
||||||
|
|
||||||
|
/* 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__ */
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
/*
|
|
||||||
* Virtual address allocation pool (for shm)
|
|
||||||
*
|
|
||||||
* Copyright (C) 2007 Bahadir Balban
|
|
||||||
*/
|
|
||||||
#ifndef __VADDR_H__
|
|
||||||
#define __VADDR_H__
|
|
||||||
|
|
||||||
#include <lib/idpool.h>
|
|
||||||
|
|
||||||
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__ */
|
|
||||||
|
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
#include <l4/lib/list.h>
|
#include <l4/lib/list.h>
|
||||||
#include <l4lib/types.h>
|
#include <l4lib/types.h>
|
||||||
#include <l4lib/utcb.h>
|
#include <l4lib/utcb.h>
|
||||||
|
#include <lib/addr.h>
|
||||||
|
|
||||||
#define __TASKNAME__ __PAGERNAME__
|
#define __TASKNAME__ __PAGERNAME__
|
||||||
|
|
||||||
@@ -43,7 +44,7 @@ struct tcb {
|
|||||||
/* Related task ids */
|
/* Related task ids */
|
||||||
unsigned int pagerid; /* Task's pager */
|
unsigned int pagerid; /* Task's pager */
|
||||||
|
|
||||||
/* Program segment marks */
|
/* Program segment marks, ends exclusive as usual */
|
||||||
unsigned long text_start;
|
unsigned long text_start;
|
||||||
unsigned long text_end;
|
unsigned long text_end;
|
||||||
unsigned long data_start;
|
unsigned long data_start;
|
||||||
@@ -51,9 +52,9 @@ struct tcb {
|
|||||||
unsigned long bss_start;
|
unsigned long bss_start;
|
||||||
unsigned long bss_end;
|
unsigned long bss_end;
|
||||||
unsigned long stack_start;
|
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_start;
|
||||||
unsigned long heap_end; /* Exclusive of last currently mapped page */
|
unsigned long heap_end;
|
||||||
unsigned long env_start;
|
unsigned long env_start;
|
||||||
unsigned long env_end;
|
unsigned long env_end;
|
||||||
unsigned long args_start;
|
unsigned long args_start;
|
||||||
@@ -62,17 +63,24 @@ struct tcb {
|
|||||||
/* UTCB address */
|
/* UTCB address */
|
||||||
unsigned long 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 */
|
/* Virtual memory areas */
|
||||||
struct list_head vm_area_list;
|
struct list_head vm_area_list;
|
||||||
|
|
||||||
/* Per-task swap file for now */
|
|
||||||
struct vm_file *swap_file;
|
|
||||||
|
|
||||||
/* File descriptors for this task */
|
/* File descriptors for this task */
|
||||||
struct file_descriptor fd[TASK_OFILES_MAX];
|
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 */
|
/* 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);
|
struct tcb *find_task(int tid);
|
||||||
|
|||||||
7
tasks/mm0/include/utcb.h
Normal file
7
tasks/mm0/include/utcb.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#ifndef __MM0_UTCB_H__
|
||||||
|
#define __MM0_UTCB_H__
|
||||||
|
|
||||||
|
void *utcb_vaddr_new(void);
|
||||||
|
int utcb_pool_init(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
80
tasks/mm0/src/env.c
Normal file
80
tasks/mm0/src/env.c
Normal file
@@ -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 <l4/lib/list.h>
|
||||||
|
#include <vm_area.h>
|
||||||
|
#include <kmalloc/kmalloc.h>
|
||||||
|
#include <task.h>
|
||||||
|
#include <l4/api/kip.h>
|
||||||
|
#include <l4/api/errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <file.h>
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -108,8 +108,10 @@ int do_file_page(struct fault_data *fault)
|
|||||||
* Read the page. (Simply read into the faulty area that's
|
* Read the page. (Simply read into the faulty area that's
|
||||||
* now mapped using a newly allocated page.)
|
* now mapped using a newly allocated page.)
|
||||||
*/
|
*/
|
||||||
fault->vma->owner->pager->ops.read_page(fault->vma->owner,
|
if (fault->vma->owner->pager->ops.read_page(fault->vma->owner,
|
||||||
f_offset, vaddr);
|
f_offset,
|
||||||
|
vaddr) < 0)
|
||||||
|
BUG();
|
||||||
|
|
||||||
/* Remove temporary mapping */
|
/* Remove temporary mapping */
|
||||||
l4_unmap(vaddr, 1, self_tid());
|
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
|
* Read the page. (Simply read into the faulty area that's
|
||||||
* now mapped using a newly allocated page.)
|
* now mapped using a newly allocated page.)
|
||||||
*/
|
*/
|
||||||
fault->vma->owner->pager->ops.read_page(fault->vma->owner,
|
if (fault->vma->owner->pager->ops.read_page(fault->vma->owner,
|
||||||
f_offset, vaddr);
|
f_offset,
|
||||||
|
vaddr) < 0)
|
||||||
|
BUG();
|
||||||
|
|
||||||
/* Unmap from self */
|
/* Unmap from self */
|
||||||
l4_unmap(vaddr, 1, self_tid());
|
l4_unmap(vaddr, 1, self_tid());
|
||||||
@@ -252,26 +256,6 @@ int do_file_page(struct fault_data *fault)
|
|||||||
return 0;
|
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.
|
* Handles any page allocation or file ownership change for anonymous pages.
|
||||||
* For read accesses initialises a wired-in zero page and for write accesses
|
* 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
|
/* For non-existant pages just map the zero page, unless it is the
|
||||||
* beginning of stack which requires environment and argument data. */
|
* 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
|
* Zero page is a special wired-in page that is mapped
|
||||||
* many times in many tasks. Just update its count field.
|
* 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 */
|
/* 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);
|
paddr = alloc_page(1);
|
||||||
vaddr = phys_to_virt(paddr);
|
vaddr = phys_to_virt(paddr);
|
||||||
page = phys_to_page(paddr);
|
page = phys_to_page(paddr);
|
||||||
@@ -333,10 +317,6 @@ int do_anon_page(struct fault_data *fault)
|
|||||||
/* Clear the page */
|
/* Clear the page */
|
||||||
memset((void *)vaddr, 0, PAGE_SIZE);
|
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 */
|
/* Remove temporary mapping */
|
||||||
l4_unmap((void *)vaddr, 1, self_tid());
|
l4_unmap((void *)vaddr, 1, self_tid());
|
||||||
|
|
||||||
|
|||||||
@@ -340,5 +340,3 @@ int sys_lseek(l4id_t sender, int fd, off_t offset, int whence)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -11,22 +11,31 @@
|
|||||||
#include <kmalloc/kmalloc.h>
|
#include <kmalloc/kmalloc.h>
|
||||||
#include <l4lib/arch/syscalls.h>
|
#include <l4lib/arch/syscalls.h>
|
||||||
#include <l4lib/arch/syslib.h>
|
#include <l4lib/arch/syslib.h>
|
||||||
|
#include <l4lib/utcb.h>
|
||||||
#include <task.h>
|
#include <task.h>
|
||||||
#include <shm.h>
|
#include <shm.h>
|
||||||
#include <file.h>
|
#include <file.h>
|
||||||
#include <init.h>
|
#include <init.h>
|
||||||
#include <utcb.h>
|
#include <utcb.h>
|
||||||
|
|
||||||
/* 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 init_utcb(void)
|
||||||
{
|
{
|
||||||
void *utcb_virt, *utcb_page;
|
void *utcb_virt, *utcb_page;
|
||||||
|
|
||||||
/* Allocate and map one for self */
|
/* Allocate and map one for self */
|
||||||
|
if (utcb_pool_init() < 0)
|
||||||
|
printf("UTCB initialisation failed.\n");
|
||||||
utcb_virt = utcb_vaddr_new();
|
utcb_virt = utcb_vaddr_new();
|
||||||
printf("%s: Mapping 0x%x as utcb to self.\n", __TASKNAME__, utcb_virt);
|
printf("%s: Mapping 0x%x as utcb to self.\n", __TASKNAME__, utcb_virt);
|
||||||
utcb_page = alloc_page(1);
|
utcb_page = alloc_page(1);
|
||||||
l4_map(utcb_page, utcb_virt, 1, MAP_USR_RW_FLAGS, self_tid());
|
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)
|
void init_mm(struct initdata *initdata)
|
||||||
@@ -43,9 +52,6 @@ void init_mm(struct initdata *initdata)
|
|||||||
init_devzero();
|
init_devzero();
|
||||||
printf("%s: Initialised devzero.\n", __TASKNAME__);
|
printf("%s: Initialised devzero.\n", __TASKNAME__);
|
||||||
|
|
||||||
init_utcb();
|
|
||||||
printf("%s: Initialised own utcb.\n", __TASKNAME__);
|
|
||||||
|
|
||||||
/* Initialise the pager's memory allocator */
|
/* Initialise the pager's memory allocator */
|
||||||
kmalloc_init();
|
kmalloc_init();
|
||||||
printf("%s: Initialised kmalloc.\n", __TASKNAME__);
|
printf("%s: Initialised kmalloc.\n", __TASKNAME__);
|
||||||
@@ -53,6 +59,9 @@ void init_mm(struct initdata *initdata)
|
|||||||
shm_init();
|
shm_init();
|
||||||
printf("%s: Initialised shm structures.\n", __TASKNAME__);
|
printf("%s: Initialised shm structures.\n", __TASKNAME__);
|
||||||
|
|
||||||
|
init_utcb();
|
||||||
|
printf("%s: Initialised own utcb.\n", __TASKNAME__);
|
||||||
|
|
||||||
vmfile_init();
|
vmfile_init();
|
||||||
|
|
||||||
/* Give the kernel some memory to use for its allocators */
|
/* Give the kernel some memory to use for its allocators */
|
||||||
|
|||||||
44
tasks/mm0/src/lib/addr.c
Normal file
44
tasks/mm0/src/lib/addr.c
Normal file
@@ -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 <lib/bit.h>
|
||||||
|
#include <l4/macros.h>
|
||||||
|
#include <l4/types.h>
|
||||||
|
#include INC_GLUE(memory.h)
|
||||||
|
#include <lib/addr.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -7,12 +7,15 @@
|
|||||||
#include <kmalloc/kmalloc.h>
|
#include <kmalloc/kmalloc.h>
|
||||||
#include INC_GLUE(memory.h)
|
#include INC_GLUE(memory.h)
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <l4/api/errno.h>
|
||||||
|
|
||||||
struct id_pool *id_pool_new_init(int totalbits)
|
struct id_pool *id_pool_new_init(int totalbits)
|
||||||
{
|
{
|
||||||
int nwords = BITWISE_GETWORD(totalbits);
|
int nwords = BITWISE_GETWORD(totalbits);
|
||||||
struct id_pool *new = kzalloc((nwords * SZ_WORD)
|
struct id_pool *new = kzalloc((nwords * SZ_WORD)
|
||||||
+ sizeof(struct id_pool));
|
+ sizeof(struct id_pool));
|
||||||
|
if (!new)
|
||||||
|
return PTR_ERR(-ENOMEM);
|
||||||
new->nwords = nwords;
|
new->nwords = nwords;
|
||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
* This module allocates an unused virtual address range for shm segments.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2007 Bahadir Balban
|
|
||||||
*/
|
|
||||||
#include <lib/bit.h>
|
|
||||||
#include <l4/macros.h>
|
|
||||||
#include <l4/types.h>
|
|
||||||
#include INC_GLUE(memory.h)
|
|
||||||
#include <lib/vaddr.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -361,6 +361,8 @@ pgtable_unmap:
|
|||||||
* - If refcount is zero (they could be shared!), either add pages to some page
|
* - 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.
|
* cache, or simpler the better, free the actual pages back to the page allocator.
|
||||||
* - l4_unmap() the corresponding virtual region from the page tables.
|
* - l4_unmap() the corresponding virtual region from the page tables.
|
||||||
|
*
|
||||||
|
* -- These are all done --
|
||||||
*/
|
*/
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
#include <l4lib/arch/syscalls.h>
|
#include <l4lib/arch/syscalls.h>
|
||||||
#include <l4lib/arch/syslib.h>
|
#include <l4lib/arch/syslib.h>
|
||||||
#include <lib/idpool.h>
|
#include <lib/idpool.h>
|
||||||
#include <lib/vaddr.h>
|
#include <lib/addr.h>
|
||||||
#include <lib/spinlock.h>
|
#include <lib/spinlock.h>
|
||||||
#include <l4/api/errno.h>
|
#include <l4/api/errno.h>
|
||||||
#include <l4/lib/list.h>
|
#include <l4/lib/list.h>
|
||||||
@@ -33,7 +33,7 @@ static struct list_head shm_desc_list;
|
|||||||
static struct id_pool *shm_ids;
|
static struct id_pool *shm_ids;
|
||||||
|
|
||||||
/* Globally disjoint shm virtual address pool */
|
/* Globally disjoint shm virtual address pool */
|
||||||
static struct id_pool *shm_vaddr_pool;
|
static struct address_pool shm_vaddr_pool;
|
||||||
|
|
||||||
void shm_init()
|
void shm_init()
|
||||||
{
|
{
|
||||||
@@ -43,7 +43,7 @@ void shm_init()
|
|||||||
shm_ids = id_pool_new_init(SHM_AREA_MAX);
|
shm_ids = id_pool_new_init(SHM_AREA_MAX);
|
||||||
|
|
||||||
/* Initialise the global shm virtual address pool */
|
/* 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)
|
if (shm->shm_addr)
|
||||||
shm_addr = shm->shm_addr;
|
shm_addr = shm->shm_addr;
|
||||||
else
|
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));
|
BUG_ON(!is_page_aligned(shm_addr));
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
#include <l4lib/arch/syscalls.h>
|
#include <l4lib/arch/syscalls.h>
|
||||||
#include <l4lib/arch/syslib.h>
|
#include <l4lib/arch/syslib.h>
|
||||||
#include <l4lib/ipcdefs.h>
|
#include <l4lib/ipcdefs.h>
|
||||||
#include <lib/vaddr.h>
|
#include <lib/addr.h>
|
||||||
#include <task.h>
|
#include <task.h>
|
||||||
#include <kdata.h>
|
#include <kdata.h>
|
||||||
#include <kmalloc/kmalloc.h>
|
#include <kmalloc/kmalloc.h>
|
||||||
@@ -22,6 +22,7 @@
|
|||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
#include <file.h>
|
#include <file.h>
|
||||||
#include <utcb.h>
|
#include <utcb.h>
|
||||||
|
#include <env.h>
|
||||||
|
|
||||||
struct tcb_head {
|
struct tcb_head {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
@@ -63,8 +64,8 @@ struct tcb *create_init_tcb(struct tcb_head *tcbs)
|
|||||||
task->spid = TASK_ID_INVALID;
|
task->spid = TASK_ID_INVALID;
|
||||||
task->swap_file = kzalloc(sizeof(struct vm_file));
|
task->swap_file = kzalloc(sizeof(struct vm_file));
|
||||||
task->swap_file->pager = &swap_pager;
|
task->swap_file->pager = &swap_pager;
|
||||||
vaddr_pool_init(task->swap_file_offset_pool, 0,
|
address_pool_init(&task->swap_file_offset_pool, 0,
|
||||||
__pfn(TASK_SWAPFILE_MAXSIZE));
|
__pfn(TASK_SWAPFILE_MAXSIZE));
|
||||||
INIT_LIST_HEAD(&task->swap_file->page_cache_list);
|
INIT_LIST_HEAD(&task->swap_file->page_cache_list);
|
||||||
INIT_LIST_HEAD(&task->list);
|
INIT_LIST_HEAD(&task->list);
|
||||||
INIT_LIST_HEAD(&task->vm_area_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;
|
file->pager = &boot_file_pager;
|
||||||
list_add(&file->list, &initdata->boot_file_list);
|
list_add(&file->list, &initdata->boot_file_list);
|
||||||
|
|
||||||
/*
|
/* Prepare environment boundaries. Posix minimum is 4Kb */
|
||||||
* 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;
|
|
||||||
task->env_end = USER_AREA_END;
|
task->env_end = USER_AREA_END;
|
||||||
|
task->env_start = task->env_end - PAGE_SIZE;
|
||||||
task->args_start = task->env_start;
|
task->args_start = task->env_start;
|
||||||
task->args_end = 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 */
|
/* Only text start is valid */
|
||||||
task->text_start = USER_AREA_START;
|
task->text_start = USER_AREA_START;
|
||||||
|
|
||||||
/* Set up task's registers */
|
/* Set up task's registers */
|
||||||
sp = align(task->stack_end - 1, sizeof(int));
|
sp = align(task->stack_end - 1, 8);
|
||||||
pc = task->text_start;
|
pc = task->text_start;
|
||||||
|
|
||||||
/* mmap each task's physical image to task's address space. */
|
/* 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;
|
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. */
|
/* mmap each task's stack as 4-page anonymous memory. */
|
||||||
if ((err = do_mmap(0, 0, task, task->stack_start,
|
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);
|
printf("do_mmap: Mapping stack failed with %d.\n", err);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|||||||
32
tasks/mm0/src/utcb.c
Normal file
32
tasks/mm0/src/utcb.c
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Utcb address allocation for user tasks.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 Bahadir Balban
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <utcb.h>
|
||||||
|
#include <lib/addr.h>
|
||||||
|
#include <l4/macros.h>
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
*/
|
*/
|
||||||
/* USER_AREA_START, see memlayout.h */
|
/* USER_AREA_START, see memlayout.h */
|
||||||
virtual_base = 0x10000000;
|
virtual_base = 0x10000000;
|
||||||
__stack = 0x20000000;
|
__stack = (0x20000000 - 0x1000 - 8); /* First page before the env/args */
|
||||||
INCLUDE "include/physical_base.lds"
|
INCLUDE "include/physical_base.lds"
|
||||||
|
|
||||||
/* physical_base = 0x228000; */
|
/* physical_base = 0x228000; */
|
||||||
|
|||||||
Reference in New Issue
Block a user