Ongoing work for adding per-thread UTCB structures.

Added setting of utcb address to l4_thread_control.
This is going to be moved to exchange_registers() since we need to pass
both the utcb physical and virtual address and exregs fits such context
modification better than thread_control.
This commit is contained in:
Bahadir Balban
2009-04-29 16:53:04 +03:00
parent 54a9b2901d
commit 7a81db8782
35 changed files with 424 additions and 72 deletions

50
docs/tls.txt Normal file
View File

@@ -0,0 +1,50 @@
Thread Local Storage and UTCB Access
In an L4-like microkernel such as Codezero, there needs to be a way of
accessing the User Thread Control Block (UTCB) in order to push argument
registers and write the IPC payload. This necessitates a convenient method
of accessing the thread-specific utcb structure. Here are some of the
possible methods of accessing a thread local storage in general:
1.) Keep a global pointer to it. The scheduler updates the pointer to TLS
upon every context switch.
2.) Map the private physical TLS page to thread address space at same virtual
offset, everytime there is a context switch.
3.) Manage everything by the run-time library in the application. This includes
the following:
* Predefine a fixed TLS table area on the address space.
* Possibly allocate local thread ids E.g. [1..n]
* Get current thread id
* Take a lock (on the TLS table)
* Lookup the pointer to the TLS block by thread id
* Release the lock
* Return that pointer
The third one is least flexible solution since it requires management of the
TLS area, has concurrency issues, and limits the number of TLS areas available.
Since UTCB concept is at the heart of Codezero IPC mechanisms, it has to be
done neatly and flexibly. In that respect lets evaluate solutions:
1.) This is most convenient since user applications can simply reference a
pointer to get their unique TLS. By this approach no need to spend excessive
memory by using a page per TLS (in case TLS is less than a page). The downside
is the UTCB region still needs to be defined by a limit in the address space
and managed by the pager, if not by the application. This is because every UTCB
shall be part of an array or a table of unique UTCBs.
2.) Mapping a per-thread physical page to a fixed virtual address upon a context
switch is the most flexible, since the pager can simply allocate a physical page
as new threads come to life, and map this when they run, without managing utcb
table size. The downside is that a page is wasted per-thread.
The solution Codezero uses includes a mixture of both (1) and (2). Upon a
context switch, a private page is allocated and mapped by the pager, but also
the UTCB pointer is updated to point at an offset in this page. As an example,
if a UTCB is sized 1/4th of a page, a single page is used by 4 UTCBs. This way,
the pager needs to manage 4 entries per-private page, utcbs utilise page memory
better, and there is no need for a fixed table of utcbs per address space.

View File

@@ -11,9 +11,8 @@
#include INC_GLUE(context.h)
#include <l4/types.h>
enum exregs_flags {
EXREGS_SET_PAGER = 1,
};
#define EXREGS_SET_PAGER 1
#define EXREGS_SET_UTCB 2
/* Structure passed by userspace pagers for exchanging registers */
struct exregs_data {
@@ -21,6 +20,8 @@ struct exregs_data {
u32 valid_vect;
u32 flags;
l4id_t pagerid;
unsigned long utcb_phys;
unsigned long utcb_virt;
};

View File

@@ -68,6 +68,8 @@ struct kip {
u32 arch_syscall2;
u32 arch_syscall3;
u32 utcb;
struct kernel_desc kdesc;
} __attribute__((__packed__));

View File

@@ -1,7 +1,7 @@
#ifndef __THREAD_H__
#define __THREAD_H__
#define THREAD_CREATE_MASK 0x00F0
#define THREAD_CREATE_MASK 0x0030
/* Create new thread and new space */
#define THREAD_NEW_SPACE 0x0010
@@ -12,7 +12,11 @@
/* Create new thread, use given space */
#define THREAD_SAME_SPACE 0x0030
/* Shared UTCB, New UTCB, No UTCB */
#define THREAD_UTCB_MASK 0x00C0
#define THREAD_UTCB_NEW 0x0040
#define THREAD_UTCB_SAME 0x0080
#define THREAD_UTCB_NONE 0x00C0
#define THREAD_ACTION_MASK 0x000F

View File

@@ -70,7 +70,10 @@ struct ktcb {
u32 ts_need_resched; /* Scheduling flag */
enum task_state state;
struct list_head task_list; /* Global task list. */
struct utcb *utcb; /* Reference to task's utcb area */
/* UTCB related, see utcb.txt in docs */
unsigned long utcb_virt; /* Virtual ref to task's utcb area */
unsigned long utcb_phys; /* Physical ref to task's utcb area */
/* Thread times */
u32 kernel_time; /* Ticks spent in kernel */

View File

@@ -43,7 +43,7 @@
#define USER_KIP_PAGE 0xFF000000
/* ARM-specific offset in KIP that tells the address of UTCB page */
#define UTCB_KIP_OFFSET 0xFF0
#define UTCB_KIP_OFFSET 0x50
#define IO_AREA0_VADDR (IO_AREA_START + (ARM_SECTION_SIZE*0))
#define IO_AREA1_VADDR (IO_AREA_START + (ARM_SECTION_SIZE*1))

View File

@@ -6,6 +6,7 @@
#ifndef __GLUE_ARM_MESSAGE_H__
#define __GLUE_ARM_MESSAGE_H__
#define MR_REST 56
#define MR_TOTAL 6
#define MR_TAG 0 /* Contains the purpose of message */
#define MR_SENDER 1 /* For anythread receivers to discover sender */

View File

@@ -87,7 +87,6 @@
_start:
ldr sp, =__stack
bl platform_init
bl __l4_init
bl __container_init
1:
b 1b

View File

@@ -78,6 +78,13 @@ void do_exchange_registers(struct ktcb *task, struct exregs_data *exregs)
if (exregs->flags & EXREGS_SET_PAGER)
task->pagerid = exregs->pagerid;
/* Set thread's utcb if supplied */
if (exregs->flags & EXREGS_SET_UTCB) {
BUG(); /* Check that physical and virtual addresses are in range */
task->utcb_phys = exregs->utcb_phys;
task->utcb_virt = exregs->utcb_virt;
}
}
/*

View File

@@ -164,10 +164,92 @@ int thread_start(struct task_ids *ids)
return 0;
}
int arch_setup_new_thread(struct ktcb *new, struct ktcb *orig, unsigned int flags)
/*
* Given thread creation flags, determines whether to use a new user
* (pager)-supplied utcb address, the utcb address of the original thread,
* or no utcb at all. Validation of flags done at beginning of thread_create().
*/
int arch_new_thread_setup_utcb(struct ktcb *new, struct ktcb *orig, unsigned int flags,
unsigned long utcb_address)
{
unsigned int create_flags = flags & THREAD_CREATE_MASK;
unsigned int utcb_flags = flags & THREAD_UTCB_MASK;
/* In case of multiple threads in same address space */
if (create_flags == THREAD_SAME_SPACE) {
switch (utcb_flags) {
case THREAD_UTCB_SAME:
new->utcb_address = orig->utcb_address;
break;
case THREAD_UTCB_NEW:
new->utcb_address = utcb_address;
break;
case THREAD_UTCB_NONE:
new->utcb_address = 0;
break;
default:
printk("%s: Bad thread creation flags. "
"Incorrect flag validation?\n",__FUNCTION__);
BUG();
}
}
/* In case of brand new address space and thread */
if (create_flags == THREAD_NEW_SPACE) {
switch (utcb_flags) {
case THREAD_UTCB_NEW:
new->utcb_address = utcb_address;
break;
/*
* No UTCB for brand new space means the thread cannot do
* an ipc other than exceptions. This is allowed for now.
*/
case THREAD_UTCB_NONE:
new->utcb_address = 0;
break;
default:
printk("%s: Bad thread creation flags. "
"Incorrect flag validation?\n",__FUNCTION__);
BUG();
}
}
/*
* This essentially corresponds to fork() and normally we would expect
* the UTCB to be the same as original thread, since the whole address
* space is an identical image of the original. Nevertheless it doesn't
* do harm to have none or different utcb address and this is left to
* the implementor to decide.
*/
if (create_flags == THREAD_COPY_SPACE) {
switch (utcb_flags) {
case THREAD_UTCB_SAME:
new->utcb_address = orig->utcb_address;
break;
case THREAD_UTCB_NEW:
new->utcb_address = utcb_address;
break;
case THREAD_UTCB_NONE:
new->utcb_address = 0;
break;
default:
printk("%s: Bad thread creation flags. "
"Incorrect flag validation?\n",__FUNCTION__);
BUG();
}
}
return 0;
}
int arch_setup_new_thread(struct ktcb *new, struct ktcb *orig,
unsigned int flags, unsigned long utcb_address)
{
/* Set up the utcb address */
arch_new_thread_setup_utcb(new, orig, flags, utcb_address);
/* New threads just need their mode set up */
if (flags == THREAD_NEW_SPACE) {
if ((flags & THREAD_CREATE_MASK) == THREAD_NEW_SPACE) {
BUG_ON(orig);
new->context.spsr = ARM_MODE_USR;
return 0;
@@ -262,12 +344,28 @@ int thread_setup_new_ids(struct task_ids *ids, unsigned int flags,
* are respectively used when creating a brand new task, creating a
* new thread in an existing address space, or forking a task.
*/
int thread_create(struct task_ids *ids, unsigned int flags)
int thread_create(struct task_ids *ids, unsigned int flags,
unsigned long utcb_address)
{
struct ktcb *task = 0, *new = (struct ktcb *)zalloc_page();
flags &= THREAD_CREATE_MASK;
unsigned int create_flags = flags & THREAD_CREATE_MASK;
unsigned int utcb_flags = flags & THREAD_UTCB_MASK;
if (flags == THREAD_NEW_SPACE) {
/* Handle error cases. Should have valid flags for each */
if (!utcb_flags || !create_flags)
return -EINVAL;
/* Cannot have new space with same utcb */
else if (create_flags == THREAD_NEW_SPACE &&
utcb_flags == THREAD_UTCB_SAME)
return -EINVAL;
/* Cannot have new utcb with invalid address */
else if (utcb_flags == THREAD_UTCB_NEW && !utcb_address)
return -EINVAL;
/* Determine space allocation */
if (create_flags == THREAD_NEW_SPACE) {
/* Allocate new pgd and copy all kernel areas */
new->pgd = alloc_pgd();
copy_pgd_kern_all(new->pgd);
@@ -289,7 +387,7 @@ int thread_create(struct task_ids *ids, unsigned int flags)
}
out:
/* Set up new thread's tid, spid, tgid according to flags */
thread_setup_new_ids(ids, flags, new, task);
thread_setup_new_ids(ids, create_flags, new, task);
/* Initialise task's scheduling state and parameters. */
sched_init_task(new, TASK_PRIO_NORMAL);
@@ -299,7 +397,7 @@ out:
waitqueue_head_init(&new->wqh_recv);
waitqueue_head_init(&new->wqh_pager);
arch_setup_new_thread(new, task, flags);
arch_setup_new_thread(new, task, flags, utcb_address);
/* Add task to global hlist of tasks */
add_task_global(new);
@@ -317,10 +415,11 @@ int sys_thread_control(syscall_context_t *regs)
int ret = 0;
unsigned int flags = regs->r0;
struct task_ids *ids = (struct task_ids *)regs->r1;
unsigned long utcb_address = regs->r2;
switch (flags & THREAD_ACTION_MASK) {
case THREAD_CREATE:
ret = thread_create(ids, flags);
ret = thread_create(ids, flags, utcb_address);
break;
case THREAD_RUN:
ret = thread_start(ids);

View File

@@ -255,6 +255,9 @@ static inline void context_switch(struct ktcb *next)
// printk("(%d) to (%d)\n", cur->tid, next->tid);
/* Update KIP UTCB pointer for new thread to run */
kip.utcb = next->utcb_address;
/* Flush caches and everything */
arch_hardware_flush(next->pgd);

23
tasks/fs0/container.c Normal file
View File

@@ -0,0 +1,23 @@
/*
* Container entry point for this task
*
* Copyright (C) 2007-2009 Bahadir Bilgehan Balban
*/
#include <posix/posix_init.h>
#include <l4lib/init.h>
#include <l4lib/utcb.h>
void main(void);
void __container_init(void)
{
/* Generic L4 thread initialisation */
__l4_init();
/* FS0 posix-service initialisation */
posix_service_init();
/* Entry to main */
main();
}

View File

@@ -32,6 +32,10 @@ SECTIONS
.rodata1 : AT (ADDR(.rodata1) - offset) { *(.rodata1) }
.data : AT (ADDR(.data) - offset)
{
. = ALIGN(4K); /* Align UTCB to page boundary */
_start_utcb = .;
*(.utcb)
_end_utcb = .;
. = ALIGN(4K);
_start_bdev = .;
*(.data.memfs)
@@ -39,5 +43,6 @@ SECTIONS
*(.data)
}
.bss : AT (ADDR(.bss) - offset) { *(.bss) }
_end = .;
}

View File

@@ -8,6 +8,7 @@
#include <l4/api/errno.h>
#include <l4lib/arch/syscalls.h>
#include <l4lib/arch/syslib.h>
#include <l4lib/arch/utcb.h>
#include <l4lib/ipcdefs.h>
#include <lib/malloc.h>
#include <lib/idpool.h>
@@ -20,6 +21,7 @@
#include <syscalls.h>
#include <globals.h>
extern void *shared_page;
struct global_list global_tasks = {

View File

@@ -6,6 +6,7 @@
#ifndef __ARM_SYSCALLS_H__
#define __ARM_SYSCALLS_H__
#include <l4lib/arch/types.h>
#include <l4lib/arch/utcb.h>
#include <l4/generic/space.h>
@@ -14,6 +15,12 @@
#include <l4/api/ipc.h>
#include <l4/api/thread.h>
struct task_ids {
int tid;
int spid;
int tgid;
};
static inline void *
l4_kernel_interface(unsigned int *api_version, unsigned int *api_flags,
unsigned int *kernel_id)
@@ -46,9 +53,9 @@ typedef int (*__l4_unmap_t)(void *virt, unsigned long npages, l4id_t tid);
extern __l4_unmap_t __l4_unmap;
int l4_unmap(void *virtual, unsigned long numpages, l4id_t tid);
typedef int (*__l4_thread_control_t)(unsigned int action, struct task_ids *ids);
typedef int (*__l4_thread_control_t)(unsigned int action, struct task_ids *ids, void *utcb_address);
extern __l4_thread_control_t __l4_thread_control;
int l4_thread_control(unsigned int action, struct task_ids *ids);
int l4_thread_control(unsigned int action, struct task_ids *ids, void *utcb_address);
typedef int (*__l4_space_control_t)(unsigned int action, void *kdata);
extern __l4_space_control_t __l4_space_control;

View File

@@ -1,13 +1,8 @@
#ifndef __L4_ARCH_ARM__
#define __L4_ARCH_ARM__
#ifndef __L4LIB_ARM_TYPES_H___
#define __L4LIB_ARM_TYPES_H__
#define TASK_ID_INVALID -1
struct task_ids {
int tid;
int spid;
int tgid;
};
#include <l4/arch/arm/types.h>
#endif
#endif /* __L4LIB_ARM_TYPES_H__ */

View File

@@ -1,9 +1,12 @@
/*
* Copyright (C) 2009 Bahadir Bilgehan Balban
*/
#ifndef __ARM_UTCB_H__
#define __ARM_UTCB_H__
#define USER_UTCB_REF 0xFF000FF0
#define USER_UTCB_REF 0xFF000050
#define L4_KIP_ADDRESS 0xFF000000
#define UTCB_KIP_OFFSET 0xFF0
#define UTCB_KIP_OFFSET 0x50
#ifndef __ASSEMBLY__
#include <l4lib/types.h>
@@ -13,27 +16,37 @@
#include <string.h>
#include <stdio.h>
/* UTCB implementation */
/*
* NOTE: In syslib.h the first few mrs are used by data frequently
* needed for all ipcs. Those mrs are defined the kernel message.h
*/
/*
* This is a per-task private structure where message registers are
* pushed for ipc. Its *not* TLS, but can be part of TLS when it is
* supported.
*/
struct utcb {
u32 mr[MR_TOTAL];
u32 saved_tag;
u32 saved_sender;
} __attribute__((__packed__));
u32 mr[MR_TOTAL]; /* MRs that are mapped to real registers */
u32 saved_tag; /* Saved tag field for stacked ipcs */
u32 saved_sender; /* Saved sender field for stacked ipcs */
u32 mr_rest[MR_REST]; /* Complete the utcb for up to 64 words */
};
extern struct utcb utcb;
extern struct kip *kip;
/*
* Pointer to Kernel Interface Page's UTCB pointer offset.
*/
extern struct utcb **kip_utcb_ref;
static inline struct utcb *l4_get_utcb()
{
return &utcb;
/*
* By double dereferencing, we get the private TLS (aka UTCB). First
* reference is to the KIP's utcb offset, second is to the utcb itself,
* to which the KIP's utcb reference had been updated during context
* switch.
*/
return *kip_utcb_ref;
}
/* Functions to read/write utcb registers */

View File

@@ -7,6 +7,7 @@ void exregs_set_stack(struct exregs_data *s, unsigned long sp);
void exregs_set_mr(struct exregs_data *s, int offset, unsigned long val);
void exregs_set_pc(struct exregs_data *s, unsigned long pc);
void exregs_set_pager(struct exregs_data *s, l4id_t pagerid);
void exregs_set_utcb(struct exregs_data *s, unsigned long phys, unsigned long virt);
/*
exregs_set_stack(unsigned long sp)

View File

@@ -0,0 +1,6 @@
#ifndef __L4LIB_INIT__
#define __L4LIB_INIT__
void __l4_init(void);
#endif

View File

@@ -0,0 +1,14 @@
#ifndef __L4_THREAD_H__
#define __L4_THREAD_H__
#include <libl4/arch/utcb.h>
#include <libl4/arch/types.h>
struct l4_thread_struct {
l4id_t tlid; /* Thread local id */
struct task_ids ids; /* Thread L4-defined ids */
struct utcb *utcb; /* Thread utcb */
unsigned long stack_start; /* Thread start of stack */
};
#endif /* __L4_THREAD_H__ */

View File

@@ -9,6 +9,7 @@
#include INC_GLUE(message.h)
void exregs_set_mr(struct exregs_data *s, int offset, unsigned long val)
{
/* Get MR0 */
@@ -30,6 +31,14 @@ void exregs_set_pager(struct exregs_data *s, l4id_t pagerid)
s->flags |= EXREGS_SET_PAGER;
}
void exregs_set_utcb(struct exregs_data *s, unsigned long phys,
unsigned long virt)
{
s->utcb_phys = phys;
s->utcb_virt = virt;
s->flags |= EXREGS_SET_UTCB;
}
void exregs_set_stack(struct exregs_data *s, unsigned long sp)
{
s->context.sp = sp;

View File

@@ -9,9 +9,18 @@
#include <l4/macros.h>
#include INC_GLUE(message.h)
/* Old macro */
#if 0
.macro utcb_address rx
ldr \rx, =utcb
.endm
#endif
/* New macro does double dereference */
.macro utcb_address rx
ldr \rx, =kip_utcb_ref @ First get pointer to utcb pointer in KIP
ldr \rx, [\rx] @ Get UTCB address from UTCB pointer in KIP
.endm
BEGIN_PROC(l4_thread_switch)
ldr r12, =__l4_thread_switch
@@ -152,7 +161,7 @@ END_PROC(l4_time)
/*
* System call that controls thread creation, destruction and modification.
* @r0 = thread action, @r1 = &ids
* @r0 = thread action, @r1 = &ids, @r2 = utcb address
*/
BEGIN_PROC(l4_thread_control)
stmfd sp!, {lr}

View File

@@ -1,7 +1,7 @@
/*
* Initialise system call offsets.
* Initialise system call offsets and utcb reference.
*
* Copyright (C) 2007, 2008 Bahadir Balban
* Copyright (C) 2007-2009 Bahadir Bilgehan Balban
*/
#include <l4lib/kip.h>
#include <l4lib/arch/syslib.h>
@@ -27,16 +27,20 @@ __l4_time_t __l4_time = 0;
struct kip *kip;
/*
* Private UTCB of this task. Used only for pushing/reading ipc
* message registers.
* Reference to private UTCB of this thread.
* Used only for pushing/reading ipc message registers.
*/
struct utcb utcb;
struct utcb **kip_utcb_ref;
void __l4_init(void)
{
/* Kernel interface page */
kip = l4_kernel_interface(0, 0, 0);
/* Reference to utcb field of KIP */
kip_utcb_ref = (struct utcb **)&kip->utcb;
__l4_ipc = (__l4_ipc_t)kip->ipc;
__l4_map = (__l4_map_t)kip->map;
__l4_unmap = (__l4_unmap_t)kip->unmap;

View File

@@ -12,7 +12,7 @@
#include <l4lib/utcb.h>
#include <l4/macros.h>
#include INC_GLUE(memory.h)
#include <posix_init.h>
#include <shpage.h>
static inline int l4_fork(void)
{
@@ -43,10 +43,10 @@ int fork(void)
/*
* If we're a child, we need to initialise the default
* shared page via posix_init()
* shared page via libposix_init()
*/
if (ret == 0)
posix_init();
shared_page_init();
return ret;
}

View File

@@ -1,6 +1,7 @@
#ifndef __POSIX_INIT_H__
#define __POSIX_INIT_H__
#ifndef __LIBPOSIX_INIT_H__
#define __LIBPOSIX_INIT_H__
void posix_init(void);
void libposix_init(void);
void posix_service_init(void);
#endif /* __POSIX_INIT_H__ */
#endif /* __LIBPOSIX_INIT_H__ */

View File

@@ -3,28 +3,20 @@
*
* Copyright (C) 2007-2009 Bahadir Balban
*/
#include <shpage.h>
#include <posix_init.h>
void posix_init(void)
void posix_service_init(void)
{
/* Non-pager tasks initialise their shared communication page */
if (self_tid() != PAGER_TID)
shared_page_init();
BUG_ON(self_tid() != VFS_TID);
shared_page_init();
}
int main(void);
/*
* Entry point for posix services container.
*
* This is executed by all posix system services and tasks
* that run in this container.
*/
void __container_init(void)
void libposix_init(void)
{
posix_init();
main();
/* Shall only be run by posix applications */
BUG_ON(self_tid() == PAGER_TID || self_tid() == VFS_TID);
shared_page_init();
}

28
tasks/mm0/container.c Normal file
View File

@@ -0,0 +1,28 @@
/*
* Container entry point for pager
*
* Copyright (C) 2007-2009 Bahadir Bilgehan Balban
*/
#include <posix/posix_init.h>
#include <l4lib/init.h>
#include <l4lib/utcb.h>
/*
* Application specific utcb allocation
* for this container.
*
* Copyright (C) 2007-2009 Bahadir Balban
*/
void main(void);
void __container_init(void)
{
/* Generic L4 initialisation */
__l4_init();
/* Entry to main */
main();
}

View File

@@ -29,7 +29,11 @@ SECTIONS
/* rodata is needed else your strings will link at physical! */
.rodata : AT (ADDR(.rodata) - offset) { *(.rodata) }
.rodata1 : AT (ADDR(.rodata1) - offset) { *(.rodata1) }
.data : AT (ADDR(.data) - offset) { *(.data) }
.data : AT (ADDR(.data) - offset)
{
*(.data)
}
. = ALIGN(4K);
_start_init = .;
.init : AT (ADDR(.init) - offset) { *(.init.stack) }
. = ALIGN(8);

View File

@@ -11,6 +11,7 @@
#include INC_GLUE(memlayout.h)
#include <l4/lib/list.h>
#include <l4lib/arch/types.h>
#include <l4lib/arch/syscalls.h>
#include <l4lib/utcb.h>
#include <lib/addr.h>
#include <l4/api/kip.h>
@@ -53,6 +54,20 @@ struct task_vma_head {
int tcb_refs;
};
/*
* TLS and UTCB bookkeeping:
*
* This structure is shared among threads whose utcbs are on the same
* physical page. Threads with utcbs on different physical pages have
* their own utcb_data structure, even though they are in the same
* address space, and share their vm_area_list structure.
*/
struct utcb_data {
unsigned long phys; /* Physical utcb address */
unsigned long virt; /* Virtual utcb address */
u32 bit; /* Bitvector of free utcb slots on page */
struct page *p; /* Physical page */
};
/* Stores all task information that can be kept in userspace. */
struct tcb {
@@ -104,6 +119,9 @@ struct tcb {
/* Default ipc-shared-page information */
void *shared_page;
/* Task's utcb data */
struct utcb_data *utcb;
/* Virtual memory areas */
struct task_vma_head *vm_area_head;

View File

@@ -7,10 +7,10 @@
#define __VM_AREA_H__
#include <stdio.h>
#include <task.h>
#include <l4/macros.h>
#include <l4/config.h>
#include <l4/types.h>
#include <task.h>
#include <arch/mm.h>
#include <lib/spinlock.h>

View File

@@ -18,6 +18,7 @@
#include <test.h>
#include <boot.h>
/* A separate list than the generic file list that keeps just the boot files */
LIST_HEAD(boot_file_list);

27
tasks/mm0/src/utcb.c Normal file
View File

@@ -0,0 +1,27 @@
/*
* Management of task utcb regions and own utcb.
*
* Copyright (C) 2007-2009 Bahadir Bilgehan Balban
*/
#include <l4lib/arch/utcb.h>
#include <l4/macros.h>
/*
* UTCB management in Codezero:
*
* 1.) Every task in the system defines an array of utcbs in a special .utcb
* section that is page-aligned and to be kept wired in by the pager.
* 2.) The region marks are written to bootdesc structure at compile-time.
* 3.) Pager reads the bootdesc struct from the microkernel during init.
* 4.) Pager initialises structures to alloc/dealloc new utcbs for every address
* space.
* 5.) Pagers dynamically allocate utcb addresses as each thread is created
* via a thread_control() system call.
* 6.) Each thread in an address space learns their utcb address from a
* well-defined KIP offset. This is updated as each thread becomes runnable.
*/

View File

@@ -68,7 +68,7 @@ env = Environment(CC = 'arm-none-linux-gnueabi-gcc',
CPPFLAGS = "-D__USERSPACE__",
CPPPATH = ['#include', libl4_incpath, libposix_incpath, kernel_incpath])
src = [glob("src/*.c"), glob("*.c"), glob("*.S"), glob("src/arch/arm/*.c")]
src = [glob("src/*.c"), glob("*.c"), glob("*.S"), glob("src/arch/arm/*.c"), glob("../libcont/*.c")]
objs = env.Object(src)
physical_base = env.Command(physical_base_ld_script, prev_image, get_physical_base)
crt0_copied = env.Command("crt0.o", libc_crt0, copy_crt0)

25
tasks/test0/container.c Normal file
View File

@@ -0,0 +1,25 @@
/*
* Container entry point for this task.
*
* Copyright (C) 2007-2009 Bahadir Bilgehan Balban
*/
#include <l4lib/types.h>
#include <l4lib/init.h>
#include <l4lib/utcb.h>
#include <posix_init.h> /* Initialisers for posix library */
void main(void);
void __container_init(void)
{
/* Generic L4 thread initialisation */
__l4_init();
/* Initialise posix library for application */
libposix_init();
/* Entry to main */
main();
}

View File

@@ -30,10 +30,9 @@ SECTIONS
/* rodata is needed else your strings will link at physical! */
.rodata : AT (ADDR(.rodata) - offset) { *(.rodata) }
.rodata1 : AT (ADDR(.rodata1) - offset) { *(.rodata1) }
. = ALIGN(4K);
.data : AT (ADDR(.data) - offset)
{
. = ALIGN(4K);
_start_test1 = .;
*(.test1)
_end_test1 = .;