mirror of
https://github.com/drasko/codezero.git
synced 2026-02-28 09:43:14 +01:00
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:
50
docs/tls.txt
Normal file
50
docs/tls.txt
Normal 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.
|
||||||
|
|
||||||
@@ -11,9 +11,8 @@
|
|||||||
#include INC_GLUE(context.h)
|
#include INC_GLUE(context.h)
|
||||||
#include <l4/types.h>
|
#include <l4/types.h>
|
||||||
|
|
||||||
enum exregs_flags {
|
#define EXREGS_SET_PAGER 1
|
||||||
EXREGS_SET_PAGER = 1,
|
#define EXREGS_SET_UTCB 2
|
||||||
};
|
|
||||||
|
|
||||||
/* Structure passed by userspace pagers for exchanging registers */
|
/* Structure passed by userspace pagers for exchanging registers */
|
||||||
struct exregs_data {
|
struct exregs_data {
|
||||||
@@ -21,6 +20,8 @@ struct exregs_data {
|
|||||||
u32 valid_vect;
|
u32 valid_vect;
|
||||||
u32 flags;
|
u32 flags;
|
||||||
l4id_t pagerid;
|
l4id_t pagerid;
|
||||||
|
unsigned long utcb_phys;
|
||||||
|
unsigned long utcb_virt;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -68,6 +68,8 @@ struct kip {
|
|||||||
u32 arch_syscall2;
|
u32 arch_syscall2;
|
||||||
u32 arch_syscall3;
|
u32 arch_syscall3;
|
||||||
|
|
||||||
|
u32 utcb;
|
||||||
|
|
||||||
struct kernel_desc kdesc;
|
struct kernel_desc kdesc;
|
||||||
} __attribute__((__packed__));
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#ifndef __THREAD_H__
|
#ifndef __THREAD_H__
|
||||||
#define __THREAD_H__
|
#define __THREAD_H__
|
||||||
|
|
||||||
#define THREAD_CREATE_MASK 0x00F0
|
#define THREAD_CREATE_MASK 0x0030
|
||||||
|
|
||||||
/* Create new thread and new space */
|
/* Create new thread and new space */
|
||||||
#define THREAD_NEW_SPACE 0x0010
|
#define THREAD_NEW_SPACE 0x0010
|
||||||
@@ -12,7 +12,11 @@
|
|||||||
/* Create new thread, use given space */
|
/* Create new thread, use given space */
|
||||||
#define THREAD_SAME_SPACE 0x0030
|
#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
|
#define THREAD_ACTION_MASK 0x000F
|
||||||
|
|||||||
@@ -70,7 +70,10 @@ struct ktcb {
|
|||||||
u32 ts_need_resched; /* Scheduling flag */
|
u32 ts_need_resched; /* Scheduling flag */
|
||||||
enum task_state state;
|
enum task_state state;
|
||||||
struct list_head task_list; /* Global task list. */
|
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 */
|
/* Thread times */
|
||||||
u32 kernel_time; /* Ticks spent in kernel */
|
u32 kernel_time; /* Ticks spent in kernel */
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
#define USER_KIP_PAGE 0xFF000000
|
#define USER_KIP_PAGE 0xFF000000
|
||||||
|
|
||||||
/* ARM-specific offset in KIP that tells the address of UTCB page */
|
/* 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_AREA0_VADDR (IO_AREA_START + (ARM_SECTION_SIZE*0))
|
||||||
#define IO_AREA1_VADDR (IO_AREA_START + (ARM_SECTION_SIZE*1))
|
#define IO_AREA1_VADDR (IO_AREA_START + (ARM_SECTION_SIZE*1))
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#ifndef __GLUE_ARM_MESSAGE_H__
|
#ifndef __GLUE_ARM_MESSAGE_H__
|
||||||
#define __GLUE_ARM_MESSAGE_H__
|
#define __GLUE_ARM_MESSAGE_H__
|
||||||
|
|
||||||
|
#define MR_REST 56
|
||||||
#define MR_TOTAL 6
|
#define MR_TOTAL 6
|
||||||
#define MR_TAG 0 /* Contains the purpose of message */
|
#define MR_TAG 0 /* Contains the purpose of message */
|
||||||
#define MR_SENDER 1 /* For anythread receivers to discover sender */
|
#define MR_SENDER 1 /* For anythread receivers to discover sender */
|
||||||
|
|||||||
@@ -87,7 +87,6 @@
|
|||||||
_start:
|
_start:
|
||||||
ldr sp, =__stack
|
ldr sp, =__stack
|
||||||
bl platform_init
|
bl platform_init
|
||||||
bl __l4_init
|
|
||||||
bl __container_init
|
bl __container_init
|
||||||
1:
|
1:
|
||||||
b 1b
|
b 1b
|
||||||
|
|||||||
@@ -78,6 +78,13 @@ void do_exchange_registers(struct ktcb *task, struct exregs_data *exregs)
|
|||||||
if (exregs->flags & EXREGS_SET_PAGER)
|
if (exregs->flags & EXREGS_SET_PAGER)
|
||||||
task->pagerid = exregs->pagerid;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
115
src/api/thread.c
115
src/api/thread.c
@@ -164,10 +164,92 @@ int thread_start(struct task_ids *ids)
|
|||||||
return 0;
|
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 */
|
/* New threads just need their mode set up */
|
||||||
if (flags == THREAD_NEW_SPACE) {
|
if ((flags & THREAD_CREATE_MASK) == THREAD_NEW_SPACE) {
|
||||||
BUG_ON(orig);
|
BUG_ON(orig);
|
||||||
new->context.spsr = ARM_MODE_USR;
|
new->context.spsr = ARM_MODE_USR;
|
||||||
return 0;
|
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
|
* are respectively used when creating a brand new task, creating a
|
||||||
* new thread in an existing address space, or forking a task.
|
* 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();
|
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 */
|
/* Allocate new pgd and copy all kernel areas */
|
||||||
new->pgd = alloc_pgd();
|
new->pgd = alloc_pgd();
|
||||||
copy_pgd_kern_all(new->pgd);
|
copy_pgd_kern_all(new->pgd);
|
||||||
@@ -289,7 +387,7 @@ int thread_create(struct task_ids *ids, unsigned int flags)
|
|||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
/* Set up new thread's tid, spid, tgid according to flags */
|
/* 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. */
|
/* Initialise task's scheduling state and parameters. */
|
||||||
sched_init_task(new, TASK_PRIO_NORMAL);
|
sched_init_task(new, TASK_PRIO_NORMAL);
|
||||||
@@ -299,7 +397,7 @@ out:
|
|||||||
waitqueue_head_init(&new->wqh_recv);
|
waitqueue_head_init(&new->wqh_recv);
|
||||||
waitqueue_head_init(&new->wqh_pager);
|
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 to global hlist of tasks */
|
||||||
add_task_global(new);
|
add_task_global(new);
|
||||||
@@ -317,10 +415,11 @@ int sys_thread_control(syscall_context_t *regs)
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
unsigned int flags = regs->r0;
|
unsigned int flags = regs->r0;
|
||||||
struct task_ids *ids = (struct task_ids *)regs->r1;
|
struct task_ids *ids = (struct task_ids *)regs->r1;
|
||||||
|
unsigned long utcb_address = regs->r2;
|
||||||
|
|
||||||
switch (flags & THREAD_ACTION_MASK) {
|
switch (flags & THREAD_ACTION_MASK) {
|
||||||
case THREAD_CREATE:
|
case THREAD_CREATE:
|
||||||
ret = thread_create(ids, flags);
|
ret = thread_create(ids, flags, utcb_address);
|
||||||
break;
|
break;
|
||||||
case THREAD_RUN:
|
case THREAD_RUN:
|
||||||
ret = thread_start(ids);
|
ret = thread_start(ids);
|
||||||
|
|||||||
@@ -255,6 +255,9 @@ static inline void context_switch(struct ktcb *next)
|
|||||||
|
|
||||||
// printk("(%d) to (%d)\n", cur->tid, next->tid);
|
// 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 */
|
/* Flush caches and everything */
|
||||||
arch_hardware_flush(next->pgd);
|
arch_hardware_flush(next->pgd);
|
||||||
|
|
||||||
|
|||||||
23
tasks/fs0/container.c
Normal file
23
tasks/fs0/container.c
Normal 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();
|
||||||
|
}
|
||||||
|
|
||||||
@@ -32,6 +32,10 @@ SECTIONS
|
|||||||
.rodata1 : AT (ADDR(.rodata1) - offset) { *(.rodata1) }
|
.rodata1 : AT (ADDR(.rodata1) - offset) { *(.rodata1) }
|
||||||
.data : AT (ADDR(.data) - offset)
|
.data : AT (ADDR(.data) - offset)
|
||||||
{
|
{
|
||||||
|
. = ALIGN(4K); /* Align UTCB to page boundary */
|
||||||
|
_start_utcb = .;
|
||||||
|
*(.utcb)
|
||||||
|
_end_utcb = .;
|
||||||
. = ALIGN(4K);
|
. = ALIGN(4K);
|
||||||
_start_bdev = .;
|
_start_bdev = .;
|
||||||
*(.data.memfs)
|
*(.data.memfs)
|
||||||
@@ -39,5 +43,6 @@ SECTIONS
|
|||||||
*(.data)
|
*(.data)
|
||||||
}
|
}
|
||||||
.bss : AT (ADDR(.bss) - offset) { *(.bss) }
|
.bss : AT (ADDR(.bss) - offset) { *(.bss) }
|
||||||
|
|
||||||
_end = .;
|
_end = .;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include <l4/api/errno.h>
|
#include <l4/api/errno.h>
|
||||||
#include <l4lib/arch/syscalls.h>
|
#include <l4lib/arch/syscalls.h>
|
||||||
#include <l4lib/arch/syslib.h>
|
#include <l4lib/arch/syslib.h>
|
||||||
|
#include <l4lib/arch/utcb.h>
|
||||||
#include <l4lib/ipcdefs.h>
|
#include <l4lib/ipcdefs.h>
|
||||||
#include <lib/malloc.h>
|
#include <lib/malloc.h>
|
||||||
#include <lib/idpool.h>
|
#include <lib/idpool.h>
|
||||||
@@ -20,6 +21,7 @@
|
|||||||
#include <syscalls.h>
|
#include <syscalls.h>
|
||||||
#include <globals.h>
|
#include <globals.h>
|
||||||
|
|
||||||
|
|
||||||
extern void *shared_page;
|
extern void *shared_page;
|
||||||
|
|
||||||
struct global_list global_tasks = {
|
struct global_list global_tasks = {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#ifndef __ARM_SYSCALLS_H__
|
#ifndef __ARM_SYSCALLS_H__
|
||||||
#define __ARM_SYSCALLS_H__
|
#define __ARM_SYSCALLS_H__
|
||||||
|
|
||||||
|
|
||||||
#include <l4lib/arch/types.h>
|
#include <l4lib/arch/types.h>
|
||||||
#include <l4lib/arch/utcb.h>
|
#include <l4lib/arch/utcb.h>
|
||||||
#include <l4/generic/space.h>
|
#include <l4/generic/space.h>
|
||||||
@@ -14,6 +15,12 @@
|
|||||||
#include <l4/api/ipc.h>
|
#include <l4/api/ipc.h>
|
||||||
#include <l4/api/thread.h>
|
#include <l4/api/thread.h>
|
||||||
|
|
||||||
|
struct task_ids {
|
||||||
|
int tid;
|
||||||
|
int spid;
|
||||||
|
int tgid;
|
||||||
|
};
|
||||||
|
|
||||||
static inline void *
|
static inline void *
|
||||||
l4_kernel_interface(unsigned int *api_version, unsigned int *api_flags,
|
l4_kernel_interface(unsigned int *api_version, unsigned int *api_flags,
|
||||||
unsigned int *kernel_id)
|
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;
|
extern __l4_unmap_t __l4_unmap;
|
||||||
int l4_unmap(void *virtual, unsigned long numpages, l4id_t tid);
|
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;
|
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);
|
typedef int (*__l4_space_control_t)(unsigned int action, void *kdata);
|
||||||
extern __l4_space_control_t __l4_space_control;
|
extern __l4_space_control_t __l4_space_control;
|
||||||
|
|||||||
@@ -1,13 +1,8 @@
|
|||||||
#ifndef __L4_ARCH_ARM__
|
#ifndef __L4LIB_ARM_TYPES_H___
|
||||||
#define __L4_ARCH_ARM__
|
#define __L4LIB_ARM_TYPES_H__
|
||||||
|
|
||||||
#define TASK_ID_INVALID -1
|
#define TASK_ID_INVALID -1
|
||||||
struct task_ids {
|
|
||||||
int tid;
|
|
||||||
int spid;
|
|
||||||
int tgid;
|
|
||||||
};
|
|
||||||
|
|
||||||
#include <l4/arch/arm/types.h>
|
#include <l4/arch/arm/types.h>
|
||||||
|
|
||||||
#endif
|
#endif /* __L4LIB_ARM_TYPES_H__ */
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2009 Bahadir Bilgehan Balban
|
||||||
|
*/
|
||||||
#ifndef __ARM_UTCB_H__
|
#ifndef __ARM_UTCB_H__
|
||||||
#define __ARM_UTCB_H__
|
#define __ARM_UTCB_H__
|
||||||
|
|
||||||
#define USER_UTCB_REF 0xFF000FF0
|
#define USER_UTCB_REF 0xFF000050
|
||||||
#define L4_KIP_ADDRESS 0xFF000000
|
#define L4_KIP_ADDRESS 0xFF000000
|
||||||
#define UTCB_KIP_OFFSET 0xFF0
|
#define UTCB_KIP_OFFSET 0x50
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
#include <l4lib/types.h>
|
#include <l4lib/types.h>
|
||||||
@@ -13,27 +16,37 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* UTCB implementation */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NOTE: In syslib.h the first few mrs are used by data frequently
|
* 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
|
* 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 {
|
struct utcb {
|
||||||
u32 mr[MR_TOTAL];
|
u32 mr[MR_TOTAL]; /* MRs that are mapped to real registers */
|
||||||
u32 saved_tag;
|
u32 saved_tag; /* Saved tag field for stacked ipcs */
|
||||||
u32 saved_sender;
|
u32 saved_sender; /* Saved sender field for stacked ipcs */
|
||||||
} __attribute__((__packed__));
|
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()
|
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 */
|
/* Functions to read/write utcb registers */
|
||||||
|
|||||||
@@ -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_mr(struct exregs_data *s, int offset, unsigned long val);
|
||||||
void exregs_set_pc(struct exregs_data *s, unsigned long pc);
|
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_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)
|
exregs_set_stack(unsigned long sp)
|
||||||
|
|||||||
6
tasks/libl4/include/l4lib/init.h
Normal file
6
tasks/libl4/include/l4lib/init.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef __L4LIB_INIT__
|
||||||
|
#define __L4LIB_INIT__
|
||||||
|
|
||||||
|
void __l4_init(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
14
tasks/libl4/include/l4lib/thread.h
Normal file
14
tasks/libl4/include/l4lib/thread.h
Normal 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__ */
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
#include INC_GLUE(message.h)
|
#include INC_GLUE(message.h)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void exregs_set_mr(struct exregs_data *s, int offset, unsigned long val)
|
void exregs_set_mr(struct exregs_data *s, int offset, unsigned long val)
|
||||||
{
|
{
|
||||||
/* Get MR0 */
|
/* Get MR0 */
|
||||||
@@ -30,6 +31,14 @@ void exregs_set_pager(struct exregs_data *s, l4id_t pagerid)
|
|||||||
s->flags |= EXREGS_SET_PAGER;
|
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)
|
void exregs_set_stack(struct exregs_data *s, unsigned long sp)
|
||||||
{
|
{
|
||||||
s->context.sp = sp;
|
s->context.sp = sp;
|
||||||
|
|||||||
@@ -9,9 +9,18 @@
|
|||||||
#include <l4/macros.h>
|
#include <l4/macros.h>
|
||||||
#include INC_GLUE(message.h)
|
#include INC_GLUE(message.h)
|
||||||
|
|
||||||
|
/* Old macro */
|
||||||
|
#if 0
|
||||||
.macro utcb_address rx
|
.macro utcb_address rx
|
||||||
ldr \rx, =utcb
|
ldr \rx, =utcb
|
||||||
.endm
|
.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)
|
BEGIN_PROC(l4_thread_switch)
|
||||||
ldr r12, =__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.
|
* 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)
|
BEGIN_PROC(l4_thread_control)
|
||||||
stmfd sp!, {lr}
|
stmfd sp!, {lr}
|
||||||
|
|||||||
@@ -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/kip.h>
|
||||||
#include <l4lib/arch/syslib.h>
|
#include <l4lib/arch/syslib.h>
|
||||||
@@ -27,16 +27,20 @@ __l4_time_t __l4_time = 0;
|
|||||||
struct kip *kip;
|
struct kip *kip;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Private UTCB of this task. Used only for pushing/reading ipc
|
* Reference to private UTCB of this thread.
|
||||||
* message registers.
|
* Used only for pushing/reading ipc message registers.
|
||||||
*/
|
*/
|
||||||
struct utcb utcb;
|
struct utcb **kip_utcb_ref;
|
||||||
|
|
||||||
|
|
||||||
void __l4_init(void)
|
void __l4_init(void)
|
||||||
{
|
{
|
||||||
|
/* Kernel interface page */
|
||||||
kip = l4_kernel_interface(0, 0, 0);
|
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_ipc = (__l4_ipc_t)kip->ipc;
|
||||||
__l4_map = (__l4_map_t)kip->map;
|
__l4_map = (__l4_map_t)kip->map;
|
||||||
__l4_unmap = (__l4_unmap_t)kip->unmap;
|
__l4_unmap = (__l4_unmap_t)kip->unmap;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
#include <l4lib/utcb.h>
|
#include <l4lib/utcb.h>
|
||||||
#include <l4/macros.h>
|
#include <l4/macros.h>
|
||||||
#include INC_GLUE(memory.h)
|
#include INC_GLUE(memory.h)
|
||||||
#include <posix_init.h>
|
#include <shpage.h>
|
||||||
|
|
||||||
static inline int l4_fork(void)
|
static inline int l4_fork(void)
|
||||||
{
|
{
|
||||||
@@ -43,10 +43,10 @@ int fork(void)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* If we're a child, we need to initialise the default
|
* If we're a child, we need to initialise the default
|
||||||
* shared page via posix_init()
|
* shared page via libposix_init()
|
||||||
*/
|
*/
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
posix_init();
|
shared_page_init();
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#ifndef __POSIX_INIT_H__
|
#ifndef __LIBPOSIX_INIT_H__
|
||||||
#define __POSIX_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__ */
|
||||||
|
|||||||
@@ -3,28 +3,20 @@
|
|||||||
*
|
*
|
||||||
* Copyright (C) 2007-2009 Bahadir Balban
|
* Copyright (C) 2007-2009 Bahadir Balban
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <shpage.h>
|
#include <shpage.h>
|
||||||
#include <posix_init.h>
|
#include <posix_init.h>
|
||||||
|
|
||||||
void posix_init(void)
|
void posix_service_init(void)
|
||||||
{
|
{
|
||||||
/* Non-pager tasks initialise their shared communication page */
|
/* Non-pager tasks initialise their shared communication page */
|
||||||
if (self_tid() != PAGER_TID)
|
BUG_ON(self_tid() != VFS_TID);
|
||||||
shared_page_init();
|
shared_page_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void);
|
void libposix_init(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)
|
|
||||||
{
|
{
|
||||||
posix_init();
|
/* Shall only be run by posix applications */
|
||||||
main();
|
BUG_ON(self_tid() == PAGER_TID || self_tid() == VFS_TID);
|
||||||
|
shared_page_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
28
tasks/mm0/container.c
Normal file
28
tasks/mm0/container.c
Normal 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();
|
||||||
|
}
|
||||||
|
|
||||||
@@ -29,7 +29,11 @@ SECTIONS
|
|||||||
/* rodata is needed else your strings will link at physical! */
|
/* rodata is needed else your strings will link at physical! */
|
||||||
.rodata : AT (ADDR(.rodata) - offset) { *(.rodata) }
|
.rodata : AT (ADDR(.rodata) - offset) { *(.rodata) }
|
||||||
.rodata1 : AT (ADDR(.rodata1) - offset) { *(.rodata1) }
|
.rodata1 : AT (ADDR(.rodata1) - offset) { *(.rodata1) }
|
||||||
.data : AT (ADDR(.data) - offset) { *(.data) }
|
.data : AT (ADDR(.data) - offset)
|
||||||
|
{
|
||||||
|
*(.data)
|
||||||
|
}
|
||||||
|
. = ALIGN(4K);
|
||||||
_start_init = .;
|
_start_init = .;
|
||||||
.init : AT (ADDR(.init) - offset) { *(.init.stack) }
|
.init : AT (ADDR(.init) - offset) { *(.init.stack) }
|
||||||
. = ALIGN(8);
|
. = ALIGN(8);
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include INC_GLUE(memlayout.h)
|
#include INC_GLUE(memlayout.h)
|
||||||
#include <l4/lib/list.h>
|
#include <l4/lib/list.h>
|
||||||
#include <l4lib/arch/types.h>
|
#include <l4lib/arch/types.h>
|
||||||
|
#include <l4lib/arch/syscalls.h>
|
||||||
#include <l4lib/utcb.h>
|
#include <l4lib/utcb.h>
|
||||||
#include <lib/addr.h>
|
#include <lib/addr.h>
|
||||||
#include <l4/api/kip.h>
|
#include <l4/api/kip.h>
|
||||||
@@ -53,6 +54,20 @@ struct task_vma_head {
|
|||||||
int tcb_refs;
|
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. */
|
/* Stores all task information that can be kept in userspace. */
|
||||||
struct tcb {
|
struct tcb {
|
||||||
@@ -104,6 +119,9 @@ struct tcb {
|
|||||||
/* Default ipc-shared-page information */
|
/* Default ipc-shared-page information */
|
||||||
void *shared_page;
|
void *shared_page;
|
||||||
|
|
||||||
|
/* Task's utcb data */
|
||||||
|
struct utcb_data *utcb;
|
||||||
|
|
||||||
/* Virtual memory areas */
|
/* Virtual memory areas */
|
||||||
struct task_vma_head *vm_area_head;
|
struct task_vma_head *vm_area_head;
|
||||||
|
|
||||||
|
|||||||
@@ -7,10 +7,10 @@
|
|||||||
#define __VM_AREA_H__
|
#define __VM_AREA_H__
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <task.h>
|
|
||||||
#include <l4/macros.h>
|
#include <l4/macros.h>
|
||||||
#include <l4/config.h>
|
#include <l4/config.h>
|
||||||
#include <l4/types.h>
|
#include <l4/types.h>
|
||||||
|
#include <task.h>
|
||||||
#include <arch/mm.h>
|
#include <arch/mm.h>
|
||||||
#include <lib/spinlock.h>
|
#include <lib/spinlock.h>
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include <test.h>
|
#include <test.h>
|
||||||
#include <boot.h>
|
#include <boot.h>
|
||||||
|
|
||||||
|
|
||||||
/* A separate list than the generic file list that keeps just the boot files */
|
/* A separate list than the generic file list that keeps just the boot files */
|
||||||
LIST_HEAD(boot_file_list);
|
LIST_HEAD(boot_file_list);
|
||||||
|
|
||||||
|
|||||||
27
tasks/mm0/src/utcb.c
Normal file
27
tasks/mm0/src/utcb.c
Normal 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ env = Environment(CC = 'arm-none-linux-gnueabi-gcc',
|
|||||||
CPPFLAGS = "-D__USERSPACE__",
|
CPPFLAGS = "-D__USERSPACE__",
|
||||||
CPPPATH = ['#include', libl4_incpath, libposix_incpath, kernel_incpath])
|
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)
|
objs = env.Object(src)
|
||||||
physical_base = env.Command(physical_base_ld_script, prev_image, get_physical_base)
|
physical_base = env.Command(physical_base_ld_script, prev_image, get_physical_base)
|
||||||
crt0_copied = env.Command("crt0.o", libc_crt0, copy_crt0)
|
crt0_copied = env.Command("crt0.o", libc_crt0, copy_crt0)
|
||||||
|
|||||||
25
tasks/test0/container.c
Normal file
25
tasks/test0/container.c
Normal 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();
|
||||||
|
}
|
||||||
|
|
||||||
@@ -30,10 +30,9 @@ SECTIONS
|
|||||||
/* rodata is needed else your strings will link at physical! */
|
/* rodata is needed else your strings will link at physical! */
|
||||||
.rodata : AT (ADDR(.rodata) - offset) { *(.rodata) }
|
.rodata : AT (ADDR(.rodata) - offset) { *(.rodata) }
|
||||||
.rodata1 : AT (ADDR(.rodata1) - offset) { *(.rodata1) }
|
.rodata1 : AT (ADDR(.rodata1) - offset) { *(.rodata1) }
|
||||||
|
|
||||||
. = ALIGN(4K);
|
|
||||||
.data : AT (ADDR(.data) - offset)
|
.data : AT (ADDR(.data) - offset)
|
||||||
{
|
{
|
||||||
|
. = ALIGN(4K);
|
||||||
_start_test1 = .;
|
_start_test1 = .;
|
||||||
*(.test1)
|
*(.test1)
|
||||||
_end_test1 = .;
|
_end_test1 = .;
|
||||||
|
|||||||
Reference in New Issue
Block a user