mirror of
https://github.com/drasko/codezero.git
synced 2026-01-12 02:43:15 +01: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. */
|
||||
#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)
|
||||
|
||||
@@ -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 { \
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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; */
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
* Copyright (C) 2007 Bahadir Balban
|
||||
*/
|
||||
#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_map_t __l4_map = 0;
|
||||
@@ -22,22 +25,32 @@ struct kip *kip;
|
||||
|
||||
/* UTCB address of this task. */
|
||||
struct utcb *utcb;
|
||||
#include <stdio.h>
|
||||
|
||||
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/syslib.h>
|
||||
#include <l4lib/ipcdefs.h>
|
||||
|
||||
#define PTR_ERR(x) ((void *)(x))
|
||||
#define IS_ERR(x) (((int)(x)) < 0)
|
||||
#include <l4/macros.h>
|
||||
|
||||
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>
|
||||
|
||||
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__ */
|
||||
|
||||
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 <l4lib/types.h>
|
||||
#include <l4lib/utcb.h>
|
||||
#include <lib/addr.h>
|
||||
|
||||
#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);
|
||||
|
||||
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
|
||||
* 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());
|
||||
|
||||
|
||||
@@ -340,5 +340,3 @@ int sys_lseek(l4id_t sender, int fd, off_t offset, int whence)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -11,22 +11,31 @@
|
||||
#include <kmalloc/kmalloc.h>
|
||||
#include <l4lib/arch/syscalls.h>
|
||||
#include <l4lib/arch/syslib.h>
|
||||
#include <l4lib/utcb.h>
|
||||
#include <task.h>
|
||||
#include <shm.h>
|
||||
#include <file.h>
|
||||
#include <init.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 *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 */
|
||||
|
||||
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 INC_GLUE(memory.h)
|
||||
#include <stdio.h>
|
||||
#include <l4/api/errno.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
* 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;
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <l4lib/arch/syscalls.h>
|
||||
#include <l4lib/arch/syslib.h>
|
||||
#include <lib/idpool.h>
|
||||
#include <lib/vaddr.h>
|
||||
#include <lib/addr.h>
|
||||
#include <lib/spinlock.h>
|
||||
#include <l4/api/errno.h>
|
||||
#include <l4/lib/list.h>
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include <l4lib/arch/syscalls.h>
|
||||
#include <l4lib/arch/syslib.h>
|
||||
#include <l4lib/ipcdefs.h>
|
||||
#include <lib/vaddr.h>
|
||||
#include <lib/addr.h>
|
||||
#include <task.h>
|
||||
#include <kdata.h>
|
||||
#include <kmalloc/kmalloc.h>
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <memory.h>
|
||||
#include <file.h>
|
||||
#include <utcb.h>
|
||||
#include <env.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 */
|
||||
virtual_base = 0x10000000;
|
||||
__stack = 0x20000000;
|
||||
__stack = (0x20000000 - 0x1000 - 8); /* First page before the env/args */
|
||||
INCLUDE "include/physical_base.lds"
|
||||
|
||||
/* physical_base = 0x228000; */
|
||||
|
||||
Reference in New Issue
Block a user