1. Old pending files cleaned from public repo. 2. Thread_create routines removed from timer_service and kmi_service. 3. Sconstruct of libdev updated.

This commit is contained in:
Amit Mahajan
2010-03-30 14:44:05 +05:30
parent 92645be6ff
commit 2b340c9f2f
86 changed files with 27 additions and 7113 deletions

View File

@@ -1,67 +0,0 @@
# -*- mode: python; coding: utf-8; -*-
#
# Codezero -- Virtualization microkernel for embedded systems.
#
# Copyright © 2009 B Labs Ltd
#
import os, shelve, sys
from os.path import *
PROJRELROOT = '../..'
sys.path.append(PROJRELROOT)
from config.projpaths import *
from config.configuration import *
config = configuration_retrieve()
platform = config.platform
arch = config.arch
gcc_cpu_flag = config.gcc_cpu_flag
LIBL4_RELDIR = 'conts/libl4'
KERNEL_INCLUDE = join(PROJROOT, 'include')
LIBL4_DIR = join(PROJROOT, LIBL4_RELDIR)
LIBL4_INCLUDE = join(LIBL4_DIR, 'include')
LIBL4_LIBPATH = join(BUILDDIR, LIBL4_RELDIR)
# Locally important paths are here
LIBC_RELDIR = 'conts/libc'
LIBC_DIR = join(PROJROOT, LIBC_RELDIR)
LIBC_LIBPATH = join(BUILDDIR, LIBC_RELDIR)
LIBC_INCLUDE = [join(LIBC_DIR, 'include'), \
join(LIBC_DIR, 'include/arch' + '/' + arch)]
LIBDEV_RELDIR = 'conts/libdev'
LIBDEV_DIR = join(PROJROOT, LIBDEV_RELDIR)
LIBDEV_LIBPATH = join(join(BUILDDIR, LIBDEV_RELDIR), 'sys-userspace')
LIBDEV_INCLUDE = [join(LIBDEV_DIR, 'uart/include'),
join(LIBDEV_DIR, 'clcd/pl110/include')]
LIBDEV_CCFLAGS = '-DPLATFORM_' + platform.upper()
# FIXME: Add these to autogenerated SConstruct !!!
LIBMEM_RELDIR = 'conts/libmem'
LIBMEM_DIR = join(PROJROOT, LIBMEM_RELDIR)
LIBMEM_LIBPATH = join(BUILDDIR, LIBMEM_RELDIR)
LIBMEM_INCLUDE = LIBMEM_DIR
env = Environment(CC = config.user_toolchain + 'gcc',
# We don't use -nostdinc because sometimes we need standard headers,
# such as stdarg.h e.g. for variable args, as in printk().
CCFLAGS = ['-g', '-nostdlib', '-ffreestanding', '-std=gnu99', '-Wall', \
'-Werror', ('-mcpu=' + gcc_cpu_flag), LIBDEV_CCFLAGS],
LINKFLAGS = ['-nostdlib', '-T' + "include/linker.lds", "-u_start"],
ASFLAGS = ['-D__ASSEMBLY__'], \
PROGSUFFIX = '.elf', # The suffix to use for final executable\
ENV = {'PATH' : os.environ['PATH']}, # Inherit shell path\
LIBS = ['gcc', 'libl4', 'libmalloc', 'c-userspace', 'libdev-userspace', 'gcc', 'c-userspace'], # libgcc.a - This is required for division routines.
CPPPATH = ["#include", KERNEL_INCLUDE, LIBL4_INCLUDE, LIBDEV_INCLUDE, LIBC_INCLUDE, LIBMEM_INCLUDE],
LIBPATH = [LIBL4_LIBPATH, LIBDEV_LIBPATH, LIBC_LIBPATH, LIBMEM_LIBPATH],
CPPFLAGS = '-include l4/config.h -include l4/macros.h -include l4/types.h')
src = Glob('*.[cS]')
src += Glob('src/*.[cS]')
objs = env.Object(src)
prog = env.Program('main.elf', objs)
Depends(prog, 'include/linker.lds')

View File

@@ -1,21 +0,0 @@
/*
* Container entry point for pager
*
* Copyright (C) 2007-2009 B Labs Ltd.
*/
#include <l4lib/init.h>
#include <l4lib/utcb.h>
extern void main(void);
void __container_init(void)
{
/* Generic L4 initialisation */
__l4_init();
/* Entry to main */
main();
}

View File

@@ -1,13 +0,0 @@
/*
* Autogenerated definitions for this container.
*/
#ifndef __CONTAINER_H__
#define __CONTAINER_H__
#define __CONTAINER_NAME__ "uart_service"
#define __CONTAINER_ID__ 0
#define __CONTAINER__ "cont0"
#endif /* __CONTAINER_H__ */

View File

@@ -1,7 +0,0 @@
#ifndef __LINKER_H__
#define __LINKER_H__
extern char vma_start[];
extern char __end[];
#endif /* __LINKER_H__ */

View File

@@ -1,277 +0,0 @@
/*
* CLCD service for userspace
*/
#include <l4lib/arch/syslib.h>
#include <l4lib/arch/syscalls.h>
#include <l4lib/addr.h>
#include <l4lib/exregs.h>
#include <l4lib/ipcdefs.h>
#include <l4/api/errno.h>
#include <l4/api/space.h>
#include <l4lib/capability/cap_print.h>
#include <container.h>
#include <pl110_clcd.h> /* FIXME: Its best if this is <libdev/uart/pl011.h> */
#include <linker.h>
#define CLCD_TOTAL 1
static struct capability caparray[32];
static int total_caps = 0;
struct capability clcd_cap[CLCD_TOTAL];
int cap_read_all()
{
int ncaps;
int err;
/* Read number of capabilities */
if ((err = l4_capability_control(CAP_CONTROL_NCAPS,
0, &ncaps)) < 0) {
printf("l4_capability_control() reading # of"
" capabilities failed.\n Could not "
"complete CAP_CONTROL_NCAPS request.\n");
BUG();
}
total_caps = ncaps;
/* Read all capabilities */
if ((err = l4_capability_control(CAP_CONTROL_READ,
0, caparray)) < 0) {
printf("l4_capability_control() reading of "
"capabilities failed.\n Could not "
"complete CAP_CONTROL_READ_CAPS request.\n");
BUG();
}
return 0;
}
/*
* Scans for up to CLCD_TOTAL clcd devices in capabilities.
*/
int clcd_probe_devices(void)
{
int clcds = 0;
/* Scan for clcd devices */
for (int i = 0; i < total_caps; i++) {
/* Match device type */
if (cap_devtype(&caparray[i]) == CAP_DEVTYPE_CLCD) {
/* Copy to correct device index */
memcpy(&clcd_cap[cap_devnum(&caparray[i])],
&caparray[i], sizeof(clcd_cap[0]));
clcds++;
}
}
if (clcds != CLCD_TOTAL) {
printf("%s: Error, not all clcd could be found. "
"total clcds=%d\n", __CONTAINER_NAME__, clcds);
return -ENODEV;
}
return 0;
}
/*
* 1MB frame buffer,
* FIXME: can we do dma in this buffer?
*/
#define CLCD_FRAMEBUFFER_SZ 0x100000
static char framebuffer[CLCD_FRAMEBUFFER_SZ];
static struct pl110_clcd clcd[CLCD_TOTAL];
int clcd_setup_devices(void)
{
for (int i = 0; i < CLCD_TOTAL; i++) {
/* Get one page from address pool */
clcd[i].virt_base = (unsigned long)l4_new_virtual(1);
/* Map clcd to a virtual address region */
if (IS_ERR(l4_map((void *)__pfn_to_addr(clcd_cap[i].start),
(void *)clcd[i].virt_base, clcd_cap[i].size,
MAP_USR_IO_FLAGS,
self_tid()))) {
printf("%s: FATAL: Failed to map CLCD device "
"%d to a virtual address\n",
__CONTAINER_NAME__,
cap_devnum(&clcd_cap[i]));
BUG();
}
/* Initialize clcd */
pl110_initialise(&clcd[i], framebuffer);
}
return 0;
}
static struct address_pool device_vaddr_pool;
/*
* Initialize a virtual address pool
* for mapping physical devices.
*/
void init_vaddr_pool(void)
{
for (int i = 0; i < total_caps; i++) {
/* Find the virtual memory region for this process */
if (cap_type(&caparray[i]) == CAP_TYPE_MAP_VIRTMEM &&
__pfn_to_addr(caparray[i].start) ==
(unsigned long)vma_start) {
/*
* Do we have any unused virtual space
* where we run, and do we have enough
* pages of it to map all clcd?
*/
if (__pfn(page_align_up(__end))
+ CLCD_TOTAL <= caparray[i].end) {
/*
* Yes. We initialize the device
* virtual memory pool here.
*
* We may allocate virtual memory
* addresses from this pool.
*/
address_pool_init(&device_vaddr_pool,
page_align_up(__end),
__pfn_to_addr(caparray[i].end),
CLCD_TOTAL);
return;
} else
goto out_err;
}
}
out_err:
printf("%s: FATAL: No virtual memory "
"region available to map "
"devices.\n", __CONTAINER_NAME__);
BUG();
}
void *l4_new_virtual(int npages)
{
return address_new(&device_vaddr_pool, npages, PAGE_SIZE);
}
void handle_requests(void)
{
u32 mr[MR_UNUSED_TOTAL];
l4id_t senderid;
u32 tag;
int ret;
printf("%s: Initiating ipc.\n", __CONTAINER__);
if ((ret = l4_receive(L4_ANYTHREAD)) < 0) {
printf("%s: %s: IPC Error: %d. Quitting...\n",
__CONTAINER__, __FUNCTION__, ret);
BUG();
}
/* Syslib conventional ipc data which uses first few mrs. */
tag = l4_get_tag();
senderid = l4_get_sender();
/* Read mrs not used by syslib */
for (int i = 0; i < MR_UNUSED_TOTAL; i++)
mr[i] = read_mr(MR_UNUSED_START + i);
/*
* TODO:
*
* Maybe add tags here that handle requests for sharing
* of the requested cld device with the client?
*
* In order to be able to do that, we should have a
* shareable/grantable capability to the device. Also
* the request should (currently) come from a task
* inside the current container
*/
/*
* FIXME: Right now we are talking to CLCD by default, we need to define protocol
* for sommunication with CLCD service
*/
switch (tag) {
default:
printf("%s: Error received ipc from 0x%x residing "
"in container %x with an unrecognized tag: "
"0x%x\n", __CONTAINER__, senderid,
__cid(senderid), tag);
}
/* Reply */
if ((ret = l4_ipc_return(ret)) < 0) {
printf("%s: IPC return error: %d.\n", __FUNCTION__, ret);
BUG();
}
}
/*
* UTCB-size aligned utcb.
*
* BIG WARNING NOTE:
* This in-place declaration is legal if we are running
* in a disjoint virtual address space, where the utcb
* declaration lies in a unique virtual address in
* the system.
*/
#define DECLARE_UTCB(name) \
struct utcb name ALIGN(sizeof(struct utcb))
DECLARE_UTCB(utcb);
/* Set up own utcb for ipc */
int l4_utcb_setup(void *utcb_address)
{
struct task_ids ids;
struct exregs_data exregs;
int err;
l4_getid(&ids);
/* Clear utcb */
memset(utcb_address, 0, sizeof(struct utcb));
/* Setup exregs for utcb request */
memset(&exregs, 0, sizeof(exregs));
exregs_set_utcb(&exregs, (unsigned long)utcb_address);
if ((err = l4_exchange_registers(&exregs, ids.tid)) < 0)
return err;
return 0;
}
void main(void)
{
int err;
/* Read all capabilities */
cap_read_all();
/* Scan for clcd devices in capabilities */
clcd_probe_devices();
/* Initialize virtual address pool for clcds */
init_vaddr_pool();
/* Map and initialize clcd devices */
clcd_setup_devices();
/* Setup own utcb */
if ((err = l4_utcb_setup(&utcb)) < 0) {
printf("FATAL: Could not set up own utcb. "
"err=%d\n", err);
BUG();
}
/* Listen for clcd requests */
while (1)
handle_requests();
}

View File

@@ -6,7 +6,7 @@
#include <l4lib/init.h>
#include <l4lib/utcb.h>
#include <l4lib/lib/thread.h>
void main(void);
@@ -15,6 +15,9 @@ void __container_init(void)
/* Generic L4 initialisation */
__l4_init();
/* Thread library initialisation */
__l4_threadlib_init();
/* Entry to main */
main();
}

View File

@@ -4,10 +4,6 @@
#ifndef __MOUSE_H__
#define __MOUSE_H__
#include <l4lib/mutex.h>
#include <l4/lib/list.h>
#include <l4lib/types.h>
/*
* Keyboard structure
*/

View File

@@ -1,19 +0,0 @@
#ifndef __THREAD_H__
#define __THREAD_H__
#include <l4lib/macros.h>
#include L4LIB_INC_ARCH(syslib.h)
#include L4LIB_INC_ARCH(syscalls.h)
#include <l4lib/exregs.h>
#include <l4/api/thread.h>
int thread_create(int (*func)(void *), void *args, unsigned int flags,
struct task_ids *new_ids);
/* For same space */
#define STACK_SIZE 0x1000
#define THREADS_TOTAL 10
#endif /* __THREAD_H__ */

View File

@@ -2,6 +2,7 @@
* Keyboard and Mouse service for userspace
*/
#include <l4lib/lib/addr.h>
#include <l4lib/lib/thread.h>
#include <l4lib/irq.h>
#include <l4lib/ipcdefs.h>
#include <l4/api/errno.h>
@@ -14,7 +15,6 @@
#include <linker.h>
#include <keyboard.h>
#include <mouse.h>
#include <thread.h>
#define KEYBOARDS_TOTAL 1
#define MOUSE_TOTAL 1
@@ -179,7 +179,8 @@ int mouse_irq_handler(void *arg)
int kmi_setup_devices(void)
{
struct task_ids irq_tids;
struct l4_thread thread;
struct l4_thread *tptr = &thread;
int err;
for (int i = 0; i < KEYBOARDS_TOTAL; i++) {
@@ -209,7 +210,7 @@ int kmi_setup_devices(void)
*/
if ((err = thread_create(keyboard_irq_handler, &kbd[i],
TC_SHARE_SPACE,
&irq_tids)) < 0) {
&tptr)) < 0) {
printf("FATAL: Creation of irq handler "
"thread failed.\n");
BUG();
@@ -238,7 +239,7 @@ int kmi_setup_devices(void)
* wait on irqs.
*/
if ((err = thread_create(mouse_irq_handler, &mouse[i],
TC_SHARE_SPACE, &irq_tids)) < 0) {
TC_SHARE_SPACE, &tptr)) < 0) {
printf("FATAL: Creation of irq handler "
"thread failed.\n");
BUG();

View File

@@ -1,11 +0,0 @@
#include <l4lib/macros.h>
#include L4LIB_INC_ARCH(asm.h)
BEGIN_PROC(local_setup_new_thread)
ldr r0, [sp, #-4]! @ Load first argument.
mov lr, pc @ Save return address
ldr pc, [sp, #-4]! @ Load function pointer from stack
new_thread_exit:
b new_thread_exit @ We infinitely loop for now.
END_PROC(local_setup_new_thread)

View File

@@ -1,73 +0,0 @@
/*
* Thread creation userspace helpers
*
* Copyright (C) 2009 B Labs Ltd.
*/
#include <thread.h>
#include <l4/api/errno.h>
char stack[THREADS_TOTAL][STACK_SIZE] ALIGN(8);
char *__stack_ptr = &stack[1][0];
char utcb[THREADS_TOTAL][UTCB_SIZE] ALIGN(8);
char *__utcb_ptr = &utcb[1][0];
extern void local_setup_new_thread(void);
int thread_create(int (*func)(void *), void *args, unsigned int flags,
struct task_ids *new_ids)
{
struct task_ids ids;
struct exregs_data exregs;
int err;
l4_getid(&ids);
/* Shared space only */
if (!(TC_SHARE_SPACE & flags)) {
printf("%s: This function allows only "
"shared space thread creation.\n",
__FUNCTION__);
return -EINVAL;
}
/* Create thread */
if ((err = l4_thread_control(THREAD_CREATE | flags, &ids)) < 0)
return err;
/* Check if more stack/utcb available */
if ((unsigned long)__utcb_ptr ==
(unsigned long)&utcb[THREADS_TOTAL][0])
return -ENOMEM;
if ((unsigned long)__stack_ptr ==
(unsigned long)&stack[THREADS_TOTAL][0])
return -ENOMEM;
/* First word of new stack is arg */
((unsigned long *)__stack_ptr)[-1] = (unsigned long)args;
/* Second word of new stack is function address */
((unsigned long *)__stack_ptr)[-2] = (unsigned long)func;
/* Setup new thread pc, sp, utcb */
memset(&exregs, 0, sizeof(exregs));
exregs_set_stack(&exregs, (unsigned long)__stack_ptr);
exregs_set_utcb(&exregs, (unsigned long)__utcb_ptr);
exregs_set_pc(&exregs, (unsigned long)local_setup_new_thread);
if ((err = l4_exchange_registers(&exregs, ids.tid)) < 0)
return err;
/* Update utcb, stack pointers */
__stack_ptr += STACK_SIZE;
__utcb_ptr += UTCB_SIZE;
/* Start the new thread */
if ((err = l4_thread_control(THREAD_RUN, &ids)) < 0)
return err;
memcpy(new_ids, &ids, sizeof(ids));
return 0;
}

View File

@@ -1,68 +0,0 @@
# -*- mode: python; coding: utf-8; -*-
#
# Codezero -- Virtualization microkernel for embedded systems.
#
# Copyright © 2009 B Labs Ltd
#
import os, shelve, sys
from os.path import *
PROJRELROOT = '../..'
sys.path.append(PROJRELROOT)
from config.projpaths import *
from config.configuration import *
from config.lib import *
config = configuration_retrieve()
arch = config.arch
platform = config.platform
gcc_cpu_flag = config.gcc_cpu_flag
LIBL4_RELDIR = 'conts/libl4'
KERNEL_INCLUDE = join(PROJROOT, 'include')
LIBL4_DIR = join(PROJROOT, LIBL4_RELDIR)
LIBL4_INCLUDE = join(LIBL4_DIR, 'include')
LIBL4_LIBPATH = join(BUILDDIR, LIBL4_RELDIR)
# Locally important paths are here
LIBC_RELDIR = 'conts/libc'
LIBC_DIR = join(PROJROOT, LIBC_RELDIR)
LIBC_LIBPATH = join(BUILDDIR, LIBC_RELDIR)
LIBC_INCLUDE = [join(LIBC_DIR, 'include'), \
join(LIBC_DIR, 'include/arch' + '/' + arch)]
LIBDEV_RELDIR = 'conts/libdev'
LIBDEV_DIR = join(PROJROOT, LIBDEV_RELDIR)
LIBDEV_LIBPATH = join(join(BUILDDIR, LIBDEV_RELDIR), 'sys-userspace')
LIBDEV_INCLUDE = [join(LIBDEV_DIR, 'uart/include')]
LIBDEV_CCFLAGS = '-DPLATFORM_' + platform.upper()
LIBMEM_RELDIR = 'conts/libmem'
LIBMEM_DIR = join(PROJROOT, LIBMEM_RELDIR)
LIBMEM_LIBPATH = join(BUILDDIR, LIBMEM_RELDIR)
LIBMEM_INCLUDE = LIBMEM_DIR
env = Environment(CC = config.user_toolchain + 'gcc',
# We don't use -nostdinc because sometimes we need standard headers,
# such as stdarg.h e.g. for variable args, as in printk().
CCFLAGS = ['-g', '-nostdlib', '-ffreestanding', '-std=gnu99', '-Wall', \
'-Werror', ('-mcpu=' + gcc_cpu_flag), LIBDEV_CCFLAGS],
LINKFLAGS = ['-nostdlib', '-T' + "include/linker.lds", "-u_start"],\
ASFLAGS = ['-D__ASSEMBLY__'], \
PROGSUFFIX = '.elf', # The suffix to use for final executable\
ENV = {'PATH' : os.environ['PATH']}, # Inherit shell path\
LIBS = ['gcc', 'libl4', 'c-userspace', 'libdev-userspace', 'gcc', 'libmalloc',
'c-userspace'], # libgcc.a - This is required for division routines.
CPPPATH = ["#include", KERNEL_INCLUDE, LIBL4_INCLUDE, LIBDEV_INCLUDE, LIBC_INCLUDE, LIBMEM_INCLUDE],
LIBPATH = [LIBL4_LIBPATH, LIBDEV_LIBPATH, LIBC_LIBPATH, LIBMEM_LIBPATH],
CPPFLAGS = '-include l4/config.h -include l4/macros.h -include l4/types.h')
src = Glob('*.[cS]')
src += Glob('src/*.[cS]')
src += Glob('src/arch/*.[cS]')
objs = env.Object(src)
prog = env.Program('main.elf', objs)
Depends(prog, 'include/linker.lds')

View File

@@ -1,21 +0,0 @@
/*
* Container entry point for pager
*
* Copyright (C) 2007-2009 B Labs Ltd.
*/
#include <l4lib/init.h>
#include <l4lib/utcb.h>
extern void main(void);
void __container_init(void)
{
/* Generic L4 initialisation */
__l4_init();
/* Entry to main */
main();
}

View File

@@ -1,6 +0,0 @@
#ifndef __CAPABILITY_H__
#define __CAPABILITY_H__
int caps_read_all();
#endif /* __CAPABILITY_H__ */

View File

@@ -1,7 +0,0 @@
#ifndef __TESTS_H__
#define __TESTS_H__
int capability_test(void);
#endif /* __TESTS_H__ */

View File

@@ -1,18 +0,0 @@
#ifndef __THREAD_H__
#define __THREAD_H__
#include <l4lib/arch/syslib.h>
#include <l4lib/arch/syscalls.h>
#include <l4lib/exregs.h>
#include <l4/api/thread.h>
int thread_create(int (*func)(void *), void *args, unsigned int flags,
struct task_ids *new_ids);
/* For same space */
#define STACK_SIZE 0x1000
#define THREADS_TOTAL 10
#endif /* __THREAD_H__ */

View File

@@ -1,80 +0,0 @@
/*
* Main function for all tests
*
* Copyright (C) 2009 B Labs Ltd.
*/
#include <l4/api/errno.h>
#include <container.h>
#include <thread.h>
#include <tests.h>
#include <l4lib/arch/syslib.h>
#include <l4lib/arch/syscalls.h>
#include <l4/api/space.h>
int exit_test_thread(void *arg)
{
while (1)
;
//l4_thread_switch(0);
//l4_exit(5);
return 0;
}
int exit_test(void)
{
int ret;
struct task_ids ids;
/* Create and run a new thread */
if ((ret = thread_create(exit_test_thread, 0,
TC_SHARE_SPACE | TC_AS_PAGER,
&ids)) < 0) {
printf("Top-level simple_pager creation failed.\n");
goto out_err;
} else
printf("Thread (%d) created successfully.\n", ids.tid);
// l4_thread_switch(0);
/* Kill it */
printf("Killing Thread (%d).\n", ids.tid);
if ((ret = l4_thread_control(THREAD_DESTROY, &ids)) < 0)
printf("Error: Killing Thread (%d), err = %d\n", ids.tid, ret);
else
printf("Success: Killed Thread (%d)\n", ids.tid);
#if 0
/* Wait on it */
printf("Waiting on Thread (%d) to exit.\n", ids.tid);
if ((ret = l4_thread_control(THREAD_WAIT, &ids)) >= 0)
printf("Success. Paged child returned %d\n", ret);
else
printf("Error. Wait on (%d) failed. err = %d\n",
ids.tid, ret);
#endif
return 0;
out_err:
BUG();
}
int main(void)
{
printf("%s: Container %s started\n",
__CONTAINER__, __CONTAINER_NAME__);
capability_test();
//exit_test();
/* Now quit to demo self-paging quit */
//l4_exit(0);
/* Now quit by null pointer */
// *((int *)0) = 5;
return 0;
}

View File

@@ -1 +0,0 @@
arch-arm

View File

@@ -1,11 +0,0 @@
#include <l4lib/arch/asm.h>
BEGIN_PROC(local_setup_new_thread)
ldr r0, [sp, #-4]! @ Load first argument.
mov lr, pc @ Save return address
ldr pc, [sp, #-4]! @ Load function pointer from stack
new_thread_exit:
b new_thread_exit @ We infinitely loop for now.
END_PROC(local_setup_new_thread)

View File

@@ -1,105 +0,0 @@
/*
* Capability-related userspace helpers
*
* Copyright (C) 2009 B Labs Ltd.
*/
#include <stdio.h>
#include <l4lib/capability/cap_print.h>
#include <l4lib/arch/syscalls.h>
static struct capability cap_array[30];
#if 0
struct cap_group {
struct cap_list virtmem;
struct cap_list physmem;
struct cap_list threadpool;
struct cap_list tctrl;
struct cap_list exregs;
struct cap_list ipc;
struct cap_list mutex;
struct cap_list sched;
struct cap_list mutexpool;
struct cap_list spacepool;
struct cap_list cappool;
};
static inline struct capability *cap_get_thread()
{
}
static inline struct capability *cap_get_space()
{
}
static inline struct capability *cap_get_ipc()
{
}
static inline struct capability *cap_get_virtmem()
{
}
static inline struct capability *cap_get_physmem()
{
}
static inline struct capability *cap_get_physmem(unsigned long phys)
{
}
static inline struct capability *cap_get_virtmem(unsigned long virt)
{
}
static inline struct capability *cap_get_byid(l4id_t id)
{
}
void cap_share_single(struct capability *orig, struct capability *share, l4id_t target, unsigned int flags)
{
}
void cap_grant_single(struct capability *orig, struct capability *share, l4id_t target, unsigned int flags)
{
}
#endif
int caps_read_all(void)
{
int ncaps;
int err;
/* Read number of capabilities */
if ((err = l4_capability_control(CAP_CONTROL_NCAPS,
0, &ncaps)) < 0) {
printf("l4_capability_control() reading # of"
" capabilities failed.\n Could not "
"complete CAP_CONTROL_NCAPS request.\n");
BUG();
}
/* Read all capabilities */
if ((err = l4_capability_control(CAP_CONTROL_READ,
0, cap_array)) < 0) {
printf("l4_capability resource_control() reading of "
"capabilities failed.\n Could not "
"complete CAP_CONTROL_READ_CAPS request.\n");
BUG();
}
//cap_array_print(ncaps, caparray);
return 0;
}

View File

@@ -1,148 +0,0 @@
#include <thread.h>
#include <container.h>
#include <capability.h>
#include <tests.h>
#include <l4/api/errno.h>
#include <l4lib/arch/syslib.h>
#include <l4/api/capability.h>
int simple_pager_thread(void *arg)
{
int err;
int res = *(int *)arg;
struct task_ids ids;
int testres = 0;
l4_getid(&ids);
printf("Thread spawned from pager, \
trying to create new thread.\n");
err = l4_thread_control(THREAD_CREATE |
TC_SHARE_SPACE |
TC_AS_PAGER, &ids);
if (res == 0)
if (err == -ENOCAP ||
err == -ENOMEM) {
printf("Creation failed with %d "
"as expected.\n", err);
testres = 0;
} else {
printf("Creation was supposed to fail "
"with %d or %d, but err = %d\n",
-ENOMEM, -ENOCAP, err);
testres = 1;
}
else
if (err == 0) {
// printf("Creation succeeded as expected.\n");
testres = 0;
} else {
printf("Creation was supposed to succeed, "
"but err = %d\n", err);
testres = 1;
}
/* Destroy thread we created */
if (err == 0 &&
res == 0)
l4_thread_control(THREAD_DESTROY, &ids);
/* Destroy self */
l4_exit(testres);
return 0;
}
int wait_check_test(struct task_ids *ids)
{
int result;
/* Wait for thread to finish */
result = l4_thread_control(THREAD_WAIT, ids);
if (result < 0) {
printf("Waiting on (%d)'s exit failed.\n", ids->tid);
return -1;
} else if (result > 0) {
printf("Top-level test has failed\n");
}
/* Else it is a success */
return 0;
}
int capability_test(void)
{
int err;
struct task_ids ids;
int TEST_MUST_FAIL = 0;
//int TEST_MUST_SUCCEED = 1;
/* Read pager capabilities */
caps_read_all();
/*
* Create new thread that will attempt
* a pager privileged operation
*/
if ((err = thread_create(simple_pager_thread,
&TEST_MUST_FAIL,
TC_SHARE_SPACE, &ids)) < 0) {
printf("Top-level simple_pager creation failed.\n");
goto out_err;
}
printf("waititng for result\n");
/* Wait for test to finish and check result */
if (wait_check_test(&ids) < 0)
goto out_err;
#if 0
/* Destroy test thread */
if ((err = l4_thread_control(THREAD_DESTROY, &ids)) < 0) {
printf("Destruction of top-level simple_pager failed.\n");
BUG();
}
/*
* Share operations with the same thread
* group
*/
if ((err = l4_capability_control(CAP_CONTROL_SHARE,
CAP_SHARE_CONTAINER, 0)) < 0) {
printf("Sharing capability with thread group failed.\n");
goto out_err;
}
/*
* Create new thread that will attempt a pager privileged
* operation. This should succeed as we shared caps with
* the thread group.
*/
if ((err = thread_create(simple_pager_thread,
&TEST_MUST_SUCCEED,
TC_SHARE_SPACE |
TC_SHARE_GROUP, &ids)) < 0) {
printf("Top-level simple_pager creation failed.\n");
goto out_err;
}
/* Wait for test to finish and check result */
if (wait_check_test(&ids) < 0)
goto out_err;
/* Destroy test thread */
if ((err = l4_thread_control(THREAD_DESTROY, &ids)) < 0) {
printf("Destruction of top-level simple_pager failed.\n");
BUG();
}
#endif
printf("Capability Sharing Test -- PASSED --\n");
return 0;
out_err:
printf("Capability Sharing Test -- FAILED --\n");
return 0;
}

View File

@@ -1,220 +0,0 @@
#if 0
int mutex_user_thread(void *arg)
{
/* TODO: Create and access a mutex */
}
int independent_thread(void *arg)
{
/* TODO: Do whatever syscall available */
}
/*
* This example demonstrates how the capability-based
* security model can be bypassed and taken out of the
* way for the sake of implementing an application that
* doesn't worry too much about security.
*
* The benefit is that the user does neither worry about
* capabilities nor using its api to design correctly
* secure systems. The downside is that the system is
* less security-enforced, i.e. all parties must be
* trusted.
*/
int multi_threaded_nocaps_example(void)
{
/*
* We are the first pager with capabilities to
* create new tasks, spaces, in its own container.
*/
pager_read_caps();
/*
* We have all our capabilities private to us.
*
* If we create a new task, it won't be able to
* any kernel operations that we can do, because
* we hold our capabilities privately.
*
* In order to settle all capability access issues
* once and for all threads we will create and manage,
* we share our capabilities with the most global
* collection possible.
*/
/*
* Share all of our capabilities with all threads
* in the same container.
*
* From this point onwards, any thread we create and
* manage (i.e. whose container id is equal to our
* container id) will have the ability to leverage
* all of our capabilities as defined for us at
* configuration time.
*/
l4_cap_share(0, CAP_SHARE_CONTAINER | CAP_SHARE_ALL, self_tid());
/*
* Lets try it.
*
* Create new thread that we don't have any hieararchical
* relationship, i.e. one that is a pager of itself, one
* that runs in a new address space, and in a new thread
* group. All we share is the container.
*/
if ((err = thread_create(independent_thread, 0,
TC_NO_SHARING, &ids)) < 0) {
printf("mutex_user_thread creation failed.\n");
goto out_err;
}
/*
* We can inspect the new thread by doing an ipc to it.
* NOTE:
*
* We are able to send to this thread from the start,
* as we had a container-wide ipc capability defined at
* config-time.
*
* But we would not be able to receive from it, if we
* did not share this capability with the container. It
* would have no rights to do a send to us. But because
* we're in the same container, and we shared our
* capability, it now can.
*/
if ((err = l4_recv(ids->tid, ids->tid, 0)) < 0) {
print_err("%s: L4 IPC Error: %d.\n", __FUNCTION__, fd);
goto out_err;
}
/*
* From this point onwards we can create more threads
* without worrying about whether they have the caps
* to do certain ops, and the caps api. because we shared
* them all at the beginning.
*/
out_err:
BUG();
}
/*
* This example demonstrates how a pager would
* share part of its capabilities on the system
* with its children.
*
* The example includes sharing of a mutex
* capability with a paged-child.
*/
int multi_threaded_capability_sharing_example(void)
{
struct capability *mutex_cap;
int thread_retval;
/*
* We are the first pager with capabilities to
* create new tasks, spaces, in its own container.
*/
pager_read_caps();
/*
* We have all our capabilities private to us.
*
* If we create a new task, it won't be able to
* create and use userspace mutexes, because we
* hold mutex capabilities privately.
*
* Lets try it.
*/
/*
* Create new thread that will attempt
* a mutex operation, and die on us with a
* negative return code if it fails.
*/
if ((err = thread_create(mutex_user_thread, 0,
TC_SHARE_SPACE |
TC_AS_PAGER, &ids)) < 0) {
printf("mutex_user_thread creation failed.\n");
goto out_err;
}
/* Check on how the thread has done */
if ((err = l4_thread_wait_on(ids, &thread_retval)) < 0) {
print("Waiting on thread %d failed. err = %d\n",
ids->tid, err);
goto out_err;
}
if (thread_retval == 0) {
printf("Thread %d returned with success, where "
"we expected failure.\n", ids->tid);
goto out_err;
}
/*
* Therefore, we share our capabilities with a
* collection so that our capabilities may be also
* used by them.
*/
/* Get our private mutex cap */
mutex_cap = cap_get(CAP_TYPE_MUTEX);
/* We have ability to create and use this many mutexes */
printf("%s: We have ability to create/use %d mutexes\n",
self_tid(), mutex_cap->size);
/* Split it */
cap_new = cap_split(mutex_cap, 10, CAP_SPLIT_SIZE);
/*
* Share the split part with paged-children.
*
* From this point onwards, any thread we create and
* manage (i.e. whose pagerid == self_tid()) will have
* the ability to use mutexes, as defined by cap_new
* we created.
*/
l4_cap_share(cap_new, CAP_SHARE_PGGROUP, self_tid());
/*
* Create new thread that will attempt
* a mutex operation, and die on us with a
* negative return code if it fails.
*/
if ((err = thread_create(mutex_user_thread, 0,
TC_SHARE_SPACE |
TC_AS_PAGER, &ids)) < 0) {
printf("mutex_user_thread creation failed.\n");
goto out_err;
}
/* Check on how the thread has done */
if ((err = l4_thread_wait_on(ids, &thread_retval)) < 0) {
printf("Waiting on thread %d failed. err = %d\n",
ids->tid, err);
goto out_err;
}
if (thread_retval < 0) {
printf("Thread %d returned with failure, where "
"we expected success.\n", ids->tid);
goto out_err;
}
out_err:
BUG();
}
#endif

View File

@@ -1,73 +0,0 @@
/*
* Thread creation userspace helpers
*
* Copyright (C) 2009 B Labs Ltd.
*/
#include <thread.h>
#include <l4/api/errno.h>
char stack[THREADS_TOTAL][STACK_SIZE] ALIGN(8);
char *__stack_ptr = &stack[1][0];
char utcb[THREADS_TOTAL][UTCB_SIZE] ALIGN(8);
char *__utcb_ptr = &utcb[1][0];
extern void local_setup_new_thread(void);
int thread_create(int (*func)(void *), void *args, unsigned int flags,
struct task_ids *new_ids)
{
struct task_ids ids;
struct exregs_data exregs;
int err;
l4_getid(&ids);
/* Shared space only */
if (!(TC_SHARE_SPACE & flags)) {
printf("%s: This function allows only "
"shared space thread creation.\n",
__FUNCTION__);
return -EINVAL;
}
/* Create thread */
if ((err = l4_thread_control(THREAD_CREATE | flags, &ids)) < 0)
return err;
/* Check if more stack/utcb available */
if ((unsigned long)__utcb_ptr ==
(unsigned long)&utcb[THREADS_TOTAL][0])
return -ENOMEM;
if ((unsigned long)__stack_ptr ==
(unsigned long)&stack[THREADS_TOTAL][0])
return -ENOMEM;
/* First word of new stack is arg */
*(((unsigned int *)__stack_ptr) -1) = (unsigned int)args;
/* Second word of new stack is function address */
*(((unsigned int *)__stack_ptr) -2) = (unsigned int)func;
/* Setup new thread pc, sp, utcb */
memset(&exregs, 0, sizeof(exregs));
exregs_set_stack(&exregs, (unsigned long)__stack_ptr);
exregs_set_utcb(&exregs, (unsigned long)__utcb_ptr);
exregs_set_pc(&exregs, (unsigned long)local_setup_new_thread);
if ((err = l4_exchange_registers(&exregs, ids.tid)) < 0)
return err;
/* Update utcb, stack pointers */
__stack_ptr += STACK_SIZE;
__utcb_ptr += UTCB_SIZE;
/* Start the new thread */
if ((err = l4_thread_control(THREAD_RUN, &ids)) < 0)
return err;
memcpy(new_ids, &ids, sizeof(ids));
return 0;
}

View File

@@ -6,7 +6,7 @@
#include <l4lib/init.h>
#include <l4lib/utcb.h>
#include <l4lib/lib/thread.h>
void main(void);
@@ -15,6 +15,9 @@ void __container_init(void)
/* Generic L4 initialisation */
__l4_init();
/* Thread library initialisation */
__l4_threadlib_init();
/* Entry to main */
main();
}

View File

@@ -1,19 +0,0 @@
#ifndef __THREAD_H__
#define __THREAD_H__
#include <l4lib/macros.h>
#include L4LIB_INC_ARCH(syslib.h)
#include L4LIB_INC_ARCH(syscalls.h)
#include <l4lib/exregs.h>
#include <l4/api/thread.h>
int thread_create(int (*func)(void *), void *args, unsigned int flags,
struct task_ids *new_ids);
/* For same space */
#define STACK_SIZE 0x1000
#define THREADS_TOTAL 10
#endif /* __THREAD_H__ */

View File

@@ -3,6 +3,7 @@
*/
#include <l4lib/lib/addr.h>
#include <l4lib/irq.h>
#include <l4lib/lib/thread.h>
#include <l4lib/ipcdefs.h>
#include <l4/api/errno.h>
#include <l4/api/irq.h>
@@ -13,7 +14,6 @@
#include <container.h>
#include <linker.h>
#include <timer.h>
#include <thread.h>
#include <libdev/timer.h>
/* Capabilities of this service */
@@ -296,7 +296,8 @@ void task_wake(void)
int timer_setup_devices(void)
{
struct task_ids irq_tids;
struct l4_thread thread;
struct l4_thread *tptr = &thread;
int err;
for (int i = 0; i < TIMERS_TOTAL; i++) {
@@ -324,7 +325,7 @@ int timer_setup_devices(void)
*/
if ((err = thread_create(timer_irq_handler, &timer[i],
TC_SHARE_SPACE,
&irq_tids)) < 0) {
&tptr)) < 0) {
printf("FATAL: Creation of irq handler "
"thread failed.\n");
BUG();

View File

@@ -1,11 +0,0 @@
#include <l4lib/macros.h>
#include L4LIB_INC_ARCH(asm.h)
BEGIN_PROC(local_setup_new_thread)
ldr r0, [sp, #-4]! @ Load first argument.
mov lr, pc @ Save return address
ldr pc, [sp, #-4]! @ Load function pointer from stack
new_thread_exit:
b new_thread_exit @ We infinitely loop for now.
END_PROC(local_setup_new_thread)

View File

@@ -1,75 +0,0 @@
/*
* Thread creation userspace helpers
*
* Copyright (C) 2009 B Labs Ltd.
*/
#include <thread.h>
#include <l4/api/errno.h>
char stack[THREADS_TOTAL][STACK_SIZE] ALIGN(8);
char *__stack_ptr = &stack[1][0];
char utcb[THREADS_TOTAL][UTCB_SIZE] ALIGN(8);
//char utcb[THREADS_TOTAL][0x1000] ALIGN(0x1000);
char *__utcb_ptr = &utcb[1][0];
extern void local_setup_new_thread(void);
int thread_create(int (*func)(void *), void *args, unsigned int flags,
struct task_ids *new_ids)
{
struct task_ids ids;
struct exregs_data exregs;
int err;
l4_getid(&ids);
/* Shared space only */
if (!(TC_SHARE_SPACE & flags)) {
printf("%s: Warning - This function allows only "
"shared space thread creation.\n",
__FUNCTION__);
return -EINVAL;
}
/* Create thread */
if ((err = l4_thread_control(THREAD_CREATE | flags, &ids)) < 0)
return err;
/* Check if more stack/utcb available */
if ((unsigned long)__utcb_ptr ==
(unsigned long)&utcb[THREADS_TOTAL][0])
return -ENOMEM;
if ((unsigned long)__stack_ptr ==
(unsigned long)&stack[THREADS_TOTAL][0])
return -ENOMEM;
/* First word of new stack is arg */
((unsigned long *)__stack_ptr)[-1] = (unsigned long)args;
/* Second word of new stack is function address */
((unsigned long *)__stack_ptr)[-2] = (unsigned long)func;
/* Setup new thread pc, sp, utcb */
memset(&exregs, 0, sizeof(exregs));
exregs_set_stack(&exregs, (unsigned long)__stack_ptr);
exregs_set_utcb(&exregs, (unsigned long)__utcb_ptr);
exregs_set_pc(&exregs, (unsigned long)local_setup_new_thread);
if ((err = l4_exchange_registers(&exregs, ids.tid)) < 0)
return err;
/* Update utcb, stack pointers */
__stack_ptr += STACK_SIZE;
__utcb_ptr += UTCB_SIZE;
//__utcb_ptr += 0x1000;
/* Start the new thread */
if ((err = l4_thread_control(THREAD_RUN, &ids)) < 0)
return err;
memcpy(new_ids, &ids, sizeof(ids));
return 0;
}

View File

@@ -46,6 +46,12 @@ objects += SConscript('uart/pl011/SConscript', duplicate=0, \
exports = {'platform' : platform, 'env' : env})
objects += SConscript('timer/sp804/SConscript', duplicate=0, \
exports = {'platform' : platform, 'env' : env})
objects += SConscript('kmi/pl050/SConscript', duplicate=0, \
exports = {'platform' : platform, 'env' : env})
objects += SConscript('uart/omap/SConscript', duplicate=0, \
exports = {'platform' : platform, 'env' : env})
objects += SConscript('timer/omap/SConscript', duplicate=0, \
exports = {'platform' : platform, 'env' : env})
library = env.StaticLibrary('libdev-' + variant, objects)

View File

@@ -1,104 +0,0 @@
#ifndef __PL110_CLCD_H__
#define __PL110_CLCD_H__
/* Register offsets */
#define PL110_CLCD_TIMING0 0x000 /* Horizontal Axis Panel Control*/
#define PL110_CLCD_TIMING1 0x004 /* Vertical Axis Panel Control */
#define PL110_CLCD_TIMING2 0x008 /* Clock and Polarity Signal Control*/
#define PL110_CLCD_TIMING3 0x00c /* Line End Control */
#define PL110_CLCD_UPBASE 0x010 /* Upper Panel Frame Base Address*/
#define PL110_CLCD_LPBASE 0x014 /* Lower Panel Frame Base Address */
#define PL110_CLCD_IMSC 0x018 /* Interrupt Mast Set Clear */
#define PL110_CLCD_CONTROL 0x01c /* CLCD Control */
#define PL110_CLCD_RIS 0x020 /* Raw Interrupt Status */
#define PL110_CLCD_MIS 0x024 /* Masked Interrupt Status */
#define PL110_CLCD_ICR 0x028 /* Interrupt Clear */
#define PL110_CLCD_UPCURR 0x02c /* Upper Panel Current Address Value */
#define PL110_CLCD_LPCURR 0x030 /* Lower Panel Current Address Value */
//#define PL110_LCD_PALETTE
#define PL110_CLCD_PERIPHID0 0xfe0 /* Peripheral Identification */
#define PL110_CLCD_PERIPHID1 0xfe4 /* Peripheral Identification */
#define PL110_CLCD_PERIPHID2 0xfe8 /* Peripheral Identification */
#define PL110_CLCD_PERIPHID3 0xfec /* Peripheral Identification */
#define PL110_CLCD_PCELLID0 0xff0 /* Peripheral Identification */
#define PL110_CLCD_PCELLID1 0xff4 /* PrimeCell Identification */
#define PL110_CLCD_PCELLID2 0xff8 /* PrimeCell Identification */
#define PL110_CLCD_PCELLID3 0xffc /* PrimeCell Identification */
/* Scan mode */
#define SCAN_VMODE_NONINTERLACED 0 /* non interlaced */
#define SCAN_VMODE_INTERLACED 1 /* interlaced */
#define SCAN_VMODE_DOUBLE 2 /* double scan */
#define SCAN_VMODE_ODD_FLD_FIRST 4 /* interlaced: top line first */
#define SCAN_VMODE_MASK 255
/* Control Register Bits */
#define PL110_CNTL_LCDEN (1 << 0)
#define PL110_CNTL_LCDBPP1 (0 << 1)
#define PL110_CNTL_LCDBPP2 (1 << 1)
#define PL110_CNTL_LCDBPP4 (2 << 1)
#define PL110_CNTL_LCDBPP8 (3 << 1)
#define PL110_CNTL_LCDBPP16 (4 << 1)
#define PL110_CNTL_LCDBPP16_565 (6 << 1)
#define PL110_CNTL_LCDBPP24 (5 << 1)
#define PL110_CNTL_LCDBW (1 << 4)
#define PL110_CNTL_LCDTFT (1 << 5)
#define PL110_CNTL_LCDMONO8 (1 << 6)
#define PL110_CNTL_LCDDUAL (1 << 7)
#define PL110_CNTL_BGR (1 << 8)
#define PL110_CNTL_BEBO (1 << 9)
#define PL110_CNTL_BEPO (1 << 10)
#define PL110_CNTL_LCDPWR (1 << 11)
#define PL110_CNTL_LCDVCOMP(x) ((x) << 12)
#define PL110_CNTL_LDMAFIFOTIME (1 << 15)
#define PL110_CNTL_WATERMARK (1 << 16)
#define PL110_TIM2_CLKSEL (1 << 5)
#define PL110_TIM2_IVS (1 << 11)
#define PL110_TIM2_IHS (1 << 12)
#define PL110_TIM2_IPC (1 << 13)
#define PL110_TIM2_IOE (1 << 14)
#define PL110_TIM2_BCD (1 << 26)
struct videomode {
const char *name; /* optional */
unsigned int refresh; /* optional */
unsigned int xres;
unsigned int yres;
unsigned int pixclock;
unsigned int left_margin;
unsigned int right_margin;
unsigned int upper_margin;
unsigned int lower_margin;
unsigned int hsync_len;
unsigned int vsync_len;
unsigned int sync;
unsigned int vmode;
unsigned int flag;
};
struct pl110_clcd_panel {
struct videomode mode;
signed short width; /* width in mm */
signed short height; /* height in mm */
unsigned int tim2;
unsigned int tim3;
unsigned int cntl;
unsigned int bpp:8,
fixedtimings:1,
grayscale:1;
unsigned int connector;
};
struct pl110_clcd {
unsigned int virt_base;
struct pl110_clcd_panel *panel;
char *frame_buffer;
};
void pl110_initialise(struct pl110_clcd *clcd, char *buf);
#endif /* __PL110_CLCD_H__ */

View File

@@ -1,68 +0,0 @@
#include <pl110_clcd.h>
#define read(a) *((volatile unsigned int *)(a))
#define write(v, a) (*((volatile unsigned int *)(a)) = v)
#define setbit(bit, a) write(read(a) | bit, a)
#define clrbit(bit, a) write(read(a) & ~bit, a)
/*
* Default panel, we will use this for now
* Seems like qemu has support for this
*/
static struct pl110_clcd_panel vga = {
.mode = {
.name = "VGA",
.refresh = 60,
.xres = 640,
.yres = 480,
.pixclock = 39721,
.left_margin = 40,
.right_margin = 24,
.upper_margin = 32,
.lower_margin = 11,
.hsync_len = 96,
.vsync_len = 2,
.sync = 0,
.vmode = SCAN_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = PL110_TIM2_BCD | PL110_TIM2_IPC,
.cntl = PL110_CNTL_LCDTFT | PL110_CNTL_LCDVCOMP(1),
.bpp = 16,
};
static void pl110_clcd_set_uppanel_fb(unsigned int clcd_base,
unsigned int fb_base)
{
write(fb_base, (clcd_base + PL110_CLCD_UPBASE));
}
#if 0
static void pl110_clcd_set_lwrpanel_fb(unsigned int clcd_base, unsigned int fb_base)
{
write(fb_base, (clcd_base +PL110_CLCD_LPBASE));
}
static unsigned int pl110_clcd_get_uppanel_fb(unsigned int clcd_base)
{
return read((clcd_base +PL110_CLCD_UPBASE));
}
static unsigned int pl110_clcd_get_lwrpanel_fb(unsigned int clcd_base)
{
return read((clcd_base +PL110_CLCD_LPBASE));
}
#endif
void pl110_initialise(struct pl110_clcd *clcd, char *buf)
{
clcd->panel = &vga;
clcd->frame_buffer = buf;
pl110_clcd_set_uppanel_fb(clcd->virt_base, (unsigned int)(buf));
}

View File

@@ -1,67 +0,0 @@
/*
* SP804 Primecell Timer offsets
*
* Copyright (C) 2007 Bahadir Balban
*
*/
#ifndef __SP804_TIMER_H__
#define __SP804_TIMER_H__
#define SP804_TIMER2_OFFSET 0x20
/* Base address of Timers for differen platforms */
#if defined(PLATFORM_PB926)
#define TIMER0_PHYS_BASE 0x101E2000
#define TIMER1_PHYS_BASE (TIMER0_PHYS_BASE + SP804_TIMER2_OFFSET)
#define TIMER2_PHYS_BASE 0x101E3000
#define TIMER3_PHYS_BASE (TIMER2_PHYS_BASE + SP804_TIMER2_OFFSET)
#elif defined(PLATFORM_EB)
#define TIMER0_PHYS_BASE 0x10011000
#define TIMER1_PHYS_BASE (TIMER0_PHYS_BASE + SP804_TIMER2_OFFSET)
#define TIMER2_PHYS_BASE 0x10012000
#define TIMER3_PHYS_BASE (TIMER2_PHYS_BASE + SP804_TIMER2_OFFSET)
#elif defined(PLATFORM_PB11MPCORE)
#define TIMER0_PHYS_BASE 0x10011000
#define TIMER1_PHYS_BASE (TIMER0_PHYS_BASE + SP804_TIMER2_OFFSET)
#define TIMER2_PHYS_BASE 0x10012000
#define TIMER3_PHYS_BASE (TIMER2_PHYS_BASE + SP804_TIMER2_OFFSET)
#define TIMER4_PHYS_BASE 0x10018000
#define TIMER5_PHYS_BASE (TIMER4_PHYS_BASE + SP804_TIMER2_OFFSET)
#define TIMER6_PHYS_BASE 0x10019000
#define TIMER7_PHYS_BASE (TIMER6_PHYS_BASE + SP804_TIMER2_OFFSET)
#endif
/* Run mode of timers */
#define SP804_TIMER_RUNMODE_FREERUN 0
#define SP804_TIMER_RUNMODE_PERIODIC 1
/* Wrap mode of timers */
#define SP804_TIMER_WRAPMODE_WRAPPING 0
#define SP804_TIMER_WRAPMODE_ONESHOT 1
/* Operational width of timer */
#define SP804_TIMER_WIDTH16BIT 0
#define SP804_TIMER_WIDTH32BIT 1
/* Enable/disable irq on timer */
#define SP804_TIMER_IRQDISABLE 0
#define SP804_TIMER_IRQENABLE 1
/* Register offsets */
#define SP804_TIMERLOAD 0x0
#define SP804_TIMERVALUE 0x4
#define SP804_TIMERCONTROL 0x8
#define SP804_TIMERINTCLR 0xC
#define SP804_TIMERRIS 0x10
#define SP804_TIMERMIS 0x14
#define SP804_TIMERBGLOAD 0x18
void sp804_init(unsigned int timer_base, int runmode, int wrapmode, \
int width, int irq_enable);
void sp804_irq_handler(unsigned int timer_base);
void sp804_enable(unsigned int timer_base, int enable);
void sp804_set_irq(unsigned int timer_base, int enable);
unsigned int sp804_read_value(unsigned int timer_base);
#endif /* __SP804_TIMER_H__ */

View File

@@ -1,107 +0,0 @@
/*
* SP804 Primecell Timer driver
*
* Copyright (C) 2007 Bahadir Balban
*/
#include <sp804_timer.h>
#define read(a) *((volatile unsigned int *)(a))
#define write(v, a) (*((volatile unsigned int *)(a)) = v)
#define setbit(bit, a) write(read(a) | bit, a)
#define clrbit(bit, a) write(read(a) & ~bit, a)
extern void timer_irq_handler(void);
void sp804_irq_handler(unsigned int timer_base)
{
/*
* Timer enabled as Periodic/Wrapper only needs irq clearing
* as it automatically reloads and wraps
*/
write(1, (timer_base + SP804_TIMERINTCLR));
timer_irq_handler();
}
static inline void sp804_control(unsigned int timer_base, int bit, int setclr)
{
unsigned long addr = (timer_base + SP804_TIMERCONTROL);
setclr ? setbit(bit, addr) : clrbit(bit, addr);
}
/*
* Sets timer's run mode:
* @periodic: periodic mode = 1, free-running = 0.
*/
#define SP804_PEREN (1 << 6)
static inline void sp804_set_runmode(unsigned int timer_base, int periodic)
{
sp804_control(timer_base, SP804_PEREN, periodic);
}
/*
* Sets timer's wrapping mode:
* @oneshot: oneshot = 1, wrapping = 0.
*/
#define SP804_ONESHOT (1 << 0)
static inline void sp804_set_wrapmode(unsigned int timer_base, int oneshot)
{
sp804_control(timer_base, SP804_ONESHOT, oneshot);
}
/*
* Sets the operational width of timers.
* In 16bit mode, top halfword is ignored.
* @width: 32bit mode = 1; 16bit mode = 0
*/
#define SP804_32BIT (1 << 1)
static inline void sp804_set_widthmode(unsigned int timer_base, int width)
{
sp804_control(timer_base, SP804_32BIT, width);
}
/*
* Enable/disable timer:
* @enable: enable = 1, disable = 0;
*/
#define SP804_ENABLE (1 << 7)
void sp804_enable(unsigned int timer_base, int enable)
{
sp804_control(timer_base, SP804_ENABLE, enable);
}
/*
* Enable/disable local irq register:
* @enable: enable = 1, disable = 0
*/
#define SP804_IRQEN (1 << 5)
void sp804_set_irq(unsigned int timer_base, int enable)
{
sp804_control(timer_base, SP804_IRQEN, enable);
}
/* Loads timer with value in val */
static inline void sp804_load_value(unsigned int timer_base, unsigned int val)
{
write(val, (timer_base + SP804_TIMERLOAD));
}
/* Returns current timer value */
unsigned int sp804_read_value(unsigned int timer_base)
{
return read(timer_base + SP804_TIMERVALUE);
}
/* TODO: Define macro values for duration */
void sp804_init(unsigned int timer_base, int run_mode, int wrap_mode, \
int width, int irq_enable)
{
/* 1 tick per usec */
const int duration = 250;
sp804_set_runmode(timer_base, run_mode); /* Periodic */
sp804_set_wrapmode(timer_base, wrap_mode); /* Wrapping */
sp804_set_widthmode(timer_base, width); /* 32 bit */
sp804_set_irq(timer_base, irq_enable); /* Enable */
sp804_load_value(timer_base, duration);
}

View File

@@ -1,379 +0,0 @@
#ifndef __PL011__UART__H__
#define __PL011__UART__H__
/*
* PL011 UART Generic driver implementation.
* Copyright Bahadir Balban (C) 2009
*
* The particular intention of this code is that it has been carefully
* written as decoupled from os-specific code and in a verbose way such
* that it clearly demonstrates how the device operates, reducing the
* amount of time to be spent for understanding the operational model
* and implementing a driver from scratch. This is the very first to be
* such a driver so far, hopefully it will turn out to be useful.
*/
#if defined(VARIANT_USERSPACE)
/* FIXME: Take this value in agreement from kernel, or from kernel only */
#define PL011_BASE 0x500000
#endif
#if defined(VARIANT_BAREMETAL)
#if defined(PLATFORM_PB926)
#define PL011_BASE 0x101F1000
#elif defined(PLATFORM_EB)
#define PL011_BASE 0x10009000
#elif defined(PLATFORM_PB11MPCORE)
#define PL011_BASE 0x10009000
#endif
#endif
/* Architecture specific memory access macros */
#define read(val, address) val = *((volatile unsigned int *) address)
#define write(val, address) *((volatile unsigned int *) address) = val
/* Register offsets */
#define PL011_UARTDR 0x00
#define PL011_UARTRSR 0x04
#define PL011_UARTECR 0x04
#define PL011_UARTFR 0x18
#define PL011_UARTILPR 0x20
#define PL011_UARTIBRD 0x24
#define PL011_UARTFBRD 0x28
#define PL011_UARTLCR_H 0x2C
#define PL011_UARTCR 0x30
#define PL011_UARTIFLS 0x34
#define PL011_UARTIMSC 0x38
#define PL011_UARTRIS 0x3C
#define PL011_UARTMIS 0x40
#define PL011_UARTICR 0x44
#define PL011_UARTDMACR 0x48
/* IRQ bits for each uart irq event */
#define PL011_RXIRQ (1 << 4)
#define PL011_TXIRQ (1 << 5)
#define PL011_RXTIMEOUTIRQ (1 << 6)
#define PL011_FEIRQ (1 << 7)
#define PL011_PEIRQ (1 << 8)
#define PL011_BEIRQ (1 << 9)
#define PL011_OEIRQ (1 << 10)
struct pl011_uart {
unsigned long base;
unsigned int frame_errors;
unsigned int parity_errors;
unsigned int break_errors;
unsigned int overrun_errors;
unsigned int rx_timeout_errors;
};
int pl011_tx_char(unsigned int base, char c);
int pl011_rx_char(unsigned int base, char *c);
void pl011_set_baudrate(unsigned int base, unsigned int baud,
unsigned int clkrate);
void pl011_set_irq_mask(unsigned int base, unsigned int flags);
void pl011_clr_irq_mask(unsigned int base, unsigned int flags);
void pl011_irq_handler(struct pl011_uart *);
void pl011_tx_irq_handler(struct pl011_uart *uart, unsigned int);
void pl011_rx_irq_handler(struct pl011_uart *uart, unsigned int);
void pl011_error_irq_handler(struct pl011_uart *uart, unsigned int);
static inline void pl011_uart_enable(unsigned int base);
static inline void pl011_uart_disable(unsigned int base);
static inline void pl011_tx_enable(unsigned int base);
static inline void pl011_tx_disable(unsigned int base);
static inline void pl011_rx_enable(unsigned int base);
static inline void pl011_rx_disable(unsigned int base);
static inline void pl011_irq_clear(unsigned int base, unsigned int flags);
static inline unsigned int pl011_read_irqstat(unsigned int base);
static inline unsigned int pl011_read_irqmask(unsigned int base);
static inline void pl011_rx_dma_disable(unsigned int base);
static inline void pl011_rx_dma_enable(unsigned int base);
static inline void pl011_tx_dma_enable(unsigned int base);
static inline void pl011_tx_dma_disable(unsigned int base);
static inline void pl011_set_irq_fifolevel(unsigned int base,
unsigned int xfer, unsigned int level);
static inline void pl011_set_word_width(unsigned int base, int size);
static inline void pl011_disable_fifos(unsigned int base);
static inline void pl011_set_parity_even(unsigned int base);
static inline void pl011_parity_enable(unsigned int base);
static inline void pl011_set_stopbits(unsigned int base, int stopbits);
static inline void pl011_set_parity_odd(unsigned int base);
static inline void pl011_enable_fifos(unsigned int base);
static inline void pl011_parity_disable(unsigned int base);
#define PL011_UARTEN (1 << 0)
static inline void pl011_uart_enable(unsigned int base)
{
unsigned int val = 0;
read(val, (base + PL011_UARTCR));
val |= PL011_UARTEN;
write(val, (base + PL011_UARTCR));
return;
}
static inline void pl011_uart_disable(unsigned int base)
{
unsigned int val = 0;
read(val, (base + PL011_UARTCR));
val &= ~PL011_UARTEN;
write(val, (base + PL011_UARTCR));
return;
}
#define PL011_TXE (1 << 8)
static inline void pl011_tx_enable(unsigned int base)
{
unsigned int val = 0;
read(val, (base + PL011_UARTCR));
val |= PL011_TXE;
write(val, (base + PL011_UARTCR));
return;
}
static inline void pl011_tx_disable(unsigned int base)
{
unsigned int val = 0;
read(val, (base + PL011_UARTCR));
val &= ~PL011_TXE;
write(val, (base + PL011_UARTCR));
return;
}
#define PL011_RXE (1 << 9)
static inline void pl011_rx_enable(unsigned int base)
{
unsigned int val = 0;
read(val, (base + PL011_UARTCR));
val |= PL011_RXE;
write(val, (base + PL011_UARTCR));
return;
}
static inline void pl011_rx_disable(unsigned int base)
{
unsigned int val = 0;
read(val, (base + PL011_UARTCR));
val &= ~PL011_RXE;
write(val, (base + PL011_UARTCR));
return;
}
#define PL011_TWO_STOPBITS_SELECT (1 << 3)
static inline void pl011_set_stopbits(unsigned int base, int stopbits)
{
unsigned int val = 0;
read(val, (base + PL011_UARTLCR_H));
if(stopbits == 2) { /* Set to two bits */
val |= PL011_TWO_STOPBITS_SELECT;
} else { /* Default is 1 */
val &= ~PL011_TWO_STOPBITS_SELECT;
}
write(val, (base + PL011_UARTLCR_H));
return;
}
#define PL011_PARITY_ENABLE (1 << 1)
static inline void pl011_parity_enable(unsigned int base)
{
unsigned int val = 0;
read(val, (base +PL011_UARTLCR_H));
val |= PL011_PARITY_ENABLE;
write(val, (base + PL011_UARTLCR_H));
return;
}
static inline void pl011_parity_disable(unsigned int base)
{
unsigned int val = 0;
read(val, (base + PL011_UARTLCR_H));
val &= ~PL011_PARITY_ENABLE;
write(val, (base + PL011_UARTLCR_H));
return;
}
#define PL011_PARITY_EVEN (1 << 2)
static inline void pl011_set_parity_even(unsigned int base)
{
unsigned int val = 0;
read(val, (base + PL011_UARTLCR_H));
val |= PL011_PARITY_EVEN;
write(val, (base + PL011_UARTLCR_H));
return;
}
static inline void pl011_set_parity_odd(unsigned int base)
{
unsigned int val = 0;
read(val, (base + PL011_UARTLCR_H));
val &= ~PL011_PARITY_EVEN;
write(val, (base + PL011_UARTLCR_H));
return;
}
#define PL011_ENABLE_FIFOS (1 << 4)
static inline void pl011_enable_fifos(unsigned int base)
{
unsigned int val = 0;
read(val, (base + PL011_UARTLCR_H));
val |= PL011_ENABLE_FIFOS;
write(val, (base + PL011_UARTLCR_H));
return;
}
static inline void pl011_disable_fifos(unsigned int base)
{
unsigned int val = 0;
read(val, (base + PL011_UARTLCR_H));
val &= ~PL011_ENABLE_FIFOS;
write(val, (base + PL011_UARTLCR_H));
return;
}
#define PL011_WORD_WIDTH_SHIFT (5)
/* Sets the transfer word width for the data register. */
static inline void pl011_set_word_width(unsigned int base, int size)
{
unsigned int val = 0;
if(size < 5 || size > 8) /* Default is 8 */
size = 8;
/* Clear size field */
read(val, (base + PL011_UARTLCR_H));
val &= ~(0x3 << PL011_WORD_WIDTH_SHIFT);
write(val, (base + PL011_UARTLCR_H));
/*
* The formula is to write 5 less of size given:
* 11 = 8 bits
* 10 = 7 bits
* 01 = 6 bits
* 00 = 5 bits
*/
read(val, (base + PL011_UARTLCR_H));
val |= (size - 5) << PL011_WORD_WIDTH_SHIFT;
write(val, (base + PL011_UARTLCR_H));
return;
}
/*
* Defines at which level of fifo fullness an irq will be generated.
* @xfer: tx fifo = 0, rx fifo = 1
* @level: Generate irq if:
* 0 rxfifo >= 1/8 full txfifo <= 1/8 full
* 1 rxfifo >= 1/4 full txfifo <= 1/4 full
* 2 rxfifo >= 1/2 full txfifo <= 1/2 full
* 3 rxfifo >= 3/4 full txfifo <= 3/4 full
* 4 rxfifo >= 7/8 full txfifo <= 7/8 full
* 5-7 reserved reserved
*/
static inline void pl011_set_irq_fifolevel(unsigned int base, \
unsigned int xfer, unsigned int level)
{
if(xfer != 1 && xfer != 0) /* Invalid fifo */
return;
if(level > 4) /* Invalid level */
return;
write(level << (xfer * 3), (base + PL011_UARTIFLS));
return;
}
/* returns which irqs are masked */
static inline unsigned int pl011_read_irqmask(unsigned int base)
{
unsigned int flags;
read(flags, (base + PL011_UARTIMSC));
return flags;
}
/* returns masked irq status */
static inline unsigned int pl011_read_irqstat(unsigned int base)
{
unsigned int irqstatus;
read(irqstatus, (base + PL011_UARTMIS));
return irqstatus;
}
/* Clears the given asserted irqs */
static inline void pl011_irq_clear(unsigned int base, unsigned int flags)
{
if(flags > 0x3FF) {
/* Invalid irq clearing bitvector */
return;
}
/* Simply write the flags since it's a write-only register */
write(flags, (base + PL011_UARTICR));
return;
}
#define PL011_TXDMAEN (1 << 1)
#define PL011_RXDMAEN (1 << 0)
/*
* Enables dma transfers for uart. The dma controller
* must be initialised, set-up and enabled separately.
*/
static inline void pl011_tx_dma_enable(unsigned int base)
{
unsigned int val = 0;
read(val, (base + PL011_UARTDMACR));
val |= PL011_TXDMAEN;
write(val, (base + PL011_UARTDMACR));
return;
}
/* Disables dma transfers for uart */
static inline void pl011_tx_dma_disable(unsigned int base)
{
unsigned int val = 0;
read(val, (base + PL011_UARTDMACR));
val &= ~PL011_TXDMAEN;
write(val, (base + PL011_UARTDMACR));
return;
}
static inline void pl011_rx_dma_enable(unsigned int base)
{
unsigned int val = 0;
read(val, (base + PL011_UARTDMACR));
val |= PL011_RXDMAEN;
write(val, (base + PL011_UARTDMACR));
return;
}
static inline void pl011_rx_dma_disable(unsigned int base)
{
unsigned int val = 0;
read(val, (base + PL011_UARTDMACR));
val &= ~PL011_RXDMAEN;
write(val, (base +PL011_UARTDMACR));
return;
}
int pl011_initialise(struct pl011_uart *uart);
#endif /* __PL011__UART__ */

View File

@@ -1,123 +0,0 @@
/*
* Copyright (C) 2009 B Labs Ltd.
*/
#include <pl011_uart.h>
/* UART-specific internal error codes */
#define PL011_ERROR 1
#define PL011_EAGAIN 2
/* Error status bits in receive status register */
#define PL011_FE (1 << 0)
#define PL011_PE (1 << 1)
#define PL011_BE (1 << 2)
#define PL011_OE (1 << 3)
/* Status bits in flag register */
#define PL011_TXFE (1 << 7)
#define PL011_RXFF (1 << 6)
#define PL011_TXFF (1 << 5)
#define PL011_RXFE (1 << 4)
#define PL011_BUSY (1 << 3)
#define PL011_DCD (1 << 2)
#define PL011_DSR (1 << 1)
#define PL011_CTS (1 << 0)
int pl011_tx_char(unsigned int base, char c)
{
unsigned int val = 0;
read(val, (base + PL011_UARTFR));
if(val & PL011_TXFF) { /* TX FIFO Full */
return -PL011_EAGAIN;
}
write(c, (base + PL011_UARTDR));
return 0;
}
int pl011_rx_char(unsigned int base, char * c)
{
unsigned int data;
unsigned int val = 0;
read(val, (base + PL011_UARTFR));
if(val & PL011_RXFE) { /* RX FIFO Empty */
return -PL011_EAGAIN;
}
read(data, (base + PL011_UARTDR));
*c = (char) data;
if((data >> 8) & 0xF) { /* There were errors */
return -1; /* Signal error in xfer */
}
return 0; /* No error return */
}
/*
* Sets the baud rate in kbps. It is recommended to use
* standard rates such as: 1200, 2400, 3600, 4800, 7200,
* 9600, 14400, 19200, 28800, 38400, 57600 76800, 115200.
*/
void pl011_set_baudrate(unsigned int base, unsigned int baud,
unsigned int clkrate)
{
const unsigned int uartclk = 24000000; /* 24Mhz clock fixed on pb926 */
unsigned int val = 0, ipart = 0, fpart = 0;
/* Use default pb926 rate if no rate is supplied */
if(clkrate == 0) {
clkrate = uartclk;
}
if(baud > 115200 || baud < 1200) {
baud = 38400; /* Default rate. */
}
/* 24000000 / (38400 * 16) */
ipart = 39;
write(ipart, (base + PL011_UARTIBRD));
write(fpart, (base + PL011_UARTFBRD));
/*
* For the IBAUD and FBAUD to update, we need to
* write to UARTLCR_H because the 3 registers are
* actually part of a single register in hardware
* which only updates by a write to UARTLCR_H
*/
read(val, (base + PL011_UARTLCR_H));
write(val, (base + PL011_UARTLCR_H));
return;
}
/* Masks the irqs given in the flags bitvector. */
void pl011_set_irq_mask(unsigned int base, unsigned int flags)
{
unsigned int val = 0;
if(flags > 0x3FF) { /* Invalid irqmask bitvector */
return;
}
read(val, (base + PL011_UARTIMSC));
val |= flags;
write(val, (base + PL011_UARTIMSC));
return;
}
/* Clears the irqs given in flags from masking */
void pl011_clr_irq_mask(unsigned int base, unsigned int flags)
{
unsigned int val = 0;
if(flags > 0x3FF) {
/* Invalid irqmask bitvector */
return;
}
read(val, (base + PL011_UARTIMSC));
val &= ~flags;
write(val, (base + PL011_UARTIMSC));
return;
}

View File

@@ -1,60 +0,0 @@
/*
* User space uart driver.
*
* Copyright (C) 2009, B Labs Ltd.
*/
#include <pl011_uart.h>
/*
* Every task who wants to use this uart needs
* to initialize an instance of this
*/
struct pl011_uart uart;
/*
* Initialises the uart class data structures, and the device.
* Terminal-like operation is assumed for default settings.
*/
int pl011_initialise(struct pl011_uart *uart)
{
uart->frame_errors = 0;
uart->parity_errors = 0;
uart->break_errors = 0;
uart->overrun_errors = 0;
/* Initialise data register for 8 bit data read/writes */
pl011_set_word_width(uart->base, 8);
/*
* Fifos are disabled because by default it is assumed the port
* will be used as a user terminal, and in that case the typed
* characters will only show up when fifos are flushed, rather than
* when each character is typed. We avoid this by not using fifos.
*/
pl011_disable_fifos(uart->base);
/* Set default baud rate of 38400 */
pl011_set_baudrate(uart->base, 38400, 24000000);
/* Set default settings of 1 stop bit, no parity, no hw flow ctrl */
pl011_set_stopbits(uart->base, 1);
pl011_parity_disable(uart->base);
/* Disable all irqs */
pl011_set_irq_mask(uart->base, 0x3FF);
/* Enable rx, tx, and uart chip */
pl011_tx_enable(uart->base);
pl011_rx_enable(uart->base);
pl011_uart_enable(uart->base);
return 0;
}
void platform_init(void)
{
uart.base = PL011_BASE;
pl011_initialise(&uart);
}

View File

@@ -1,27 +0,0 @@
/*
* Address allocation pool.
*
* Copyright (C) 2007 Bahadir Balban
*/
#ifndef __ADDR_H__
#define __ADDR_H__
#include <l4lib/idpool.h>
/* Address pool to allocate from a range of addresses */
struct address_pool {
struct id_pool *idpool;
unsigned long start;
unsigned long end;
};
int address_pool_init_with_idpool(struct address_pool *pool,
struct id_pool *idpool,
unsigned long start, unsigned long end);
int address_pool_init(struct address_pool *pool,
unsigned long start, unsigned long end,
unsigned int size);
void *address_new(struct address_pool *pool, int nitems, int size);
int address_del(struct address_pool *, void *addr, int nitems, int size);
#endif /* __ADDR_H__ */

View File

@@ -1,15 +0,0 @@
#ifndef __ARM_ASM_H__
#define __ARM_ASM_H__
#define BEGIN_PROC(name) \
.global name; \
.type name,function; \
.align; \
name:
#define END_PROC(name) \
.fend_##name: \
.size name,.fend_##name - name;
#endif /* __ARM_ASM_H__ */

View File

@@ -1,11 +0,0 @@
#ifndef __L4LIB_ARCH_IRQ_H__
#define __L4LIB_ARCH_IRQ_H__
/*
* Destructive atomic-read.
*
* Write 0 to byte at @location as its contents are read back.
*/
char l4_atomic_dest_readb(void *location);
#endif

View File

@@ -1,92 +0,0 @@
/*
* System call prototypes.
*
* Copyright (C) 2007 Bahadir Balban
*/
#ifndef __ARM_SYSCALLS_H__
#define __ARM_SYSCALLS_H__
#include <l4lib/arch/types.h>
#include <l4lib/arch/utcb.h>
#include <l4/generic/space.h>
#include <l4/api/space.h>
#include <l4/api/kip.h>
#include <l4/api/ipc.h>
#include <l4/api/thread.h>
struct task_ids {
l4id_t tid;
l4id_t spid;
l4id_t tgid;
};
static inline void *
l4_kernel_interface(unsigned int *api_version, unsigned int *api_flags,
unsigned int *kernel_id)
{
return (void *)L4_KIP_ADDRESS;
}
typedef unsigned int (*__l4_thread_switch_t)(u32);
extern __l4_thread_switch_t __l4_thread_switch;
unsigned int l4_thread_switch (u32 dest);
typedef int (*__l4_getid_t)(struct task_ids *ids);
extern __l4_getid_t __l4_getid;
int l4_getid(struct task_ids *ids);
typedef int (*__l4_ipc_t)(l4id_t to, l4id_t from, u32 flags);
extern __l4_ipc_t __l4_ipc;
int l4_ipc(l4id_t to, l4id_t from, u32 flags);
typedef int (*__l4_capability_control_t)(unsigned int req, unsigned int flags, void *buf);
extern __l4_capability_control_t __l4_capability_control;
int l4_capability_control(unsigned int req, unsigned int flags, void *buf);
typedef int (*__l4_map_t)(void *phys, void *virt,
u32 npages, u32 flags, l4id_t tid);
extern __l4_map_t __l4_map;
int l4_map(void *p, void *v, u32 npages, u32 flags, l4id_t tid);
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);
extern __l4_thread_control_t __l4_thread_control;
int l4_thread_control(unsigned int action, struct task_ids *ids);
typedef int (*__l4_irq_control_t)(unsigned int req, unsigned int flags, l4id_t id);
extern __l4_irq_control_t __l4_irq_control;
int l4_irq_control(unsigned int req, unsigned int flags, l4id_t id);
typedef int (*__l4_ipc_control_t)(unsigned int action, l4id_t blocked_sender,
u32 blocked_tag);
extern __l4_ipc_control_t __l4_ipc_control;
int l4_ipc_control(unsigned int, l4id_t blocked_sender, u32 blocked_tag);
typedef int (*__l4_exchange_registers_t)(void *exregs_struct, l4id_t tid);
extern __l4_exchange_registers_t __l4_exchange_registers;
int l4_exchange_registers(void *exregs_struct, l4id_t tid);
typedef int (*__l4_container_control_t)(unsigned int req, unsigned int flags, void *buf);
extern __l4_container_control_t __l4_container_control;
int l4_container_control(unsigned int req, unsigned int flags, void *buf);
typedef int (*__l4_time_t)(void *timeval, int set);
extern __l4_time_t __l4_time;
int l4_time(void *timeval, int set);
typedef int (*__l4_mutex_control_t)(void *mutex_word, int op);
extern __l4_mutex_control_t __l4_mutex_control;
int l4_mutex_control(void *mutex_word, int op);
/* To be supplied by server tasks. */
void *virt_to_phys(void *);
void *phys_to_virt(void *);
#endif /* __ARM_SYSCALLS_H__ */

View File

@@ -1,366 +0,0 @@
/*
* Helper functions that wrap raw l4 syscalls.
*
* Copyright (C) 2007-2009 Bahadir Bilgehan Balban
*/
#ifndef __L4LIB_SYSLIB_H__
#define __L4LIB_SYSLIB_H__
#include <stdio.h>
#include <l4lib/arch/syscalls.h>
#include <l4/macros.h>
/*
* NOTE:
* Its best to use these wrappers because they generalise the way
* common ipc data like sender id, error, ipc tag are passed
* between ipc parties.
*
* The arguments to l4_ipc() are used by the microkernel to initiate
* the ipc. Any data passed in message registers may or may not be
* a duplicate of this data, but the distinction is that anything
* that is passed via the mrs are meant to be used by the other party
* participating in the ipc.
*/
/* For system call arguments */
#define L4SYS_ARG0 (MR_UNUSED_START)
#define L4SYS_ARG1 (MR_UNUSED_START + 1)
#define L4SYS_ARG2 (MR_UNUSED_START + 2)
#define L4SYS_ARG3 (MR_UNUSED_START + 3)
#define L4_IPC_TAG_MASK 0x00000FFF
/*
* Servers get sender.
*/
static inline l4id_t l4_get_sender(void)
{
return (l4id_t)read_mr(MR_SENDER);
}
/*
* When doing an ipc the sender never has to be explicitly set in
* the utcb via this function since this information is found out
* by the microkernel by checking the system caller's id. This is
* only used for restoring the sender on the utcb in order to
* complete an earlier ipc.
*/
static inline void l4_set_sender(l4id_t sender)
{
write_mr(MR_SENDER, sender);
}
static inline unsigned int l4_set_ipc_size(unsigned int word, unsigned int size)
{
word &= ~L4_IPC_FLAGS_SIZE_MASK;
word |= ((size << L4_IPC_FLAGS_SIZE_SHIFT) & L4_IPC_FLAGS_SIZE_MASK);
return word;
}
static inline unsigned int l4_get_ipc_size(unsigned int word)
{
return (word & L4_IPC_FLAGS_SIZE_MASK) >> L4_IPC_FLAGS_SIZE_SHIFT;
}
static inline unsigned int l4_set_ipc_msg_index(unsigned int word, unsigned int index)
{
/* FIXME: Define MR_PRIMARY_TOTAL, MR_TOTAL etc. and use MR_TOTAL HERE! */
BUG_ON(index > UTCB_SIZE);
word &= ~L4_IPC_FLAGS_MSG_INDEX_MASK;
word |= (index << L4_IPC_FLAGS_MSG_INDEX_SHIFT) &
L4_IPC_FLAGS_MSG_INDEX_MASK;
return word;
}
static inline unsigned int l4_get_ipc_msg_index(unsigned int word)
{
return (word & L4_IPC_FLAGS_MSG_INDEX_MASK)
>> L4_IPC_FLAGS_MSG_INDEX_SHIFT;
}
static inline unsigned int l4_set_ipc_flags(unsigned int word, unsigned int flags)
{
word &= ~L4_IPC_FLAGS_TYPE_MASK;
word |= flags & L4_IPC_FLAGS_TYPE_MASK;
return word;
}
static inline unsigned int l4_get_ipc_flags(unsigned int word)
{
return word & L4_IPC_FLAGS_TYPE_MASK;
}
static inline unsigned int l4_get_tag(void)
{
return read_mr(MR_TAG) & L4_IPC_TAG_MASK;
}
static inline void l4_set_tag(unsigned int tag)
{
unsigned int tag_flags = read_mr(MR_TAG);
tag_flags &= ~L4_IPC_TAG_MASK;
tag_flags |= tag & L4_IPC_TAG_MASK;
write_mr(MR_TAG, tag_flags);
}
/* Servers:
* Sets the message register for returning errors back to client task.
* These are usually posix error codes.
*/
static inline void l4_set_retval(int retval)
{
write_mr(MR_RETURN, retval);
}
/* Clients:
* Learn result of request.
*/
static inline int l4_get_retval(void)
{
return read_mr(MR_RETURN);
}
/*
* This is useful for stacked IPC. A stacked IPC happens
* when a new IPC is initiated before concluding the current
* one.
*
* This saves the last ipc's parameters such as the sender
* and tag information. Any previously saved data in save
* slots are destroyed. This is fine as IPC stacking is only
* useful if done once.
*/
static inline void l4_save_ipcregs(void)
{
l4_get_utcb()->saved_sender = l4_get_sender();
l4_get_utcb()->saved_tag = l4_get_tag();
}
static inline void l4_restore_ipcregs(void)
{
l4_set_tag(l4_get_utcb()->saved_tag);
l4_set_sender(l4_get_utcb()->saved_sender);
}
#define TASK_CID_MASK 0xFF000000
#define TASK_ID_MASK 0x00FFFFFF
#define TASK_CID_SHIFT 24
static inline l4id_t __raw_tid(l4id_t tid)
{
return tid & TASK_ID_MASK;
}
static inline l4id_t __cid(l4id_t tid)
{
return (tid & TASK_CID_MASK) >> TASK_CID_SHIFT;
}
static inline l4id_t self_tid(void)
{
struct task_ids ids;
l4_getid(&ids);
return ids.tid;
}
static inline l4id_t __raw_self_tid(void)
{
return __raw_tid(self_tid());
}
static inline int l4_send_full(l4id_t to, unsigned int tag)
{
l4_set_tag(tag);
return l4_ipc(to, L4_NILTHREAD, L4_IPC_FLAGS_FULL);
}
static inline int l4_receive_full(l4id_t from)
{
return l4_ipc(L4_NILTHREAD, from, L4_IPC_FLAGS_FULL);
}
static inline int l4_sendrecv_full(l4id_t to, l4id_t from, unsigned int tag)
{
int err;
BUG_ON(to == L4_NILTHREAD || from == L4_NILTHREAD);
l4_set_tag(tag);
err = l4_ipc(to, from, L4_IPC_FLAGS_FULL);
return err;
}
static inline int l4_send_extended(l4id_t to, unsigned int tag,
unsigned int size, void *buf)
{
unsigned int flags = 0;
l4_set_tag(tag);
/* Set up flags word for extended ipc */
flags = l4_set_ipc_flags(flags, L4_IPC_FLAGS_EXTENDED);
flags = l4_set_ipc_size(flags, size);
flags = l4_set_ipc_msg_index(flags, L4SYS_ARG0);
/* Write buffer pointer to MR index that we specified */
write_mr(L4SYS_ARG0, (unsigned long)buf);
return l4_ipc(to, L4_NILTHREAD, flags);
}
static inline int l4_receive_extended(l4id_t from, unsigned int size, void *buf)
{
unsigned int flags = 0;
/* Indicate extended receive */
flags = l4_set_ipc_flags(flags, L4_IPC_FLAGS_EXTENDED);
/* How much data is accepted */
flags = l4_set_ipc_size(flags, size);
/* Indicate which MR index buffer pointer is stored */
flags = l4_set_ipc_msg_index(flags, L4SYS_ARG0);
/* Set MR with buffer to receive data */
write_mr(L4SYS_ARG0, (unsigned long)buf);
return l4_ipc(L4_NILTHREAD, from, flags);
}
/*
* Return result value as extended IPC.
*
* Extended IPC copies up to 2KB user address space buffers.
* Along with such an ipc, a return value is sent using a primary
* mr that is used as the return register.
*
* It may not be desirable to return a payload on certain conditions,
* (such as an error return value) So a nopayload field is provided.
*/
static inline int l4_return_extended(int retval, unsigned int size,
void *buf, int nopayload)
{
unsigned int flags = 0;
l4id_t sender = l4_get_sender();
l4_set_retval(retval);
/* Set up flags word for extended ipc */
flags = l4_set_ipc_flags(flags, L4_IPC_FLAGS_EXTENDED);
flags = l4_set_ipc_msg_index(flags, L4SYS_ARG0);
/* Write buffer pointer to MR index that we specified */
write_mr(L4SYS_ARG0, (unsigned long)buf);
if (nopayload)
flags = l4_set_ipc_size(flags, 0);
else
flags = l4_set_ipc_size(flags, size);
return l4_ipc(sender, L4_NILTHREAD, flags);
}
static inline int l4_sendrecv_extended(l4id_t to, l4id_t from,
unsigned int tag, void *buf)
{
/* Need to imitate sendrecv but with extended send/recv flags */
return 0;
}
static inline int l4_send(l4id_t to, unsigned int tag)
{
l4_set_tag(tag);
return l4_ipc(to, L4_NILTHREAD, 0);
}
static inline int l4_sendrecv(l4id_t to, l4id_t from, unsigned int tag)
{
int err;
BUG_ON(to == L4_NILTHREAD || from == L4_NILTHREAD);
l4_set_tag(tag);
err = l4_ipc(to, from, 0);
return err;
}
static inline int l4_receive(l4id_t from)
{
return l4_ipc(L4_NILTHREAD, from, 0);
}
static inline void l4_print_mrs()
{
printf("Message registers: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n",
read_mr(0), read_mr(1), read_mr(2), read_mr(3),
read_mr(4), read_mr(5));
}
/* Servers:
* Return the ipc result back to requesting task.
*/
static inline int l4_ipc_return(int retval)
{
l4id_t sender = l4_get_sender();
l4_set_retval(retval);
/* Setting the tag would overwrite retval so we l4_send without tagging */
return l4_ipc(sender, L4_NILTHREAD, 0);
}
void *l4_new_virtual(int npages);
void *l4_del_virtual(void *virt, int npages);
/* A helper that translates and maps a physical address to virtual */
static inline void *l4_map_helper(void *phys, int npages)
{
struct task_ids ids;
int err;
void *virt = l4_new_virtual(npages);
l4_getid(&ids);
if ((err = l4_map(phys, virt, npages,
MAP_USR_RW_FLAGS, ids.tid)) < 0)
return PTR_ERR(err);
return virt;
}
/* A helper that translates and maps a physical address to virtual */
static inline void *l4_unmap_helper(void *virt, int npages)
{
struct task_ids ids;
l4_getid(&ids);
l4_unmap(virt, npages, ids.tid);
l4_del_virtual(virt, npages);
return 0;
}
#define L4_EXIT_MASK 0xFFFF
static inline void l4_exit(unsigned int exit_code)
{
struct task_ids ids;
l4_getid(&ids);
l4_thread_control(THREAD_DESTROY |
(exit_code & L4_EXIT_MASK),
&ids);
}
#endif /* __L4LIB_SYSLIB_H__ */

View File

@@ -1,8 +0,0 @@
#ifndef __L4LIB_ARM_TYPES_H___
#define __L4LIB_ARM_TYPES_H__
#define TASK_ID_INVALID 0xFFFFFFFF
#include <l4/arch/arm/types.h>
#endif /* __L4LIB_ARM_TYPES_H__ */

View File

@@ -1,93 +0,0 @@
/*
* Copyright (C) 2009 Bahadir Bilgehan Balban
*/
#ifndef __ARM_UTCB_H__
#define __ARM_UTCB_H__
#define USER_UTCB_REF 0xFF000050
#define L4_KIP_ADDRESS 0xFF000000
#define UTCB_KIP_OFFSET 0x50
#ifndef __ASSEMBLY__
#include <l4lib/types.h>
#include <l4/macros.h>
#include <l4/lib/math.h>
#include INC_GLUE(message.h)
#include INC_GLUE(memory.h)
#include <string.h>
#include <stdio.h>
/*
* See kernel glue/arch/message.h for utcb details
*/
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()
{
/*
* 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 */
static inline unsigned int read_mr(int offset)
{
if (offset < MR_TOTAL)
return l4_get_utcb()->mr[offset];
else
return l4_get_utcb()->mr_rest[offset - MR_TOTAL];
}
static inline void write_mr(unsigned int offset, unsigned int val)
{
if (offset < MR_TOTAL)
l4_get_utcb()->mr[offset] = val;
else
l4_get_utcb()->mr_rest[offset - MR_TOTAL] = val;
}
static inline void *utcb_full_buffer()
{
return &l4_get_utcb()->mr_rest[0];
}
static inline char *utcb_full_strcpy_from(const char *src)
{
return strncpy((char *)&l4_get_utcb()->mr_rest[0], src,
L4_UTCB_FULL_BUFFER_SIZE);
}
static inline void *utcb_full_memcpy_from(const char *src, int size)
{
return memcpy(&l4_get_utcb()->mr_rest[0], src,
min(size, L4_UTCB_FULL_BUFFER_SIZE));
}
static inline char *utcb_full_strcpy_to(char *dst)
{
return strncpy(dst, (char *)&l4_get_utcb()->mr_rest[0],
L4_UTCB_FULL_BUFFER_SIZE);
}
static inline void *utcb_full_memcpy_to(char *dst, int size)
{
return memcpy(dst, &l4_get_utcb()->mr_rest[0],
min(size, L4_UTCB_FULL_BUFFER_SIZE));
}
#endif /* !__ASSEMBLY__ */
#endif /* __ARM_UTCB_H__ */

View File

@@ -1,44 +0,0 @@
#ifndef __BIT_H__
#define __BIT_H__
#include <l4lib/types.h>
unsigned int __clz(unsigned int bitvector);
int find_and_set_first_free_bit(u32 *word, unsigned int lastbit);
int find_and_set_first_free_contig_bits(u32 *word, unsigned int limit,
int nbits);
int check_and_clear_bit(u32 *word, int bit);
int check_and_clear_contig_bits(u32 *word, int first, int nbits);
int check_and_set_bit(u32 *word, int bit);
/* Set */
static inline void setbit(unsigned int *w, unsigned int flags)
{
*w |= flags;
}
/* Clear */
static inline void clrbit(unsigned int *w, unsigned int flags)
{
*w &= ~flags;
}
/* Test */
static inline int tstbit(unsigned int *w, unsigned int flags)
{
return *w & flags;
}
/* Test and clear */
static inline int tstclr(unsigned int *w, unsigned int flags)
{
int res = tstbit(w, flags);
clrbit(w, flags);
return res;
}
#endif /* __BIT_H__ */

View File

@@ -1,60 +0,0 @@
/*
* Capability-related management.
*
* Copyright (C) 2009 Bahadir Balban
*/
#ifndef __LIBL4_CAPABILITY_H__
#define __LIBL4_CAPABILITY_H__
#include <l4lib/types.h>
#include <l4/lib/list.h>
#include <l4/api/capability.h>
struct cap_list {
int ncaps;
struct link caps;
};
static inline void cap_list_init(struct cap_list *clist)
{
clist->ncaps = 0;
link_init(&clist->caps);
}
static inline void cap_list_insert(struct capability *cap,
struct cap_list *clist)
{
list_insert(&cap->list, &clist->caps);
clist->ncaps++;
}
/* Detach a whole list of capabilities from list head */
static inline struct capability *
cap_list_detach(struct cap_list *clist)
{
struct link *list = list_detach(&clist->caps);
clist->ncaps = 0;
return link_to_struct(list, struct capability, list);
}
/* Attach a whole list of capabilities to list head */
static inline void cap_list_attach(struct capability *cap,
struct cap_list *clist)
{
/* Attach as if cap is the list and clist is the element */
list_insert(&clist->caps, &cap->list);
/* Count the number of caps attached */
list_foreach_struct(cap, &clist->caps, list)
clist->ncaps++;
}
static inline void cap_list_move(struct cap_list *to,
struct cap_list *from)
{
struct capability *cap_head = cap_list_detach(from);
cap_list_attach(cap_head, to);
}
#endif /* __LIBL4_CAPABILITY_H__ */

View File

@@ -1,12 +0,0 @@
#ifndef __CAP_PRINT_H__
#define __CAP_PRINT_H__
#include <l4/api/capability.h>
#include <l4/generic/cap-types.h>
void cap_dev_print(struct capability *cap);
void cap_print(struct capability *cap);
void cap_array_print(int total_caps, struct capability *caparray);
#endif /* __CAP_PRINT_H__*/

View File

@@ -1,31 +0,0 @@
#ifndef __IDPOOL_H__
#define __IDPOOL_H__
#include <l4lib/bit.h>
#include <string.h>
#include <l4/macros.h>
#include INC_GLUE(memory.h)
struct id_pool {
int nwords;
int bitlimit;
u32 bitmap[];
};
/* Copy one id pool to another by calculating its size */
static inline void id_pool_copy(struct id_pool *to, struct id_pool *from, int totalbits)
{
int nwords = BITWISE_GETWORD(totalbits);
memcpy(to, from, nwords * SZ_WORD + sizeof(struct id_pool));
}
struct id_pool *id_pool_new_init(int mapsize);
int id_new(struct id_pool *pool);
int id_del(struct id_pool *pool, int id);
int id_get(struct id_pool *pool, int id);
int id_is_empty(struct id_pool *pool);
int ids_new_contiguous(struct id_pool *pool, int numids);
int ids_del_contiguous(struct id_pool *pool, int first, int numids);
#endif /* __IDPOOL_H__ */

View File

@@ -1,19 +0,0 @@
/*
* Stack space helper routines.
*
* Copyright (C) 2009 B Labs Ltd.
*/
#ifndef __LIB_STACK_H__
#define __LIB_STACK_H__
/* Checks if l4_set_stack_params is called. */
#define IS_STACK_SETUP() (lib_stack_size)
int stack_pool_init(unsigned long stack_start,
unsigned long stack_end,
unsigned long stack_size);
void *get_stack_space(void);
int delete_stack_space(void *stack_address);
#endif /* __LIB_STACK_H__ */

View File

@@ -1,43 +0,0 @@
/*
* Thread control block.
*
* Copyright (C) 2009 B Labs Ltd.
*/
#ifndef __LIB_TCB_H__
#define __LIB_TCB_H__
#include <l4/lib/list.h>
/* Keeps all the struct utcb_descs belonging to a thread group together. */
struct l4lib_utcb_head {
struct link list;
};
/* A simple thread control block for the thread library. */
struct l4lib_tcb {
/* Task list */
struct link list;
/* Task id */
int tid;
/* Chain of utcb descriptors */
struct l4lib_utcb_head *utcb_head;
/* Stack and utcb address */
unsigned long utcb_addr;
unsigned long stack_addr;
};
/* All the threads handled by the thread lib are kept in this list. */
struct l4lib_global_list {
int total;
struct link list;
};
struct l4lib_tcb *l4lib_find_task(int tid);
struct l4lib_tcb *l4_tcb_alloc_init(struct l4lib_tcb *parent, unsigned int flags);
void l4lib_global_add_task(struct l4lib_tcb *task);
void l4lib_global_remove_task(struct l4lib_tcb *task);
#endif /* __LIB_TCB_H__ */

View File

@@ -1,36 +0,0 @@
#ifndef __L4_THREAD_H__
#define __L4_THREAD_H__
#include <l4lib/arch/utcb.h>
#include <l4lib/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 */
};
/* -- Bora start -- */
/*
* A helper macro easing utcb space creation,
* FIXME: We need to fix address allocation path, so as to use
* actual size of units instead of page size
*/
#define DECLARE_UTCB_SPACE(name, entries) \
char name[entries * PAGE_SIZE] ALIGN(PAGE_SIZE);
int l4_set_stack_params(unsigned long stack_top,
unsigned long stack_bottom,
unsigned long stack_size);
int l4_set_utcb_params(unsigned long utcb_start, unsigned long utcb_end);
int l4_thread_create(struct task_ids *ids, unsigned int flags,
int (*func)(void *), void *arg);
void l4_thread_exit(int retval);
/* -- Bora start -- */
#endif /* __L4_THREAD_H__ */

View File

@@ -1,33 +0,0 @@
/*
* UTCB handling common helper routines.
*
* Copyright (C) 2009 B Labs Ltd.
*/
#ifndef __UTCB_COMMON_H__
#define __UTCB_COMMON_H__
#include <l4/lib/list.h>
#include <l4lib/thread/tcb.h>
struct l4lib_utcb_desc {
struct link list;
unsigned long utcb_base;
struct id_pool *slots;
};
int utcb_pool_init(unsigned long utcb_start, unsigned long utcb_end);
unsigned long utcb_new_slot(struct l4lib_utcb_desc *desc);
int utcb_delete_slot(struct l4lib_utcb_desc *desc, unsigned long address);
struct l4lib_utcb_desc *utcb_new_desc(void);
int utcb_delete_desc(struct l4lib_utcb_desc *desc);
/* Checks if l4_set_stack_params is called. */
#define IS_UTCB_SETUP() (lib_utcb_range_size)
unsigned long get_utcb_addr(struct l4lib_tcb *task);
int delete_utcb_addr(struct l4lib_tcb *task);
#endif /* __UTCB_COMMON_H__ */

View File

@@ -1,57 +0,0 @@
/*
* This module allocates an unused address range from
* a given memory region defined as the pool range.
*
* Copyright (C) 2007 Bahadir Balban
*/
#include <l4lib/addr.h>
#include <stdio.h>
/*
* Initializes an address pool, but uses an already
* allocated id pool for it.
*/
int address_pool_init_with_idpool(struct address_pool *pool,
struct id_pool *idpool,
unsigned long start, unsigned long end)
{
pool->idpool = idpool;
pool->start = start;
pool->end = end;
return 0;
}
int address_pool_init(struct address_pool *pool,
unsigned long start, unsigned long end,
unsigned int size)
{
if ((pool->idpool = id_pool_new_init(__pfn(end - start) )) < 0)
return (int)pool->idpool;
pool->start = start;
pool->end = end;
return 0;
}
void *address_new(struct address_pool *pool, int nitems, int size)
{
unsigned int idx;
if ((int)(idx = ids_new_contiguous(pool->idpool, nitems)) < 0)
return 0;
return (void *)(idx * size) + pool->start;
}
int address_del(struct address_pool *pool, void *addr, int nitems, int size)
{
unsigned long idx = (addr - (void *)pool->start) / size;
if (ids_del_contiguous(pool->idpool, idx, nitems) < 0) {
printf("%s: Invalid address range returned to "
"virtual address pool.\n", __FUNCTION__);
return -1;
}
return 0;
}

View File

@@ -1,84 +0,0 @@
/*
* Generic to arch-specific interface for
* exchange_registers()
*
* Copyright (C) 2008 Bahadir Balban
*/
#include <l4/macros.h>
#include <l4lib/exregs.h>
#include <l4lib/arch/syslib.h>
#include INC_GLUE(message.h)
void exregs_print_registers(void)
{
struct exregs_data exregs;
/* Read registers */
memset(&exregs, 0, sizeof(exregs));
exregs.valid_vect = ~0; /* Set all flags */
exregs.flags |= EXREGS_READ;
exregs.flags |= EXREGS_SET_UTCB;
exregs.flags |= EXREGS_SET_PAGER;
BUG_ON(l4_exchange_registers(&exregs, self_tid()) < 0);
/* Print out registers */
printf("Task (%x) register state upon fault:\n", self_tid());
printf("R0: 0x%x\n", exregs.context.r0);
printf("R1: 0x%x\n", exregs.context.r1);
printf("R2: 0x%x\n", exregs.context.r2);
printf("R3: 0x%x\n", exregs.context.r3);
printf("R4: 0x%x\n", exregs.context.r4);
printf("R5: 0x%x\n", exregs.context.r5);
printf("R6: 0x%x\n", exregs.context.r6);
printf("R7: 0x%x\n", exregs.context.r7);
printf("R8: 0x%x\n", exregs.context.r8);
printf("R9: 0x%x\n", exregs.context.r9);
printf("R10: 0x%x\n", exregs.context.r10);
printf("R11: 0x%x\n", exregs.context.r11);
printf("R12: 0x%x\n", exregs.context.r12);
printf("R13: 0x%x\n", exregs.context.sp);
printf("R14: 0x%x\n", exregs.context.lr);
printf("R15: 0x%x\n", exregs.context.pc);
printf("Pager: 0x%x\n", exregs.pagerid);
printf("Utcb @ 0x%lx\n", exregs.utcb_address);
}
void exregs_set_mr(struct exregs_data *s, int offset, unsigned long val)
{
/* Get MR0 */
u32 *mr = &s->context.MR0_REGISTER;
/* Sanity check */
BUG_ON(offset > MR_TOTAL || offset < 0);
/* Set MR */
mr[offset] = val;
/* Set valid bit for mr register */
s->valid_vect |= FIELD_TO_BIT(exregs_context_t, MR0_REGISTER) << offset;
}
void exregs_set_pager(struct exregs_data *s, l4id_t pagerid)
{
s->pagerid = pagerid;
s->flags |= EXREGS_SET_PAGER;
}
void exregs_set_utcb(struct exregs_data *s, unsigned long virt)
{
s->utcb_address = virt;
s->flags |= EXREGS_SET_UTCB;
}
void exregs_set_stack(struct exregs_data *s, unsigned long sp)
{
s->context.sp = sp;
s->valid_vect |= FIELD_TO_BIT(exregs_context_t, sp);
}
void exregs_set_pc(struct exregs_data *s, unsigned long pc)
{
s->context.pc = pc;
s->valid_vect |= FIELD_TO_BIT(exregs_context_t, pc);
}

View File

@@ -1,75 +0,0 @@
/*
* Copyright (C) 2009 Bahadir Balban
*/
#include <l4lib/arch/asm.h>
#include <l4lib/mutex.h>
/*
* NOTES:
*
* Recap on swp:
*
* swp rx, ry, [rz]
*
* In one instruction:
*
* 1) Stores the value in ry into location pointed by rz.
* 2) Loads the value in the location of rz into rx.
* By doing so, in one instruction one can attempt to lock
* a word, and discover whether it was already locked.
*
* Why use tid of thread to lock mutex instead of
* a single lock value?
*
* Because in one atomic instruction, not only the locking attempt
* should be able to indicate whether it is locked, but also
* the contentions. A unified lock value would not be sufficient.
* The only way to indicate a contended lock is to store the
* unique TID of the locker.
*/
/*
* Any non-negative value that is a potential TID
* (including 0) means mutex is locked.
*/
/*
* @r0 = address of mutex word
* @r1 = unique tid of current thread
*/
BEGIN_PROC(__l4_mutex_lock)
swp r2, r1, [r0]
cmp r2, #L4_MUTEX_UNLOCKED @ Was the lock available?
movne r0, #L4_MUTEX_CONTENDED @ Indicate failure
moveq r0, #L4_MUTEX_SUCCESS @ Indicate success
mov pc, lr
END_PROC(__l4_mutex_lock)
/*
* @r0 = address of mutex word
* @r1 = unique tid of current thread
*/
BEGIN_PROC(__l4_mutex_unlock)
mov r3, #L4_MUTEX_UNLOCKED
swp r2, r3, [r0]
cmp r2, r1 @ Check lock had original tid value
movne r0, #L4_MUTEX_CONTENDED @ Indicate contention
moveq r0, #L4_MUTEX_SUCCESS @ Indicate no contention
cmp r2, #L4_MUTEX_UNLOCKED @ Or - was it already unlocked?
1:
beq 1b @ If so busy-spin to indicate bug.
mov pc, lr
END_PROC(__l4_mutex_unlock)
/*
* r0 = byte address to read from.
*/
BEGIN_PROC(l4_atomic_dest_readb)
mov r1, r0 @ Move byte address to r1
mov r2, #0 @ Move 0 to r2
swpb r0, r2, [r1] @ Write 0 to byte location, while reading its value to r0
mov pc, lr @ Return byte location value
END_PROC(l4_atomic_dest_readb)

View File

@@ -1,12 +0,0 @@
#include <l4lib/arch/asm.h>
BEGIN_PROC(setup_new_thread)
ldr r0, [sp], #-4 @ Load first argument
mov lr, pc @ Save return address
ldr pc, [sp], #-4 @ Load function pointer from stack
b l4_thread_exit @ Call l4_thread_exit for cleanup
new_thread_exit:
b new_thread_exit @ Never reaches here
END_PROC(setup_new_thread)

View File

@@ -1,220 +0,0 @@
/*
* Userspace system call interface.
*
* Copyright (C) 2007 - 2009 Bahadir Balban
*/
#include <l4lib/arch/asm.h>
#include <l4lib/arch/utcb.h>
#include <l4/generic/space.h>
#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 pointer to UTCB address from UTCB pointer in KIP
ldr \rx, [\rx] @ Get the utcb address
.endm
BEGIN_PROC(l4_thread_switch)
ldr r12, =__l4_thread_switch
ldr pc, [r12] @ Jump into the SWI. Kernel returns to LR_USR, which is the caller.
END_PROC(l4_thread_switch)
/*
* The syscall returns process ids. This function saves the returned values in the
* arguments passed by reference. @r0 = struct task_ids *
*/
BEGIN_PROC(l4_getid)
ldr r12, =__l4_getid @ See l4_kdata_read for why its so simple.
ldr pc, [r12] @ Return.
END_PROC(l4_getid)
/*
* For clone() we need special assembler handling
* Same signature as ipc(): @r0 = to, @r1 = from @r2 = flags
*
* NOTE: Note that this breaks l4 system call interface,
* this should be moved elsewhere and modified using existing l4 mechanisms.
*/
BEGIN_PROC(arch_clone)
stmfd sp!, {r4-r8,lr} @ Save context.
utcb_address r12 @ Get utcb address.
ldmia r12!, {r3-r8} @ Load 6 Message registers from utcb. MR0-MR5
ldr r12, =__l4_ipc
mov lr, pc
ldr pc, [r12] @ Perform the ipc()
/*
* At this moment:
* - MR_RETURN tells us whether we are parent or child (or have failed).
* - Child has new SP set, with |func_ptr|arg1|{End of stack}SP<-| on stack.
* - Child needs exit logic when its function is finished.
*/
cmp r0, #0 @ Check ipc success
blt ipc_failed
cmp MR_RETURN_REGISTER, #0 @ Check ipc return register MR_RETURN.
blt clone_failed @ Ipc was ok but clone() failed.
bgt parent_return @ It has child pid, goto parent return.
child:
ldr r0, [sp, #-4]! @ Load child's first argument.
mov lr, pc @ Save return address
ldr pc, [sp, #-4]! @ Load function pointer from stack
child_exit:
b child_exit @ We infinitely loop for now.
@ Return with normal ipc return sequence
parent_return:
clone_failed:
ipc_failed:
utcb_address r12 @ Get utcb
stmia r12, {r3-r8} @ Store mrs.
ldmfd sp!, {r4-r8,pc} @ Return restoring pc and context.
END_PROC(arch_clone)
/*
* Inter-process communication. Loads message registers as arguments before the call,
* and stores them as results after the call. @r0 = to, @r1 = from.
*/
BEGIN_PROC(l4_ipc)
stmfd sp!, {r4-r8,lr} @ Save context.
utcb_address r12 @ Get utcb address.
ldmia r12!, {r3-r8} @ Load 6 Message registers from utcb. MR0-MR5
ldr r12, =__l4_ipc
mov lr, pc
ldr pc, [r12]
utcb_address r12 @ Get utcb address.
stmia r12, {r3-r8} @ Store 6 Message registers to utcb. MR0-MR5
ldmfd sp!, {r4-r8,pc} @ Return restoring pc, and context.
END_PROC(l4_ipc)
/*
* System call that maps an area of memory into the given address space.
* @r0 = physical address, @r1 = virtual address, @r2 = map size in pages,
* @r3 = map flags, @r4 = The tgid of the address space to map.
*/
BEGIN_PROC(l4_map)
stmfd sp!, {r4, lr}
ldr r4, [sp, #8] @ FIXME: Is this right?
ldr r12, =__l4_map
mov lr, pc @ We must return here to restore r4.
ldr pc, [r12]
ldmfd sp!, {r4, pc}
END_PROC(l4_map)
/*
* Reads/manipulates capabilities of a thread, particularly a pager.
* @r0 = request type, @r1 = request flags, @r2 = Capability buffer pointer
*/
BEGIN_PROC(l4_capability_control)
stmfd sp!, {lr}
ldr r12, =__l4_capability_control
mov lr, pc
ldr pc, [r12]
ldmfd sp!, {pc} @ Restore original lr and return.
END_PROC(l4_capability_control)
/*
* System call that unmaps an area of memory into the given address space.
* @r0 = virtual, @r1 = pages, @r2 = tid of address space to unmap
*/
BEGIN_PROC(l4_unmap)
stmfd sp!, {lr}
ldr r12, =__l4_unmap
mov lr, pc
ldr pc, [r12]
ldmfd sp!, {pc} @ Restore original lr and return.
END_PROC(l4_unmap)
/*
* System call that controls containers and their parameters.
* @r0 = request type, @r1 = request flags, @r2 = io buffer ptr
*/
BEGIN_PROC(l4_container_control)
stmfd sp!, {lr}
ldr r12, =__l4_container_control
mov lr, pc
ldr pc, [r12]
ldmfd sp!, {pc} @ Restore original lr and return.
END_PROC(l4_container_control)
/*
* System call that gets or sets the time info structure.
* @r0 = ptr to time structure @r1 = set or get. set = 1, get = 0.
*/
BEGIN_PROC(l4_time)
stmfd sp!, {lr}
ldr r12, =__l4_time
mov lr, pc
ldr pc, [r12]
ldmfd sp!, {pc} @ Restore original lr and return.
END_PROC(l4_time)
/*
* System call that controls thread creation, destruction and modification.
* @r0 = thread action, @r1 = &ids, @r2 = utcb address
*/
BEGIN_PROC(l4_thread_control)
stmfd sp!, {lr}
ldr r12, =__l4_thread_control
mov lr, pc
ldr pc, [r12]
ldmfd sp!, {pc} @ Restore original lr and return.
END_PROC(l4_thread_control)
/*
* System call that modifies ipc blocked sender lists of receivers.
* @r0 = Action (e.g. block/unblock), @r1 = sender id, @r2 = sender tag
*/
BEGIN_PROC(l4_ipc_control)
stmfd sp!, {lr}
ldr r12, =__l4_ipc_control
mov lr, pc
ldr pc, [r12]
ldmfd sp!, {pc} @ Restore original lr and return.
END_PROC(l4_ipc_control)
/*
* Manipulates address spaces, e.g. sets up shared memory areas between threads
* @r0 = operation code, @r1 = operation flags, @r2 = An id (irqnum, or capid)
*/
BEGIN_PROC(l4_irq_control)
stmfd sp!, {lr}
ldr r12, =__l4_irq_control
mov lr, pc
ldr pc, [r12]
ldmfd sp!, {pc} @ Restore original lr and return.
END_PROC(l4_irq_control)
/*
* Locks/unlocks a userspace mutex.
* @r0 = mutex virtual address, @r1 = mutex operation code
*/
BEGIN_PROC(l4_mutex_control)
stmfd sp!, {lr}
ldr r12, =__l4_mutex_control
mov lr, pc
ldr pc, [r12]
ldmfd sp!, {pc} @ Restore original lr and return.
END_PROC(l4_mutex_control)
/*
* Sets registers of a thread and its pager.
* @r0 = ptr to exregs_data structure, @r1 = tid of thread.
*/
BEGIN_PROC(l4_exchange_registers)
stmfd sp!, {lr}
ldr r12, =__l4_exchange_registers
mov lr, pc
ldr pc, [r12]
ldmfd sp!, {pc} @ Restore original lr and return.
END_PROC(l4_exchange_registers)

View File

@@ -1,109 +0,0 @@
/*
* Bit manipulation functions.
*
* Copyright (C) 2007 Bahadir Balban
*/
#include <l4lib/bit.h>
#include <stdio.h>
#include <l4/macros.h>
#include INC_GLUE(memory.h)
/* Emulation of ARM's CLZ (count leading zeroes) instruction */
unsigned int __clz(unsigned int bitvector)
{
unsigned int x = 0;
while((!(bitvector & ((unsigned)1 << 31))) && (x < 32)) {
bitvector <<= 1;
x++;
}
return x;
}
int find_and_set_first_free_bit(u32 *word, unsigned int limit)
{
int success = 0;
int i;
for(i = 0; i < limit; i++) {
/* Find first unset bit */
if (!(word[BITWISE_GETWORD(i)] & BITWISE_GETBIT(i))) {
/* Set it */
word[BITWISE_GETWORD(i)] |= BITWISE_GETBIT(i);
success = 1;
break;
}
}
/* Return bit just set */
if (success)
return i;
else
return -1;
}
int find_and_set_first_free_contig_bits(u32 *word, unsigned int limit,
int nbits)
{
int i = 0, first = 0, last = 0, found = 0;
/* Can't allocate more than the limit */
if (nbits > limit)
return -1;
/* This is a state machine that checks n contiguous free bits. */
while (i + nbits <= limit) {
first = i;
last = i;
while (!(word[BITWISE_GETWORD(last)] & BITWISE_GETBIT(last))) {
last++;
i++;
if (last == first + nbits) {
found = 1;
break;
}
}
if (found)
break;
i++;
}
/* If found, set the bits */
if (found) {
for (int x = first; x < first + nbits; x++)
word[BITWISE_GETWORD(x)] |= BITWISE_GETBIT(x);
return first;
} else
return -1;
}
int check_and_clear_bit(u32 *word, int bit)
{
/* Check that bit was set */
if (word[BITWISE_GETWORD(bit)] & BITWISE_GETBIT(bit)) {
word[BITWISE_GETWORD(bit)] &= ~BITWISE_GETBIT(bit);
return 0;
} else {
printf("Trying to clear already clear bit\n");
return -1;
}
}
int check_and_set_bit(u32 *word, int bit)
{
/* Check that bit was clear */
if (!(word[BITWISE_GETWORD(bit)] & BITWISE_GETBIT(bit))) {
word[BITWISE_GETWORD(bit)] |= BITWISE_GETBIT(bit);
return 0;
} else {
//printf("Trying to set already set bit\n");
return -1;
}
}
int check_and_clear_contig_bits(u32 *word, int first, int nbits)
{
for (int i = first; i < first + nbits; i++)
if (check_and_clear_bit(word, i) < 0)
return -1;
return 0;
}

View File

@@ -1,117 +0,0 @@
/* Capability printing generic routines */
#include <l4lib/capability/cap_print.h>
#include <stdio.h>
void cap_dev_print(struct capability *cap)
{
switch (cap_devtype(cap)) {
case CAP_DEVTYPE_UART:
printf("Device type:\t\t\t%s%d\n", "UART", cap_devnum(cap));
break;
case CAP_DEVTYPE_TIMER:
printf("Device type:\t\t\t%s%d\n", "Timer", cap_devnum(cap));
break;
case CAP_DEVTYPE_CLCD:
printf("Device type:\t\t\t%s%d\n", "CLCD", cap_devnum(cap));
break;
default:
return;
}
printf("Device Irq:\t\t%d\n", cap->irq);
}
void cap_print(struct capability *cap)
{
printf("Capability id:\t\t\t%d\n", cap->capid);
printf("Capability resource id:\t\t%d\n", cap->resid);
printf("Capability owner id:\t\t%d\n",cap->owner);
switch (cap_type(cap)) {
case CAP_TYPE_TCTRL:
printf("Capability type:\t\t%s\n", "Thread Control");
break;
case CAP_TYPE_EXREGS:
printf("Capability type:\t\t%s\n", "Exchange Registers");
break;
case CAP_TYPE_MAP_PHYSMEM:
if (!cap_is_devmem(cap)) {
printf("Capability type:\t\t%s\n", "Map/Physmem");
} else {
printf("Capability type:\t\t%s\n", "Map/Physmem/Device");
cap_dev_print(cap);
}
break;
case CAP_TYPE_MAP_VIRTMEM:
printf("Capability type:\t\t%s\n", "Map/Virtmem");
break;
case CAP_TYPE_IPC:
printf("Capability type:\t\t%s\n", "Ipc");
break;
case CAP_TYPE_UMUTEX:
printf("Capability type:\t\t%s\n", "Mutex");
break;
case CAP_TYPE_IRQCTRL:
printf("Capability type:\t\t%s\n", "IRQ Control");
break;
case CAP_TYPE_QUANTITY:
printf("Capability type:\t\t%s\n", "Quantitative");
break;
case CAP_TYPE_CAP:
printf("Capability type:\t\t%s\n", "Capability Control");
break;
default:
printf("Capability type:\t\t%s, cap_type=0x%x\n",
"Unknown", cap_type(cap));
break;
}
switch (cap_rtype(cap)) {
case CAP_RTYPE_THREAD:
printf("Capability resource type:\t%s\n", "Thread");
break;
case CAP_RTYPE_SPACE:
printf("Capability resource type:\t%s\n", "Space");
break;
case CAP_RTYPE_CONTAINER:
printf("Capability resource type:\t%s\n", "Container");
break;
case CAP_RTYPE_THREADPOOL:
printf("Capability resource type:\t%s\n", "Thread Pool");
break;
case CAP_RTYPE_SPACEPOOL:
printf("Capability resource type:\t%s\n", "Space Pool");
break;
case CAP_RTYPE_MUTEXPOOL:
printf("Capability resource type:\t%s\n", "Mutex Pool");
break;
case CAP_RTYPE_MAPPOOL:
printf("Capability resource type:\t%s\n", "Map Pool (PMDS)");
break;
case CAP_RTYPE_CPUPOOL:
printf("Capability resource type:\t%s\n", "Cpu Pool");
break;
case CAP_RTYPE_CAPPOOL:
printf("Capability resource type:\t%s\n", "Capability Pool");
break;
default:
printf("Capability resource type:\t%s, id=0x%x\n", "Unknown",
cap_rtype(cap));
break;
}
printf("\n");
}
void cap_array_print(int total_caps, struct capability *caparray)
{
printf("Capabilities\n"
"~~~~~~~~~~~~\n");
for (int i = 0; i < total_caps; i++)
cap_print(&caparray[i]);
printf("\n");
}

View File

@@ -1,87 +0,0 @@
/*
* Used for thread and space ids, and also for
* utcb tracking in page-sized-chunks.
*
* Copyright (C) 2009 B Labs Ltd.
*/
#include <l4lib/idpool.h>
#include <stdio.h>
#include <l4/api/errno.h>
#include <malloc/malloc.h>
struct id_pool *id_pool_new_init(int totalbits)
{
int nwords = BITWISE_GETWORD(totalbits) + 1;
struct id_pool *new = kzalloc((nwords * SZ_WORD)
+ sizeof(struct id_pool));
if (!new)
return PTR_ERR(-ENOMEM);
new->nwords = nwords;
new->bitlimit = totalbits;
return new;
}
/* Search for a free slot up to the limit given */
int id_new(struct id_pool *pool)
{
return find_and_set_first_free_bit(pool->bitmap, pool->bitlimit);
}
/* This finds n contiguous free ids, allocates and returns the first one */
int ids_new_contiguous(struct id_pool *pool, int numids)
{
int id = find_and_set_first_free_contig_bits(pool->bitmap,
pool->bitlimit,
numids);
if (id < 0)
printf("%s: Warning! New id alloc failed\n", __FUNCTION__);
return id;
}
/* This deletes a list of contiguous ids given the first one and number of ids */
int ids_del_contiguous(struct id_pool *pool, int first, int numids)
{
int ret;
if (pool->nwords * WORD_BITS < first + numids)
return -1;
if ((ret = check_and_clear_contig_bits(pool->bitmap, first, numids)))
printf("%s: Error: Invalid argument range.\n", __FUNCTION__);
return ret;
}
int id_del(struct id_pool *pool, int id)
{
int ret;
if (pool->nwords * WORD_BITS < id)
return -1;
if ((ret = check_and_clear_bit(pool->bitmap, id) < 0))
printf("%s: Error: Could not delete id.\n", __FUNCTION__);
return ret;
}
/* Return a specific id, if available */
int id_get(struct id_pool *pool, int id)
{
int ret;
ret = check_and_set_bit(pool->bitmap, id);
if (ret < 0)
return ret;
else
return id;
}
int id_is_empty(struct id_pool *pool)
{
for (int i = 0; i < pool->nwords; i++)
if (pool->bitmap[i])
return 0;
return 1;
}

View File

@@ -1,97 +0,0 @@
/*
* Stack management in libl4thread.
*
* Copyright © 2009 B Labs Ltd.
*/
#include <stdio.h>
#include <l4/api/errno.h>
#include <l4lib/addr.h>
#include <l4lib/mutex.h>
#include <l4lib/thread/stack.h>
/* Extern declarations */
extern struct l4_mutex lib_mutex;
/* Global variables */
unsigned long lib_stack_size;
/* Stack virtual region pool */
static struct address_pool stack_region_pool;
int stack_pool_init(unsigned long stack_start,
unsigned long stack_end,
unsigned long stack_size)
{
int err;
/* Initialise the global stack virtual address pool. */
if ((err = address_pool_init(&stack_region_pool,
stack_start, stack_end,
stack_size) < 0)) {
printf("Stack address pool initialisation failed.\n");
return err;
}
return 0;
}
void *get_stack_space(void)
{
return address_new(&stack_region_pool, 1, lib_stack_size);
}
int delete_stack_space(void *stack_address)
{
return address_del(&stack_region_pool, stack_address, 1, lib_stack_size);
}
int l4_set_stack_params(unsigned long stack_top,
unsigned long stack_bottom,
unsigned long stack_size)
{
/* Ensure that arguments are valid. */
if (IS_STACK_SETUP()) {
printf("libl4thread: You have already called: %s.\n",
__FUNCTION__);
return -EPERM;
}
if (!stack_top || !stack_bottom) {
printf("libl4thread: Stack address range cannot contain "
"0x0 as a start and/or end address(es).\n");
return -EINVAL;
}
// FIXME: Aligning should be taken into account.
/*
* Stack grows downward so the top of the stack will have
* the lowest numbered address.
*/
if (stack_top >= stack_bottom) {
printf("libl4thread: Stack bottom address must be bigger "
"than stack top address.\n");
return -EINVAL;
}
if (!stack_size) {
printf("libl4thread: Stack size cannot be zero.\n");
return -EINVAL;
}
/* stack_size at least must be equal to the difference. */
if ((stack_bottom - stack_top) < stack_size) {
printf("libl4thread: The given range size is lesser than "
"the stack size(0x%x).\n", stack_size);
return -EINVAL;
}
/* Arguments passed the validity tests. */
/* Initialize internal variables. */
lib_stack_size = stack_size;
/* Initialize stack virtual address pool. */
if (stack_pool_init(stack_top, stack_bottom, stack_size) < 0)
BUG();
/* Initialize the global mutex. */
l4_mutex_init(&lib_mutex);
return 0;
}

View File

@@ -1,65 +0,0 @@
/*
* Thread management in libl4thread.
*
* Copyright (C) 2009 B Labs Ltd.
*/
#include <stdio.h>
#include <malloc/malloc.h>
#include <l4/api/errno.h>
#include <l4/api/thread.h>
#include <l4lib/thread/tcb.h>
#include <l4/macros.h>
/* Global task list. */
struct l4lib_global_list global_tasks = {
.list = { &global_tasks.list, &global_tasks.list },
.total = 0,
};
/* Function definitions */
void l4lib_global_add_task(struct l4lib_tcb *task)
{
BUG_ON(!list_empty(&task->list));
list_insert_tail(&task->list, &global_tasks.list);
global_tasks.total++;
}
void l4lib_global_remove_task(struct l4lib_tcb *task)
{
BUG_ON(list_empty(&task->list));
list_remove_init(&task->list);
BUG_ON(--global_tasks.total < 0);
}
struct l4lib_tcb * l4lib_find_task(int tid)
{
struct l4lib_tcb *t;
list_foreach_struct(t, &global_tasks.list, list)
if (t->tid == tid)
return t;
return 0;
}
struct l4lib_tcb *l4_tcb_alloc_init(struct l4lib_tcb *parent, unsigned int flags)
{
struct l4lib_tcb *task;
if (!(task = kzalloc(sizeof(struct l4lib_tcb))))
return PTR_ERR(-ENOMEM);
link_init(&task->list);
if (flags & TC_SHARE_SPACE)
task->utcb_head = parent->utcb_head;
else {
/* COPY or NEW space */
if (!(task->utcb_head = kzalloc(sizeof(struct l4lib_utcb_head)))) {
kfree(task);
return PTR_ERR(-ENOMEM);
}
link_init(&task->utcb_head->list);
}
return task;
}

View File

@@ -1,210 +0,0 @@
/*
* Thread creation userspace helpers
*
* Copyright (C) 2009 B Labs Ltd.
*/
#include <stdio.h>
#include <malloc/malloc.h>
#include <l4lib/arch/syscalls.h>
#include <l4lib/arch/syslib.h>
#include <l4lib/exregs.h>
#include <l4lib/mutex.h>
#include <l4/api/thread.h>
#include <l4/api/errno.h>
#include <l4lib/thread/utcb-common.h>
#include <l4lib/thread/stack.h>
/* Extern declarations */
extern void setup_new_thread(void);
extern unsigned long lib_stack_size;
extern unsigned long lib_utcb_range_size;
/* Static variable definitions */
struct l4_mutex lib_mutex;
/* Function definitions */
int l4_thread_create(struct task_ids *ids, unsigned int flags,
int (*func)(void *), void *arg)
{
struct exregs_data exregs;
unsigned long utcb_addr;
struct l4lib_tcb *parent, *child;
unsigned long stack_top_addr, stack_bot_addr;
int err = 0;
/* A few controls before granting access to thread creation */
if (!IS_STACK_SETUP() || !IS_UTCB_SETUP()) {
printf("libl4thread: Stack and/or utcb have not been "
"set up.\n");
return -EPERM;
}
/* Before doing any operation get the global mutex. */
l4_mutex_lock(&lib_mutex);
/* Get parent's ids and find the l4lib_tcb belonging to it. */
l4_getid(ids);
if (!(parent = l4lib_find_task(ids->tid))) {
err = -ESRCH;
goto out_err1;
}
/* Allocate l4lib_tcb for the child. */
if (!(child = l4_tcb_alloc_init(parent, flags))) {
// FIXME: What happens to utcb_head
printf("libl4thread: No heap space left.\n");
err = -ENOMEM;
goto out_err1;
}
/* Get a utcb addr. */
if (!(utcb_addr = get_utcb_addr(child))) {
printf("libl4thread: No utcb space left.\n");
err = -ENOMEM;
goto out_err2;
}
/* Get a stack space and calculate the bottom addr of the stack. */
stack_top_addr = (unsigned long)get_stack_space();
if (!stack_top_addr) {
printf("libl4thread: No stack space left.\n");
err = -ENOMEM;
goto out_err3;
}
stack_bot_addr = stack_top_addr + lib_stack_size;
child->stack_addr = stack_top_addr;
/* Create thread */
if ((err = l4_thread_control(THREAD_CREATE | flags, ids)) < 0) {
printf("libl4thread: l4_thread_control(THREAD_CREATE) "
"failed with (%d).\n", err);
goto out_err4;
}
/* Setup new thread pc, sp, utcb */
memset(&exregs, 0, sizeof(exregs));
exregs_set_stack(&exregs, align((stack_bot_addr - 1), 8));
exregs_set_pc(&exregs, (unsigned long)setup_new_thread);
exregs_set_utcb(&exregs, (unsigned long)utcb_addr);
if ((err = l4_exchange_registers(&exregs, ids->tid)) < 0) {
printf("libl4thread: l4_exchange_registers failed with "
"(%d).\n", err);
goto out_err5;
}
/* First word of new stack is arg */
((unsigned long *)align((stack_bot_addr - 1), 8))[0] =
(unsigned long)arg;
/* Second word of new stack is function address */
((unsigned long *)align((stack_bot_addr - 1), 8))[-1] =
(unsigned long)func;
/* Add child to the global task list */
child->tid = ids->tid;
l4lib_global_add_task(child);
/* Start the new thread */
if ((err = l4_thread_control(THREAD_RUN, ids)) < 0) {
printf("libl4thread: l4_thread_control(THREAD_RUN) "
"failed with (%d).\n", err);
goto out_err6;
}
/* Release the global mutex. */
l4_mutex_unlock(&lib_mutex);
return 0;
/* Error handling. */
out_err6:
l4lib_global_remove_task(child);
out_err5:
l4_thread_control(THREAD_DESTROY, ids);
out_err4:
delete_stack_space((void *)child->stack_addr);
out_err3:
delete_utcb_addr(child);
out_err2:
if ((flags & TC_COPY_SPACE) || (flags & TC_NEW_SPACE))
kfree(child->utcb_head);
kfree(child);
out_err1:
l4_mutex_unlock(&lib_mutex);
return err;
}
void l4_thread_exit(int retval)
{
struct l4lib_tcb *task;
struct task_ids ids;
/* Before doing any operation get the global mutex. */
l4_mutex_lock(&lib_mutex);
/* Find the task. */
l4_getid(&ids);
/* Cant find the thread means it wasnt added to the list. */
if (!(task = l4lib_find_task(ids.tid)))
BUG();
/* Remove child from the global task list. */
l4lib_global_remove_task(task);
/* Delete the stack space. */
if (delete_stack_space((void *)task->stack_addr) < 0)
BUG();
/* Delete the utcb address. */
delete_utcb_addr(task);
// FIXME: We assume that main thread never leaves the scene
// FIXME: What happens to task->utcb_head?
kfree(task);
/* Release the global mutex. */
l4_mutex_unlock(&lib_mutex);
/* Relinquish the control. */
l4_exit(retval);
/* Should never reach here. */
BUG();
}
int l4_thread_kill(struct task_ids *ids)
{
struct l4lib_tcb *task;
/* Before doing any operation get the global mutex. */
l4_mutex_lock(&lib_mutex);
/* Find the task to be killed. */
if (!(task = l4lib_find_task(ids->tid))) {
l4_mutex_unlock(&lib_mutex);
return -ESRCH;
}
/* Remove child from the global task list. */
l4lib_global_remove_task(task);
/* Delete the stack space. */
if (delete_stack_space((void *)task->stack_addr) < 0)
BUG();
/* Delete the utcb address. */
delete_utcb_addr(task);
// FIXME: We assume that main thread never leaves the scene
// FIXME: What happens to task->utcb_head?
kfree(task);
/* Release the global mutex. */
l4_mutex_unlock(&lib_mutex);
/* Finally, destroy the thread. */
l4_thread_control(THREAD_DESTROY, ids);
return 0;
}

View File

@@ -1,94 +0,0 @@
/*
* UTCB management in libl4thread.
*
* Copyright © 2009 B Labs Ltd.
*/
#include <stdio.h>
#include <l4lib/addr.h>
#include <l4lib/thread/utcb-common.h>
#include <malloc/malloc.h>
#include INC_GLUE(message.h)
/* Globally disjoint utcb virtual region pool */
static struct address_pool utcb_region_pool;
int utcb_pool_init(unsigned long utcb_start, unsigned long utcb_end)
{
int err;
/* Initialise the global utcb virtual address pool */
if ((err = address_pool_init(&utcb_region_pool,
utcb_start, utcb_end,
PAGE_SIZE) < 0)) {
printf("UTCB address pool initialisation failed.\n");
return err;
}
return 0;
}
static inline void *utcb_new_address(int nitems)
{
return address_new(&utcb_region_pool, nitems, PAGE_SIZE);
}
static inline int utcb_delete_address(void *utcb_address, int nitems)
{
return address_del(&utcb_region_pool, utcb_address, nitems, PAGE_SIZE);
}
/* Return an empty utcb slot in this descriptor */
unsigned long utcb_new_slot(struct l4lib_utcb_desc *desc)
{
int slot;
if ((slot = id_new(desc->slots)) < 0)
return 0;
else
return desc->utcb_base + (unsigned long)slot * UTCB_SIZE;
}
int utcb_delete_slot(struct l4lib_utcb_desc *desc, unsigned long address)
{
BUG_ON(id_del(desc->slots, (address - desc->utcb_base)
/ UTCB_SIZE) < 0);
return 0;
}
struct l4lib_utcb_desc *utcb_new_desc(void)
{
struct l4lib_utcb_desc *d;
/* Allocate a new descriptor */
if (!(d = kzalloc(sizeof(*d))))
return 0;
link_init(&d->list);
/* We currently assume UTCB is smaller than PAGE_SIZE */
BUG_ON(UTCB_SIZE > PAGE_SIZE);
/* Initialise utcb slots */
d->slots = id_pool_new_init(PAGE_SIZE / UTCB_SIZE);
/* Obtain a new and unique utcb base */
/* FIXME: Use variable size than a page */
if (!(d->utcb_base = (unsigned long)utcb_new_address(1))) {
kfree(d->slots);
kfree(d);
return 0;
}
return d;
}
int utcb_delete_desc(struct l4lib_utcb_desc *desc)
{
/* Return descriptor address */
utcb_delete_address((void *)desc->utcb_base, 1);
/* Free the descriptor */
kfree(desc);
return 0;
}

View File

@@ -1,162 +0,0 @@
/*
* UTCB handling helper routines.
*
* Copyright (C) 2009 B Labs Ltd.
*/
#include <stdio.h>
#include <malloc/malloc.h>
#include <l4/api/errno.h>
#include <l4lib/arch/syscalls.h>
#include <l4lib/exregs.h>
#include <l4lib/idpool.h>
#include <l4lib/thread/utcb-common.h>
#include <l4lib/utcb.h>
/* Extern declarations */
extern struct l4lib_global_list global_tasks;
/* Global variables */
unsigned long lib_utcb_range_size;
/* Function definitions */
unsigned long get_utcb_addr(struct l4lib_tcb *task)
{
struct l4lib_utcb_desc *udesc;
unsigned long slot;
/* Setting this up twice is a bug. */
BUG_ON(task->utcb_addr);
/* Search for an empty utcb slot already allocated to this space. */
list_foreach_struct(udesc, &task->utcb_head->list, list)
if ((slot = utcb_new_slot(udesc)))
goto found;
/* Allocate a new utcb memory region and return its base. */
if (!(udesc = utcb_new_desc()))
return 0;
slot = utcb_new_slot(udesc);
list_insert(&udesc->list, &task->utcb_head->list);
found:
task->utcb_addr = slot;
return slot;
}
int delete_utcb_addr(struct l4lib_tcb *task)
{
struct l4lib_utcb_desc *udesc;
list_foreach_struct(udesc, &task->utcb_head->list, list) {
/* FIXME: Use variable alignment than a page */
/* Detect matching slot */
if (page_align(task->utcb_addr) == udesc->utcb_base) {
/* Delete slot from the descriptor */
utcb_delete_slot(udesc, task->utcb_addr);
/* Is the desc completely empty now? */
if (id_is_empty(udesc->slots)) {
/* Unlink desc from its list */
list_remove_init(&udesc->list);
/* Delete the descriptor */
utcb_delete_desc(udesc);
}
return 0; /* Finished */
}
}
BUG();
}
static int set_utcb_addr(void)
{
struct exregs_data exregs;
struct task_ids ids;
struct l4lib_tcb *task;
struct l4lib_utcb_desc *udesc;
int err;
/* Create a task. */
if (IS_ERR(task = l4_tcb_alloc_init(0, 0)))
return -ENOMEM;
/* Add child to the global task list. */
list_insert_tail(&task->list, &global_tasks.list);
global_tasks.total++;
if (!(udesc = utcb_new_desc()))
return -ENOMEM;
task->utcb_addr = utcb_new_slot(udesc);
list_insert(&udesc->list, &task->utcb_head->list);
memset(&exregs, 0, sizeof(exregs));
exregs_set_utcb(&exregs, task->utcb_addr);
l4_getid(&ids);
task->tid = ids.tid;
if ((err = l4_exchange_registers(&exregs, ids.tid)) < 0) {
printf("libl4thread: l4_exchange_registers failed with "
"(%d).\n", err);
return err;
}
return 0;
}
int l4_set_utcb_params(unsigned long utcb_start, unsigned long utcb_end)
{
int err;
/* Ensure that arguments are valid. */
if (IS_UTCB_SETUP()) {
printf("libl4thread: You have already called: %s.\n",
__FUNCTION__);
return -EPERM;
}
if (!utcb_start || !utcb_end) {
printf("libl4thread: Utcb address range cannot contain "
"0x0 as a start and/or end address(es).\n");
return -EINVAL;
}
/* Check if the start address is aligned on PAGE_SIZE. */
if (utcb_start & PAGE_MASK) {
printf("libl4thread: Utcb start address must be aligned "
"on PAGE_SIZE(0x%x).\n", PAGE_SIZE);
return -EINVAL;
}
/* The range must be a valid one. */
if (utcb_start >= utcb_end) {
printf("libl4thread: Utcb end address must be bigger "
"than utcb start address.\n");
return -EINVAL;
}
#if 0
/*
* This check guarantees two things:
* 1. The range must be multiple of UTCB_SIZE, at least one item.
* 2. utcb_end is aligned on UTCB_SIZE.
*/
if ((utcb_end - utcb_start) % UTCB_SIZE) {
printf("libl4thread: The given range size must be multiple "
"of the utcb size(%d).\n", UTCB_SIZE);
return -EINVAL;
}
#endif
/* Arguments passed the validity tests. */
/* Init utcb virtual address pool. */
if (utcb_pool_init(utcb_start, utcb_end) < 0)
BUG();
/*
* The very first thread's utcb address is assigned.
* It should not return an error value.
*/
if ((err = set_utcb_addr()) < 0)
BUG();
/* Initialize internal variables. */
lib_utcb_range_size = utcb_end - utcb_start;
return 0;
}

View File

@@ -155,9 +155,12 @@ struct mem_cache *mem_cache_init(void *start,
if (total & 0x1F) { /* Remainder? */
bwords++; /* Add one more word for remainder */
}
bsize = bwords * 4;
/* This many structures will be chucked from cache for bitmap space */
bwords_in_structs = ((bsize) / struct_size) + 1;
/* Total structs left after deducing bitmaps */
total = total - bwords_in_structs;
cache_size -= bsize;

View File

@@ -1,14 +0,0 @@
#ifndef __INITTASK_ARCH_MM_H__
#define __INITTASK_ARCH_MM_H__
#include <l4/macros.h>
#include <l4/types.h>
#include INC_GLUE(memory.h)
#include <vm_area.h>
struct fault_data;
unsigned int vm_prot_flags(pte_t pte);
void set_generic_fault_params(struct fault_data *fault);
void fault_handle_error(struct fault_data *fault);
#endif /* __INITTASK_ARCH_MM_H__ */

View File

@@ -1,94 +0,0 @@
/*
* Australian Public Licence B (OZPLB)
*
* Version 1-0
*
* Copyright (c) 2004 National ICT Australia
*
* All rights reserved.
*
* Developed by: Embedded, Real-time and Operating Systems Program (ERTOS)
* National ICT Australia
* http://www.ertos.nicta.com.au
*
* Permission is granted by National ICT Australia, free of charge, to
* any person obtaining a copy of this software and any associated
* documentation files (the "Software") to deal with the Software without
* restriction, including (without limitation) the rights to use, copy,
* modify, adapt, merge, publish, distribute, communicate to the public,
* sublicense, and/or sell, lend or rent out copies of the Software, and
* to permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimers.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimers in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of National ICT Australia, nor the names of its
* contributors, may be used to endorse or promote products derived
* from this Software without specific prior written permission.
*
* EXCEPT AS EXPRESSLY STATED IN THIS LICENCE AND TO THE FULL EXTENT
* PERMITTED BY APPLICABLE LAW, THE SOFTWARE IS PROVIDED "AS-IS", AND
* NATIONAL ICT AUSTRALIA AND ITS CONTRIBUTORS MAKE NO REPRESENTATIONS,
* WARRANTIES OR CONDITIONS OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO ANY REPRESENTATIONS, WARRANTIES OR CONDITIONS
* REGARDING THE CONTENTS OR ACCURACY OF THE SOFTWARE, OR OF TITLE,
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT,
* THE ABSENCE OF LATENT OR OTHER DEFECTS, OR THE PRESENCE OR ABSENCE OF
* ERRORS, WHETHER OR NOT DISCOVERABLE.
*
* TO THE FULL EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL
* NATIONAL ICT AUSTRALIA OR ITS CONTRIBUTORS BE LIABLE ON ANY LEGAL
* THEORY (INCLUDING, WITHOUT LIMITATION, IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHERWISE) FOR ANY CLAIM, LOSS, DAMAGES OR OTHER
* LIABILITY, INCLUDING (WITHOUT LIMITATION) LOSS OF PRODUCTION OR
* OPERATION TIME, LOSS, DAMAGE OR CORRUPTION OF DATA OR RECORDS; OR LOSS
* OF ANTICIPATED SAVINGS, OPPORTUNITY, REVENUE, PROFIT OR GOODWILL, OR
* OTHER ECONOMIC LOSS; OR ANY SPECIAL, INCIDENTAL, INDIRECT,
* CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES, ARISING OUT OF OR IN
* CONNECTION WITH THIS LICENCE, THE SOFTWARE OR THE USE OF OR OTHER
* DEALINGS WITH THE SOFTWARE, EVEN IF NATIONAL ICT AUSTRALIA OR ITS
* CONTRIBUTORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH CLAIM, LOSS,
* DAMAGES OR OTHER LIABILITY.
*
* If applicable legislation implies representations, warranties, or
* conditions, or imposes obligations or liability on National ICT
* Australia or one of its contributors in respect of the Software that
* cannot be wholly or partly excluded, restricted or modified, the
* liability of National ICT Australia or the contributor is limited, to
* the full extent permitted by the applicable legislation, at its
* option, to:
* a. in the case of goods, any one or more of the following:
* i. the replacement of the goods or the supply of equivalent goods;
* ii. the repair of the goods;
* iii. the payment of the cost of replacing the goods or of acquiring
* equivalent goods;
* iv. the payment of the cost of having the goods repaired; or
* b. in the case of services:
* i. the supplying of the services again; or
* ii. the payment of the cost of having the services supplied again.
*
* The construction, validity and performance of this licence is governed
* by the laws in force in New South Wales, Australia.
*/
#ifdef __thumb__
#define bl blx
#endif
.section .text.head
.code 32
.global _start;
.align;
_start:
ldr sp, =__stack
bl platform_init
bl __container_init
1:
b 1b

View File

@@ -1,84 +0,0 @@
/*
* Copyright (C) 2007 Bahadir Balban
*/
#include <arch/mm.h>
#include <task.h>
#include <vm_area.h>
#include <l4lib/exregs.h>
/* Extracts generic protection flags from architecture-specific pte */
unsigned int vm_prot_flags(pte_t pte)
{
unsigned int vm_prot_flags = 0;
unsigned int rw_flags = __MAP_USR_RW_FLAGS & PTE_PROT_MASK;
unsigned int ro_flags = __MAP_USR_RO_FLAGS & PTE_PROT_MASK;
/* Clear non-protection flags */
pte &= PTE_PROT_MASK;;
if (pte == ro_flags)
vm_prot_flags = VM_READ | VM_EXEC;
else if (pte == rw_flags)
vm_prot_flags = VM_READ | VM_WRITE | VM_EXEC;
else
vm_prot_flags = VM_NONE;
return vm_prot_flags;
}
#if defined(DEBUG_FAULT_HANDLING)
void arch_print_fault_params(struct fault_data *fault)
{
printf("%s: Handling %s fault (%s abort) from %d. fault @ 0x%x\n",
__TASKNAME__, (fault->reason & VM_READ) ? "read" : "write",
is_prefetch_abort(fault->kdata->fsr) ? "prefetch" : "data",
fault->task->tid, fault->address);
}
#else
void arch_print_fault_params(struct fault_data *fault) { }
#endif
void fault_handle_error(struct fault_data *fault)
{
struct task_ids ids;
/* Suspend the task */
ids.tid = fault->task->tid;
BUG_ON(l4_thread_control(THREAD_SUSPEND, &ids) < 0);
BUG();
}
/*
* PTE STATES:
* PTE type field: 00 (Translation fault)
* PTE type field correct, AP bits: None (Read or Write access fault)
* PTE type field correct, AP bits: RO (Write access fault)
*/
/* Extracts arch-specific fault parameters and puts them into generic format */
void set_generic_fault_params(struct fault_data *fault)
{
unsigned int prot_flags = vm_prot_flags(fault->kdata->pte);
fault->reason = 0;
fault->pte_flags = prot_flags;
if (is_prefetch_abort(fault->kdata->fsr)) {
fault->reason |= VM_READ;
fault->address = fault->kdata->faulty_pc;
} else {
fault->address = fault->kdata->far;
/* Always assume read fault first */
if (prot_flags & VM_NONE)
fault->reason |= VM_READ;
else if (prot_flags & VM_READ)
fault->reason |= VM_WRITE;
else
BUG();
}
arch_print_fault_params(fault);
}