Revised task initialisation, revising mmap yet.

This commit is contained in:
Bahadir Balban
2008-03-06 20:55:46 +00:00
parent 5681f3d1cb
commit 783904574d
12 changed files with 589 additions and 308 deletions

View File

@@ -16,57 +16,23 @@
#include <l4lib/arch/utcb.h>
#include <l4lib/ipcdefs.h>
#include <lib/addr.h>
#include <task.h>
#include <kdata.h>
#include <kmalloc/kmalloc.h>
#include <kdata.h>
#include <string.h>
#include <vm_area.h>
#include <memory.h>
#include <file.h>
#include <utcb.h>
#include <proc.h>
#include <task.h>
struct tcb_head {
struct list_head list;
int total; /* Total threads */
} tcb_head;
struct tcb *find_task(int tid)
{
struct tcb *t;
list_for_each_entry(t, &tcb_head.list, list)
if (t->tid == tid)
return t;
return 0;
}
struct tcb *tcb_alloc_init(void)
{
struct tcb *task;
if (!(task = kzalloc(sizeof(struct tcb))))
return PTR_ERR(-ENOMEM);
/* Ids will be acquired from the kernel */
task->tid = TASK_ID_INVALID;
task->spid = TASK_ID_INVALID;
/* Initialise its lists */
INIT_LIST_HEAD(&task->list);
INIT_LIST_HEAD(&task->vm_area_list);
return task;
}
#if 0
int start_boot_tasks(struct initdata *initdata, struct tcb_head *tcbs)
{
int err;
struct svc_image *img;
unsigned int sp, pc;
struct tcb *task;
struct task_ids ids;
struct bootdesc *bd;
struct vm_object *vm_obj;
bd = initdata->bootdesc;
@@ -104,14 +70,6 @@ int start_boot_tasks(struct initdata *initdata, struct tcb_head *tcbs)
/* Allocate a utcb virtual address */
task->utcb_address = (unsigned long)utcb_vaddr_new();
/* Allocate the first vm_object we want to map */
vm_obj = vm_obj_alloc_init();
vm_obj->priv.img = img;
file->length = img->phys_end - img->phys_start;
file->pager = &boot_file_pager;
list_add(&file->list, &initdata->boot_file_list);
/* Prepare environment boundaries. Posix minimum is 4Kb */
task->env_end = USER_AREA_END;
task->env_start = task->env_end - PAGE_SIZE;
@@ -199,7 +157,191 @@ int start_boot_tasks(struct initdata *initdata, struct tcb_head *tcbs)
error:
BUG();
}
#endif
struct tcb_head {
struct list_head list;
int total; /* Total threads */
} tcb_head;
struct tcb *find_task(int tid)
{
struct tcb *t;
list_for_each_entry(t, &tcb_head.list, list)
if (t->tid == tid)
return t;
return 0;
}
struct tcb *tcb_alloc_init(void)
{
struct tcb *task;
if (!(task = kzalloc(sizeof(struct tcb))))
return PTR_ERR(-ENOMEM);
/* Ids will be acquired from the kernel */
task->tid = TASK_ID_INVALID;
task->spid = TASK_ID_INVALID;
/* Initialise its lists */
INIT_LIST_HEAD(&task->list);
INIT_LIST_HEAD(&task->vm_area_list);
return task;
}
/*
* Creates a process environment, mmaps the given file along
* with any other necessary segment, and executes it as a task.
*/
int start_boot_task(struct vm_file *file, struct task_ids *ids)
{
/* Create the thread structures and address space */
printf("Creating new thread.\n");
if ((err = l4_thread_control(THREAD_CREATE, &ids)) < 0) {
printf("l4_thread_control failed with %d.\n", err);
goto error;
}
/* Create a task and use given space and thread ids. */
printf("New task with id: %d, space id: %d\n", ids->tid, ids->spid);
task = tcb_alloc_init(tcbs);
task->tid = ids->tid;
task->spid = ids->spid;
/* Allocate a utcb virtual address */
task->utcb_address = (unsigned long)utcb_vaddr_new();
/* Prepare environment boundaries. */
task->env_end = USER_AREA_END;
task->env_start = task->env_end - DEFAULT_ENV_SIZE;
task->args_end = task->env_start;
task->args_start = task->env_start;
/* Task stack starts right after the environment. TODO: Fix this. */
task->stack_end = task->env_start;
task->stack_start = task->stack_end - DEFAULT_STACK_SIZE;
/* Currently RO text and RW data are one region */
task->data_start = USER_AREA_START;
task->data_end = USER_AREA_START + file->length;
task->text_start = task->data_start;
task->text_end = task->data_end;
/* Set up task's registers */
sp = align(task->stack_end - 1, 8);
pc = task->text_start;
/* Set up the task's thread details, (pc, sp, pager etc.) */
if ((err = l4_exchange_registers(pc, sp, self_tid(), task->tid) < 0)) {
printf("l4_exchange_registers failed with %d.\n", err);
goto error;
}
/*
* mmap each task's physical image to task's address space.
* TODO: Map data and text separately when available from bootdesc.
*/
if ((err = do_mmap(file, 0, task, task->text_start,
VM_READ | VM_WRITE | VM_EXEC | VMA_PRIVATE,
__pfn(page_align_up(task->text_end)))) < 0) {
printf("do_mmap: failed with %d.\n", err);
goto error;
}
/* mmap each task's environment as anonymous memory. */
if ((err = do_mmap(0, 0, task, task->env_start,
VM_READ | VM_WRITE | VMA_PRIVATE,
__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 anonymous memory. */
if ((err = do_mmap(0, 0, task, task->stack_start,
VM_READ | VM_WRITE | VMA_PRIVATE,
__pfn(task->stack_end - task->stack_start)) < 0)) {
printf("do_mmap: Mapping stack failed with %d.\n", err);
goto error;
}
/* mmap each task's utcb as single page anonymous memory. */
printf("%s: Mapping utcb for new task at: 0x%x\n", __TASKNAME__,
task->utcb_address);
if ((err = do_mmap(0, 0, task, task->utcb_address,
VM_READ | VM_WRITE | VMA_SHARED,
DEFAULT_UTCB_SIZE) < 0)) {
printf("do_mmap: Mapping utcb failed with %d.\n", err);
goto error;
}
/* Add the task to the global task list */
list_add(&task->list, tcb_head->list);
tcb_head->total++;
/* Start the thread */
printf("Starting task with id %d\n", task->tid);
if ((err = l4_thread_control(THREAD_RUN, &ids) < 0)) {
printf("l4_thread_control failed with %d\n", err);
goto error;
}
}
/*
* Reads boot files from init data, determines their task ids if they
* match with particular servers, and starts the tasks.
*/
int start_boot_tasks(struct initdata *initdata)
{
struct vm_file *file;
struct list_head *n;
struct svg_image *img;
struct task_ids ids;
int total = 0;
do {
file = 0;
list_for_each_entry_safe(file, n, &initdata->boot_file_list,
list) {
list_del(&file->list);
break;
}
if (file) {
BUG_ON(file->type != VM_FILE_BOOTFILE);
img = file->priv_data;
if (!strcmp(img->name, __PAGERNAME__))
continue;
/* Set up task ids */
if (!strcmp(img->name, __VFSNAME__)) {
ids.tid = VFS_TID;
ids.spid = VFS_TID;
} else {
ids.tid = -1;
ids.spid = -1;
}
} else
break;
/* Add the file to global vm lists */
list_add(&file->list, &vm_file_list);
list_add(&file->vm_obj->list, &vm_object_list);
/* Start the file as a task */
start_boot_task(file, &ids);
total++;
} while (1);
if (!total) {
printf("%s: Could not start any tasks.\n", __TASKNAME__);
BUG();
}
return 0;
}
void init_pm(struct initdata *initdata)
{