Removed special-case utcb shared page from posix services.

Previously a so-called utcb shared page was used for transfering
data between posix services. This was a special shmat/get/dt case
allocating from its own virtual pool. Now the term utcb is renamed
as a shared page and integrated with the shm* handling routines.

Generic l4 threads will use long-ipc and not this method. Posix
services will continue to communicate on a shared page for now.
	modified:   tasks/libl4/include/l4lib/ipcdefs.h
	modified:   tasks/libl4/src/init.c
	new file:   tasks/libposix/init.c
	modified:   tasks/mm0/include/shm.h
	modified:   tasks/mm0/include/task.h
	deleted:    tasks/mm0/include/utcb.h
	modified:   tasks/mm0/main.c
	modified:   tasks/mm0/src/boot.c
	modified:   tasks/mm0/src/clone.c
	modified:   tasks/mm0/src/execve.c
	modified:   tasks/mm0/src/exit.c
	modified:   tasks/mm0/src/init.c
	modified:   tasks/mm0/src/shm.c
	modified:   tasks/mm0/src/task.c
	deleted:    tasks/mm0/src/utcb.c
	deleted:    tools/l4-qemu
This commit is contained in:
Bahadir Balban
2009-04-22 11:58:58 +03:00
parent 8d82fa5f5e
commit 203f053878
16 changed files with 209 additions and 268 deletions

View File

@@ -19,8 +19,8 @@
/* For ping ponging */
#define L4_IPC_TAG_SYNC 3
/* To obtain utcb address */
#define L4_IPC_TAG_UTCB 4
/* To obtain default shared page address */
#define L4_IPC_TAG_SHPAGE 4
/* XXX: unused */
#define L4_IPC_TAG_GRANT 5

View File

@@ -34,77 +34,6 @@ struct kip *kip;
*/
struct utcb utcb;
/*
* Shared utcb page for this task. Used for passing data among ipc
* parties when message registers are not big enough. Every thread
* has right to own one, and it has an address unique to every
* thread. It must be explicitly mapped by both parties of the ipc
* in order to be useful.
*/
void *utcb_page;
/*
* Obtains a unique address for the task's shared utcb page. Note this
* does *not* map the utcb, just returns the address. This address
* is used as an shm key to map it via shmget()/shmat() later on.
*/
static void *l4_utcb_page(void)
{
void *addr;
int err;
/* We're asking it for ourself. */
write_mr(L4SYS_ARG0, self_tid());
/* Call pager with utcb address request. Check ipc error. */
if ((err = l4_sendrecv(PAGER_TID, PAGER_TID, L4_IPC_TAG_UTCB)) < 0) {
printf("%s: L4 IPC Error: %d.\n", __FUNCTION__, err);
return PTR_ERR(err);
}
/* Check if syscall itself was successful */
if (IS_ERR(addr = (void *)l4_get_retval())) {
printf("%s: Request UTCB Address Error: %d.\n",
__FUNCTION__, (int)addr);
return addr;
}
return addr;
}
/*
* Initialises a non-pager task's shared memory utcb page
* using posix semantics. Used during task initialisation
* and by child tasks after a fork.
*/
int utcb_init(void)
{
int shmid;
void *shmaddr;
/*
* Initialise utcb only if we're not the pager.
* The pager does it differently for itself.
*/
if (self_tid() != PAGER_TID) {
/* Obtain our utcb page address */
utcb_page = l4_utcb_page();
//printf("%s: UTCB Read from mm0 as: 0x%x\n", __FUNCTION__,
// (unsigned long)utcb_page);
/* Use it as a key to create a shared memory region */
BUG_ON((shmid = shmget((key_t)utcb_page,
PAGE_SIZE, IPC_CREAT)) < 0);
/* Attach to the region */
BUG_ON((shmaddr = shmat(shmid, utcb_page, 0)) < 0);
BUG_ON(shmaddr != utcb_page);
}
return 0;
}
void __l4_init(void)
{
@@ -123,7 +52,5 @@ void __l4_init(void)
(__l4_exchange_registers_t)kip->exchange_registers;
__l4_kmem_control = (__l4_kmem_control_t)kip->kmem_control;
__l4_time = (__l4_time_t)kip->time;
utcb_init();
}

79
tasks/libposix/init.c Normal file
View File

@@ -0,0 +1,79 @@
/*
* Shared page initialisation of posix-like tasks.
*
* POSIX tasks currently use a default shared page for communciation.
* This could have been also done by long ipc calls.
*/
/*
* Shared page for this task. Used for passing data among ipc
* parties when message registers are not big enough. Every thread
* has right to own one, and it has an address unique to every
* thread. It must be explicitly mapped by both parties of the ipc
* in order to be useful.
*/
void *shared_page;
/*
* Obtains a unique address for the task's shared page. Note this
* just returns the address. This address is used as an shm key
* to map it via shmget()/shmat() later on.
*/
static void *shared_page_address(void)
{
void *addr;
int err;
/* We're asking it for ourself. */
write_mr(L4SYS_ARG0, self_tid());
/* Call pager with utcb address request. Check ipc error. */
if ((err = l4_sendrecv(PAGER_TID, PAGER_TID,
L4_IPC_TAG_DEFAULT_SHPAGE)) < 0) {
printf("%s: L4 IPC Error: %d.\n", __FUNCTION__, err);
return PTR_ERR(err);
}
/* Check if syscall itself was successful */
if (IS_ERR(addr = (void *)l4_get_retval())) {
printf("%s: Request UTCB Address Error: %d.\n",
__FUNCTION__, (int)addr);
return addr;
}
return addr;
}
/*
* Initialises a non-pager task's default shared memory page
* using posix semantics. Used during task initialisation
* and by child tasks after a fork.
*/
int shared_page_init(void)
{
int shmid;
void *shmaddr;
/*
* Initialise shared page only if we're not the pager.
* The pager does it differently for itself.
*/
BUG_ON(self_tid() == PAGER_TID);
/* Obtain our utcb page address */
utcb_page = l4_utcb_page();
//printf("%s: UTCB Read from mm0 as: 0x%x\n", __FUNCTION__,
// (unsigned long)utcb_page);
/* Use it as a key to create a shared memory region */
BUG_ON((shmid = shmget((key_t)utcb_page,
PAGE_SIZE, IPC_CREAT)) < 0);
/* Attach to the region */
BUG_ON((shmaddr = shmat(shmid, utcb_page, 0)) < 0);
BUG_ON(shmaddr != utcb_page);
return 0;
}

View File

@@ -47,4 +47,25 @@ void *shmat_shmget_internal(struct tcb *task, key_t key, void *shmaddr);
struct vm_file *shm_new(key_t key, unsigned long npages);
void *shm_new_address(int npages);
/* Below is the special-case per-task default shared memory page prototypes */
/* Prefaults shared page after mapping */
#define SHPAGE_PREFAULT (1 << 0)
/* Creates new shm segment for default shpage */
#define SHPAGE_NEW_SHM (1 << 1)
/* Allocates a virtual address for default shpage */
#define SHPAGE_NEW_ADDRESS (1 << 2)
/* IPC to send utcb address information to tasks */
void *task_send_shpage_address(struct tcb *sender, l4id_t taskid);
int shpage_map_to_task(struct tcb *owner, struct tcb *mapper, unsigned int flags);
int shpage_unmap_from_task(struct tcb *owner, struct tcb *mapper);
/* Prefault a *mmaped* default shared page */
int shpage_prefault(struct tcb *task, unsigned int vmflags);
#endif /* __SHM_H__ */

View File

@@ -26,7 +26,7 @@
/* POSIX minimum is 4Kb */
#define DEFAULT_ENV_SIZE SZ_4K
#define DEFAULT_STACK_SIZE SZ_32K
#define DEFAULT_UTCB_SIZE PAGE_SIZE
#define DEFAULT_SHPAGE_SIZE PAGE_SIZE
#define TCB_NO_SHARING 0
#define TCB_SHARED_VM (1 << 0)
@@ -101,8 +101,8 @@ struct tcb {
unsigned long map_start;
unsigned long map_end;
/* UTCB information */
void *utcb;
/* Default ipc-shared-page information */
void *shared_page;
/* Virtual memory areas */
struct task_vma_head *vm_area_head;

View File

@@ -1,24 +0,0 @@
#ifndef __MM0_UTCB_H__
#define __MM0_UTCB_H__
#include <l4lib/types.h>
#include <task.h>
#define UTCB_PREFAULT (1 << 0) /* Prefaults utcb pages after mapping */
#define UTCB_NEW_SHM (1 << 1) /* Creates a new shm segment for utcb */
#define UTCB_NEW_ADDRESS (1 << 2) /* Allocates a virtual address for utcb */
int utcb_pool_init(void);
void *utcb_new_address(void);
int utcb_delete_address(void *utcb_addr);
/* IPC to send utcb address information to tasks */
void *task_send_utcb_address(struct tcb *sender, l4id_t taskid);
int utcb_map_to_task(struct tcb *owner, struct tcb *mapper, unsigned int flags);
int utcb_unmap_from_task(struct tcb *owner, struct tcb *mapper);
/* Prefault an *mmaped* utcb */
int utcb_prefault(struct tcb *task, unsigned int vmflags);
#endif

View File

@@ -20,7 +20,6 @@
#include <syscalls.h>
#include <file.h>
#include <shm.h>
#include <utcb.h>
#include <mmap.h>
#include <test.h>
#include <boot.h>
@@ -85,8 +84,8 @@ void handle_requests(void)
ret = sys_shmdt(sender, (void *)mr[0]);
break;
case L4_IPC_TAG_UTCB:
ret = (int)task_send_utcb_address(sender, (l4id_t)mr[0]);
case L4_IPC_TAG_SHPAGE:
ret = (int)task_send_shpage_address(sender, (l4id_t)mr[0]);
break;
case L4_IPC_TAG_READ:

View File

@@ -5,7 +5,6 @@
*/
#include <boot.h>
#include <mmap.h>
#include <utcb.h>
#include <shm.h>
#include <l4/api/thread.h>
#include <l4lib/arch/syslib.h>
@@ -74,11 +73,12 @@ int boottask_mmap_regions(struct tcb *task, struct vm_file *file)
return (int)mapped;
}
/* Task's utcb */
task->utcb = utcb_new_address();
/* Task's default shared page */
task->shared_page = shm_new_address(DEFAULT_SHPAGE_SIZE/PAGE_SIZE);
/* Create a shared memory segment available for shmat() */
if (IS_ERR(shm = shm_new((key_t)task->utcb, __pfn(DEFAULT_UTCB_SIZE))))
if (IS_ERR(shm = shm_new((key_t)task->shared_page,
__pfn(DEFAULT_SHPAGE_SIZE))))
return (int)shm;
return 0;

View File

@@ -12,7 +12,6 @@
#include <vm_area.h>
#include <task.h>
#include <mmap.h>
#include <utcb.h>
#include <shm.h>
#include <test.h>
#include <clone.h>
@@ -31,7 +30,7 @@ int vfs_notify_fork(struct tcb *child, struct tcb *parent, unsigned int flags)
/* Write parent and child information */
write_mr(L4SYS_ARG0, parent->tid);
write_mr(L4SYS_ARG1, child->tid);
write_mr(L4SYS_ARG2, (unsigned int)child->utcb);
write_mr(L4SYS_ARG2, (unsigned int)child->shared_page);
write_mr(L4SYS_ARG3, flags);
if ((err = l4_sendrecv(VFS_TID, VFS_TID,
@@ -85,8 +84,10 @@ int sys_fork(struct tcb *parent)
BUG();
/* Create and prefault a utcb for child and map it to vfs task */
utcb_map_to_task(child, find_task(VFS_TID),
UTCB_NEW_ADDRESS | UTCB_NEW_SHM | UTCB_PREFAULT);
shpage_map_to_task(child, find_task(VFS_TID),
SHPAGE_NEW_ADDRESS | SHPAGE_NEW_SHM |
SHPAGE_PREFAULT);
// printf("Mapped 0x%p to vfs as utcb of %d\n", child->utcb, child->tid);
/* We can now notify vfs about forked process */
@@ -138,8 +139,9 @@ int do_clone(struct tcb *parent, unsigned long child_stack, unsigned int flags)
BUG();
/* Create and prefault a utcb for child and map it to vfs task */
utcb_map_to_task(child, find_task(VFS_TID),
UTCB_NEW_ADDRESS | UTCB_NEW_SHM | UTCB_PREFAULT);
shpage_map_to_task(child, find_task(VFS_TID),
SHPAGE_NEW_ADDRESS | SHPAGE_NEW_SHM |
SHPAGE_PREFAULT);
/* We can now notify vfs about forked process */
vfs_notify_fork(child, parent, flags);

View File

@@ -37,16 +37,16 @@ int vfs_open_bypath(const char *pathname, unsigned long *vnum, unsigned long *le
return -ESRCH;
/*
* Copy string to vfs utcb.
* Copy string to vfs shared page.
*
* FIXME: There's a chance we're overwriting other tasks'
* ipc information that is on the vfs utcb.
* ipc information that is on the vfs shared page.
*/
strcpy(vfs->utcb, pathname);
strcpy(vfs->shared_page, pathname);
l4_save_ipcregs();
write_mr(L4SYS_ARG0, (unsigned long)vfs->utcb);
write_mr(L4SYS_ARG0, (unsigned long)vfs->shared_page);
if ((err = l4_sendrecv(VFS_TID, VFS_TID,
L4_IPC_TAG_PAGER_OPEN_BYPATH)) < 0) {

View File

@@ -3,9 +3,9 @@
*
* Copyright (C) 2008 Bahadir Balban
*/
#include <shm.h>
#include <task.h>
#include <file.h>
#include <utcb.h>
#include <exit.h>
#include <test.h>
#include <vm_area.h>
@@ -90,7 +90,7 @@ int execve_recycle_task(struct tcb *new, struct tcb *orig)
new->pagerid = orig->pagerid;
/* Copy utcb */
new->utcb = orig->utcb;
new->shared_page = orig->shared_page;
/* Copy parent relationship */
BUG_ON(new->parent);
@@ -131,9 +131,9 @@ void do_exit(struct tcb *task, int status)
/* Tell vfs that task is exiting */
vfs_notify_exit(task, status);
/* Remove utcb shm areas from vfs */
// printf("Unmapping 0x%p from vfs as utcb of %d\n", task->utcb, task->tid);
utcb_unmap_from_task(task, find_task(VFS_TID));
/* Remove default shared page shm areas from vfs */
// printf("Unmapping 0x%p from vfs as shared-page of %d\n", task->shared_page, task->tid);
shpage_unmap_from_task(task, find_task(VFS_TID));
/* Free task's local tcb */
tcb_destroy(task);

View File

@@ -15,7 +15,6 @@
#include <shm.h>
#include <file.h>
#include <init.h>
#include <utcb.h>
#include <test.h>
#include <boot.h>
@@ -168,12 +167,8 @@ void init_mm(struct initdata *initdata)
printf("SHM initialisation failed.\n");
BUG();
}
// printf("%s: Initialised shm structures.\n", __TASKNAME__);
printf("%s: Initialised shm structures.\n", __TASKNAME__);
if (utcb_pool_init() < 0) {
printf("UTCB initialisation failed.\n");
BUG();
}
/* For supplying contiguous virtual addresses to pager */
pager_address_pool_init();

View File

@@ -7,7 +7,6 @@
#include <stdio.h>
#include <task.h>
#include <mmap.h>
#include <utcb.h>
#include <vm_area.h>
#include <globals.h>
#include <lib/malloc.h>
@@ -181,15 +180,8 @@ void shm_destroy_priv_data(struct vm_file *shm_file)
struct shm_descriptor *shm_desc = shm_file_to_desc(shm_file);
/* Release the shared memory address */
if ((unsigned long)shm_desc->shm_addr >= UTCB_AREA_START &&
(unsigned long)shm_desc->shm_addr < UTCB_AREA_END) {
BUG_ON(utcb_delete_address(shm_desc->shm_addr) < 0);
} else if ((unsigned long)shm_desc->shm_addr >= SHM_AREA_START &&
(unsigned long)shm_desc->shm_addr < SHM_AREA_END) {
BUG_ON(shm_delete_address(shm_desc->shm_addr,
shm_file->vm_obj.npages) < 0);
} else
BUG();
BUG_ON(shm_delete_address(shm_desc->shm_addr,
shm_file->vm_obj.npages) < 0);
/* Release the shared memory id */
BUG_ON(id_del(shm_ids, shm_desc->shmid) < 0);
@@ -320,3 +312,76 @@ int sys_shmget(key_t key, int size, int shmflg)
return -ENOENT;
}
/*
* Currently, a default shm page is allocated to every thread in the system
* for efficient ipc communication. This part below provides the allocation
* and mapping of this page using shmat/get/dt call semantics.
*/
/*
* Sends shpage address information to requester. The requester then uses
* this address as a shm key and maps it via shmget/shmat.
*/
void *task_send_shpage_address(struct tcb *sender, l4id_t taskid)
{
struct tcb *task = find_task(taskid);
/* Is the task asking for its own utcb address */
if (sender->tid == taskid) {
/* It hasn't got one allocated. */
BUG_ON(!task->shared_page);
/* Return it to requester */
return task->shared_page;
/* A task is asking for someone else's utcb */
} else {
/* Only vfs is allowed to do so yet, because its a server */
if (sender->tid == VFS_TID) {
/*
* Return shpage address to requester. Note if there's
* none allocated so far, requester gets 0. We don't
* allocate one here.
*/
return task->shared_page;
}
}
return 0;
}
int shpage_map_to_task(struct tcb *owner, struct tcb *mapper, unsigned int flags)
{
struct vm_file *default_shm;
/* Allocate a new utcb address */
if (flags & SHPAGE_NEW_ADDRESS)
owner->shared_page =
shm_new_address(DEFAULT_SHPAGE_SIZE/PAGE_SIZE);
else if (!owner->shared_page)
BUG();
/* Create a new shared memory segment for utcb */
if (flags & SHPAGE_NEW_SHM)
if (IS_ERR(default_shm = shm_new((key_t)owner->shared_page,
__pfn(DEFAULT_SHPAGE_SIZE))))
return (int)default_shm;
/* Map the utcb to mapper */
if (IS_ERR(shmat_shmget_internal(mapper, (key_t)owner->shared_page,
owner->shared_page)))
BUG();
/* Prefault the owner's utcb to mapper's address space */
if (flags & SHPAGE_PREFAULT)
for (int i = 0; i < __pfn(DEFAULT_SHPAGE_SIZE); i++)
prefault_page(mapper, (unsigned long)owner->shared_page +
__pfn_to_addr(i), VM_READ | VM_WRITE);
return 0;
}
int shpage_unmap_from_task(struct tcb *owner, struct tcb *mapper)
{
return sys_shmdt(mapper, owner->shared_page);
}

View File

@@ -24,7 +24,6 @@
#include <vm_area.h>
#include <memory.h>
#include <file.h>
#include <utcb.h>
#include <task.h>
#include <exec.h>
#include <shm.h>
@@ -611,13 +610,13 @@ int vfs_send_task_data(struct tcb *vfs)
}
BUG_ON(!(self = find_task(self_tid())));
BUG_ON(!vfs->utcb);
BUG_ON(!vfs->shared_page);
/* Attach mm0 to vfs's utcb segment just like a normal task */
utcb_map_to_task(vfs, self, UTCB_PREFAULT);
shpage_map_to_task(vfs, self, SHPAGE_PREFAULT);
/* Write all requested task information to utcb's user buffer area */
tdata_head = (struct task_data_head *)vfs->utcb;
/* Write all requested task information to shared pages's user buffer area */
tdata_head = (struct task_data_head *)vfs->shared_page;
/* First word is total number of tcbs */
tdata_head->total = global_tasks.total;
@@ -625,7 +624,7 @@ int vfs_send_task_data(struct tcb *vfs)
/* Write per-task data for all tasks */
list_for_each_entry(t, &global_tasks.list, list) {
tdata_head->tdata[li].tid = t->tid;
tdata_head->tdata[li].utcb_address = (unsigned long)t->utcb;
tdata_head->tdata[li].utcb_address = (unsigned long)t->shared_page;
li++;
}

View File

@@ -1,107 +0,0 @@
/*
* 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 <shm.h>
#include <vm_area.h>
#include <syscalls.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_new_address(void)
{
return address_new(&utcb_vaddr_pool, 1);
}
int utcb_delete_address(void *utcb_addr)
{
return address_del(&utcb_vaddr_pool, utcb_addr, 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.
*/
void *task_send_utcb_address(struct tcb *sender, l4id_t taskid)
{
struct tcb *task = find_task(taskid);
/* Is the task asking for its own utcb address */
if (sender->tid == taskid) {
/* It hasn't got one allocated. */
BUG_ON(!task->utcb);
/* Return it to requester */
return 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->tid == 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 task->utcb;
}
}
return 0;
}
int utcb_map_to_task(struct tcb *owner, struct tcb *mapper, unsigned int flags)
{
struct vm_file *utcb_shm;
/* Allocate a new utcb address */
if (flags & UTCB_NEW_ADDRESS)
owner->utcb = utcb_new_address();
else if (!owner->utcb)
BUG();
/* Create a new shared memory segment for utcb */
if (flags & UTCB_NEW_SHM)
if (IS_ERR(utcb_shm = shm_new((key_t)owner->utcb,
__pfn(DEFAULT_UTCB_SIZE))))
return (int)utcb_shm;
/* Map the utcb to mapper */
if (IS_ERR(shmat_shmget_internal(mapper, (key_t)owner->utcb,
owner->utcb)))
BUG();
/* Prefault the owner's utcb to mapper's address space */
if (flags & UTCB_PREFAULT)
for (int i = 0; i < __pfn(DEFAULT_UTCB_SIZE); i++)
prefault_page(mapper, (unsigned long)owner->utcb +
__pfn_to_addr(i), VM_READ | VM_WRITE);
return 0;
}
int utcb_unmap_from_task(struct tcb *owner, struct tcb *mapper)
{
return sys_shmdt(mapper, owner->utcb);
}

View File

@@ -1,15 +0,0 @@
cd build
#arm-none-eabi-insight &
/opt/qemu-0.10.2/bin/qemu-system-arm -s -kernel final.axf -nographic -m 128 -M versatilepb &
#qemu-system-arm -s -kernel final.axf -nographic -m 128 -M versatilepb &
#qemu-system-arm -s -kernel final.axf -nographic -m 128 -M versatilepb &
arm-none-linux-gnueabi-insight ; pkill qemu-system-arm
#arm-none-linux-gnueabi-gdb ; pkill qemu-system-arm
cd ..
# TODO:
# insight works ok if gdbinit script is run from the insight
# command window. Then one needs to break at bkpt_phys_to_virt and do:
# sym start.axf
# Then continue execution to see all symbols. This must be done automatic.