Files
codezero/tasks/mm0/src/utcb.c
Bahadir Balban 35d2d275b6 Multiple above-minor updates.
- fixed is_err(x), was evaluating x twice, resulting in calling a
function x twice.

- Divided task initialisation into multiple parts.
- MM0 now creates a tcb for itself and maintains memory regions of its own.
- MM0's tcb is used for mmapping other tasks' regions. MM0 mmaps and prefaults
  those regions, instead of the typical mmap() and fault approach used by
  non-pager tasks.
  For example there's an internal shmget_shmat() path to map in other tasks'
  shm utcbs. Those mappings are then prefaulted into mm0's address space using
  the default fault handling path.

- FS0 now reads task data into its utcb from mm0 via a syscall.
  FS0 shmat()s to utcbs of other tasks, e.g. mm0 and test0.

  FS0 then crashes, that is to be fixed and where this commit is left last.
2008-03-24 00:34:14 +00:00

114 lines
2.7 KiB
C

/*
* 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 <l4lib/arch/syscalls.h>
#include <l4lib/arch/syslib.h>
#include <task.h>
#include <vm_area.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);
}
/*
* Sends utcb address information to requester task, allocates
* an address if it doesn't exist and the requester is asking
* for its own. The requester then uses this address as a shm key and
* maps its own utcb via shmget/shmat.
*/
int task_send_utcb_address(l4id_t sender, l4id_t taskid)
{
struct tcb *task = find_task(taskid);
/* Is the task asking for its own utcb address */
if (sender == taskid) {
/*
* It hasn't got one allocated. We allocate one here,
* but only because the requester is requesting for its
* own utcb.
*/
BUG_ON(!task->utcb);
/* Return it to requester */
return l4_ipc_return((int)task->utcb);
/* A task is asking for someone else's utcb */
} else {
/* Only vfs is allowed to do so yet, because its a server */
if (sender == VFS_TID) {
/*
* Return utcb address to requester. Note if there's
* none allocated so far, requester gets 0. We don't
* allocate one here.
*/
return l4_ipc_return((int)task->utcb);
}
}
return 0;
}
#if 0
To be ditched
/*
* Triggered during a sys_shmat() by a client task when mapping its utcb.
* This prefaults the utcb and maps it in to mm0 so that it can freely
* access it anytime later.
*/
int utcb_prefault(struct tcb *task, unsigned int vmflags)
{
int err;
struct page *pg;
/* First map in the page to task with given flags, e.g. read/write */
if ((err = prefault_page(task, task->utcb_address, vmflags)) < 0) {
printf("%s: Failed: %d\n", __FUNCTION__, err);
return err;
}
/*
* Get the topmost page. Since we did both a VM_READ and VM_WRITE
* prefault, this gets a writeable instead of a read-only page.
*/
pg = task_virt_to_page(task, task->utcb_address);
if (!pg || IS_ERR(pg)) {
printf("%s: Cannot retrieve task %d's utcb page.\n",
__FUNCTION__, task->tid);
BUG();
}
/* Map it in to self */
l4_map((void *)page_to_phys(pg), (void *)task->utcb_address, 1,
MAP_USR_RW_FLAGS, self_tid());
/* Flag that says this task's utcb is mapped to mm0 as r/w */
task->utcb_mapped = 1;
return 0;
}
#endif