mirror of
https://github.com/drasko/codezero.git
synced 2026-01-12 02:43:15 +01:00
Added kernel + libl4 changes for full and extended ipc.
- Short ipc working as normal. Full/extended ipc haven't been tested. - Added automated compilation and inclusion of test executable in test0.
This commit is contained in:
@@ -13,8 +13,8 @@
|
||||
#if defined (__KERNEL__)
|
||||
|
||||
/* These are for internally created ipc paths. */
|
||||
int ipc_send(l4id_t to);
|
||||
int ipc_sendrecv(l4id_t to, l4id_t from);
|
||||
int ipc_send(l4id_t to, int full);
|
||||
int ipc_sendrecv(l4id_t to, l4id_t from, int full);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -42,7 +42,8 @@ void address_space_remove(struct address_space *space);
|
||||
void address_space_reference_lock();
|
||||
void address_space_reference_unlock();
|
||||
void init_address_space_list(void);
|
||||
int check_access(unsigned long vaddr, unsigned long size, unsigned int flags);
|
||||
int check_access(unsigned long vaddr, unsigned long size,
|
||||
unsigned int flags, int page_in);
|
||||
#endif
|
||||
|
||||
#endif /* __SPACE_H__ */
|
||||
|
||||
@@ -26,6 +26,9 @@
|
||||
#define TASK_SUSPENDING (1 << 1)
|
||||
#define TASK_RESUMING (1 << 2)
|
||||
|
||||
/* IPC resulted in a fault error (For ipcs that cannot page fault) */
|
||||
#define IPC_EFAULT (1 << 3)
|
||||
|
||||
/* Task states */
|
||||
enum task_state {
|
||||
TASK_INACTIVE = 0,
|
||||
|
||||
@@ -83,4 +83,13 @@
|
||||
|
||||
#include INC_GLUE(memlayout.h)
|
||||
|
||||
#if defined (__KERNEL__)
|
||||
struct utcb {
|
||||
u32 mr[MR_TOTAL]; /* MRs that are mapped to real registers */
|
||||
u32 saved_tag; /* Saved tag field for stacked ipcs */
|
||||
u32 saved_sender; /* Saved sender field for stacked ipcs */
|
||||
u32 mr_rest[MR_REST]; /* Complete the utcb for up to 64 words */
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* __GLUE_ARM_MESSAGE_H__ */
|
||||
|
||||
120
src/api/ipc.c
120
src/api/ipc.c
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Inter-process communication
|
||||
*
|
||||
* Copyright (C) 2007 Bahadir Balban
|
||||
* Copyright (C) 2007-2009 Bahadir Bilgehan Balban
|
||||
*/
|
||||
#include <l4/generic/tcb.h>
|
||||
#include <l4/lib/mutex.h>
|
||||
@@ -14,13 +14,46 @@
|
||||
#include INC_API(syscall.h)
|
||||
#include INC_GLUE(message.h)
|
||||
|
||||
/*
|
||||
* ipc syscall uses an ipc_type variable and flags and send/recv
|
||||
* details are embedded in this variable.
|
||||
*/
|
||||
#define IPC_TYPE_FLAGS_SHIFT 2
|
||||
enum IPC_TYPE {
|
||||
IPC_INVALID = 0,
|
||||
IPC_SEND = 1,
|
||||
IPC_RECV = 2,
|
||||
IPC_SENDRECV = 3
|
||||
IPC_SENDRECV = 3,
|
||||
IPC_SEND_FULL = 5,
|
||||
IPC_RECV_FULL = 6,
|
||||
IPC_SENDRECV_FULL = 7,
|
||||
IPC_SEND_EXTENDED = 9,
|
||||
IPC_RECV_EXTENDED = 10,
|
||||
IPC_SENDRECV_EXTENDED = 11,
|
||||
};
|
||||
|
||||
/* Copy full utcb region from one task to another. */
|
||||
int ipc_full_copy(struct ktcb *to, struct ktcb *from)
|
||||
{
|
||||
struct utcb *from_utcb = (struct utcb *)from->utcb_address;
|
||||
struct utcb *to_utcb = (struct utcb *)to->utcb_address;
|
||||
int ret;
|
||||
|
||||
/* Check that utcb memory accesses won't fault us */
|
||||
if ((ret = check_access(to->utcb_address, UTCB_SIZE,
|
||||
MAP_SVC_RW_FLAGS, 0)) < 0)
|
||||
return ret;
|
||||
if ((ret = check_access(to->utcb_address, UTCB_SIZE,
|
||||
MAP_SVC_RW_FLAGS, 0)) < 0)
|
||||
return ret;
|
||||
|
||||
/* Directly copy from one utcb to another */
|
||||
memcpy(to_utcb->mr_rest, from_utcb->mr_rest,
|
||||
MR_REST * sizeof(unsigned int));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copies message registers from one ktcb stack to another. During the return
|
||||
* from system call, the registers are popped from the stack. In the future
|
||||
@@ -30,10 +63,11 @@ enum IPC_TYPE {
|
||||
* L4_ANYTHREAD. This is done for security since the receiver cannot trust
|
||||
* the sender info provided by the sender task.
|
||||
*/
|
||||
int ipc_msg_copy(struct ktcb *to, struct ktcb *from)
|
||||
int ipc_msg_copy(struct ktcb *to, struct ktcb *from, int full)
|
||||
{
|
||||
unsigned int *mr0_src = KTCB_REF_MR0(from);
|
||||
unsigned int *mr0_dst = KTCB_REF_MR0(to);
|
||||
int ret = 0;
|
||||
|
||||
/* NOTE:
|
||||
* Make sure MR_TOTAL matches the number of registers saved on stack.
|
||||
@@ -44,7 +78,11 @@ int ipc_msg_copy(struct ktcb *to, struct ktcb *from)
|
||||
if (to->expected_sender == L4_ANYTHREAD)
|
||||
mr0_dst[MR_SENDER] = from->tid;
|
||||
|
||||
return 0;
|
||||
/* Check if full utcb copying is requested and do it */
|
||||
if (full)
|
||||
ret = ipc_full_copy(to, from);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sys_ipc_control(syscall_context_t *regs)
|
||||
@@ -61,10 +99,11 @@ int sys_ipc_control(syscall_context_t *regs)
|
||||
*/
|
||||
|
||||
/* Interruptible ipc */
|
||||
int ipc_send(l4id_t recv_tid)
|
||||
int ipc_send(l4id_t recv_tid, int full)
|
||||
{
|
||||
struct ktcb *receiver = tcb_find(recv_tid);
|
||||
struct waitqueue_head *wqhs, *wqhr;
|
||||
int ret = 0;
|
||||
|
||||
wqhs = &receiver->wqh_send;
|
||||
wqhr = &receiver->wqh_recv;
|
||||
@@ -89,14 +128,18 @@ int ipc_send(l4id_t recv_tid)
|
||||
spin_unlock(&wqhs->slock);
|
||||
|
||||
/* Copy message registers */
|
||||
ipc_msg_copy(receiver, current);
|
||||
if ((ret = ipc_msg_copy(receiver, current, full)) < 0) {
|
||||
/* Set ipc error flag in receiver */
|
||||
BUG_ON(ret != -EFAULT);
|
||||
receiver->flags |= IPC_EFAULT;
|
||||
}
|
||||
|
||||
// printk("%s: (%d) Waking up (%d)\n", __FUNCTION__,
|
||||
// current->tid, receiver->tid);
|
||||
|
||||
/* Wake it up, we can yield here. */
|
||||
sched_resume_sync(receiver);
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* The receiver is not ready and/or not expecting us */
|
||||
@@ -116,12 +159,19 @@ int ipc_send(l4id_t recv_tid)
|
||||
current->flags &= ~TASK_INTERRUPTED;
|
||||
return -EINTR;
|
||||
}
|
||||
|
||||
/* Did ipc fail with a fault error? */
|
||||
if (current->flags & IPC_EFAULT) {
|
||||
current->flags &= ~IPC_EFAULT;
|
||||
return -EFAULT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ipc_recv(l4id_t senderid)
|
||||
int ipc_recv(l4id_t senderid, int full)
|
||||
{
|
||||
struct waitqueue_head *wqhs, *wqhr;
|
||||
int ret = 0;
|
||||
|
||||
wqhs = ¤t->wqh_send;
|
||||
wqhr = ¤t->wqh_recv;
|
||||
@@ -154,12 +204,20 @@ int ipc_recv(l4id_t senderid)
|
||||
task_unset_wqh(sleeper);
|
||||
spin_unlock(&wqhr->slock);
|
||||
spin_unlock(&wqhs->slock);
|
||||
ipc_msg_copy(current, sleeper);
|
||||
|
||||
/* Copy message registers */
|
||||
if ((ret = ipc_msg_copy(current, sleeper,
|
||||
full)) < 0) {
|
||||
|
||||
/* Set ipc fault flag on sleeper */
|
||||
BUG_ON(ret != -EFAULT);
|
||||
sleeper->flags |= IPC_EFAULT;
|
||||
}
|
||||
|
||||
// printk("%s: (%d) Waking up (%d)\n", __FUNCTION__,
|
||||
// current->tid, sleeper->tid);
|
||||
sched_resume_sync(sleeper);
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -181,6 +239,13 @@ int ipc_recv(l4id_t senderid)
|
||||
current->flags &= ~TASK_INTERRUPTED;
|
||||
return -EINTR;
|
||||
}
|
||||
|
||||
/* Did ipc fail with a fault error? */
|
||||
if (current->flags & IPC_EFAULT) {
|
||||
current->flags &= ~IPC_EFAULT;
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -198,20 +263,22 @@ int ipc_recv(l4id_t senderid)
|
||||
* (6) System task calls ipc_send() sending the return result.
|
||||
* (7) Rendezvous occurs. Both tasks exchange mrs and leave rendezvous.
|
||||
*/
|
||||
int ipc_sendrecv(l4id_t to, l4id_t from)
|
||||
int ipc_sendrecv(l4id_t to, l4id_t from, int full)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (to == from) {
|
||||
/* Send ipc request */
|
||||
ipc_send(to);
|
||||
if ((ret = ipc_send(to, full)) < 0)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Get reply.
|
||||
* A client would block its server only very briefly
|
||||
* between these calls.
|
||||
*/
|
||||
ipc_recv(from);
|
||||
if ((ret = ipc_recv(from, full)) < 0)
|
||||
return ret;
|
||||
} else {
|
||||
printk("%s: Unsupported ipc operation.\n", __FUNCTION__);
|
||||
ret = -ENOSYS;
|
||||
@@ -225,13 +292,28 @@ static inline int __sys_ipc(l4id_t to, l4id_t from, unsigned int ipc_type)
|
||||
|
||||
switch (ipc_type) {
|
||||
case IPC_SEND:
|
||||
ret = ipc_send(to);
|
||||
ret = ipc_send(to, 0);
|
||||
break;
|
||||
case IPC_RECV:
|
||||
ret = ipc_recv(from);
|
||||
ret = ipc_recv(from, 0);
|
||||
break;
|
||||
case IPC_SENDRECV:
|
||||
ret = ipc_sendrecv(to, from);
|
||||
ret = ipc_sendrecv(to, from, 0);
|
||||
break;
|
||||
case IPC_SEND_FULL:
|
||||
ret = ipc_send(to, 1);
|
||||
break;
|
||||
case IPC_RECV_FULL:
|
||||
ret = ipc_recv(from, 1);
|
||||
break;
|
||||
case IPC_SENDRECV_FULL:
|
||||
ret = ipc_sendrecv(to, from, 1);
|
||||
break;
|
||||
case IPC_SEND_EXTENDED:
|
||||
break;
|
||||
case IPC_RECV_EXTENDED:
|
||||
break;
|
||||
case IPC_SENDRECV_EXTENDED:
|
||||
break;
|
||||
case IPC_INVALID:
|
||||
default:
|
||||
@@ -267,6 +349,7 @@ int sys_ipc(syscall_context_t *regs)
|
||||
{
|
||||
l4id_t to = (l4id_t)regs->r0;
|
||||
l4id_t from = (l4id_t)regs->r1;
|
||||
unsigned int flags = (unsigned int)regs->r2;
|
||||
unsigned int ipc_type = 0;
|
||||
int ret = 0;
|
||||
|
||||
@@ -292,6 +375,9 @@ int sys_ipc(syscall_context_t *regs)
|
||||
/* [1] for Receive, [1:0] for both */
|
||||
ipc_type |= ((from != L4_NILTHREAD) << 1);
|
||||
|
||||
/* Short, full or extended ipc set here. Bits [3:2] */
|
||||
ipc_type |= (flags & L4_IPC_FLAGS_MASK) << IPC_TYPE_FLAGS_SHIFT;
|
||||
|
||||
if (ipc_type == IPC_INVALID) {
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
@@ -302,7 +388,7 @@ int sys_ipc(syscall_context_t *regs)
|
||||
return ret;
|
||||
|
||||
error:
|
||||
printk("Erroneous ipc by: %d. Err: %d\n", current->tid, ret);
|
||||
// printk("Erroneous ipc by: %d. Err: %d\n", current->tid, ret);
|
||||
ipc_type = IPC_INVALID;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -23,19 +23,19 @@ int __sys_kread(int rd, void *dest)
|
||||
switch(rd) {
|
||||
case KDATA_PAGE_MAP:
|
||||
// printk("Handling KDATA_PAGE_MAP request.\n");
|
||||
if (check_access(vaddr, sizeof(page_map), MAP_USR_RW_FLAGS) < 0)
|
||||
if (check_access(vaddr, sizeof(page_map), MAP_USR_RW_FLAGS, 1) < 0)
|
||||
return -EINVAL;
|
||||
memcpy(dest, &page_map, sizeof(page_map));
|
||||
break;
|
||||
case KDATA_BOOTDESC:
|
||||
// printk("Handling KDATA_BOOTDESC request.\n");
|
||||
if (check_access(vaddr, bootdesc->desc_size, MAP_USR_RW_FLAGS) < 0)
|
||||
if (check_access(vaddr, bootdesc->desc_size, MAP_USR_RW_FLAGS, 1) < 0)
|
||||
return -EINVAL;
|
||||
memcpy(dest, bootdesc, bootdesc->desc_size);
|
||||
break;
|
||||
case KDATA_BOOTDESC_SIZE:
|
||||
// printk("Handling KDATA_BOOTDESC_SIZE request.\n");
|
||||
if (check_access(vaddr, sizeof(unsigned int), MAP_USR_RW_FLAGS) < 0)
|
||||
if (check_access(vaddr, sizeof(unsigned int), MAP_USR_RW_FLAGS, 1) < 0)
|
||||
return -EINVAL;
|
||||
*(unsigned int *)dest = bootdesc->desc_size;
|
||||
break;
|
||||
|
||||
@@ -58,7 +58,7 @@ void fault_ipc_to_pager(u32 faulty_pc, u32 fsr, u32 far)
|
||||
offsetof(syscall_context_t, r3));
|
||||
|
||||
/* Send ipc to the task's pager */
|
||||
ipc_sendrecv(current->pagerid, current->pagerid);
|
||||
ipc_sendrecv(current->pagerid, current->pagerid, 0);
|
||||
|
||||
/*
|
||||
* FIXME: CHECK TASK KILL REPLY !!!
|
||||
|
||||
@@ -151,7 +151,7 @@ struct address_space *address_space_create(struct address_space *orig)
|
||||
* If its not mapped-in, it generates a page-in request to the thread's
|
||||
* pager. If fault hasn't cleared, aborts.
|
||||
*/
|
||||
int check_access(unsigned long vaddr, unsigned long size, unsigned int flags)
|
||||
int check_access(unsigned long vaddr, unsigned long size, unsigned int flags, int page_in)
|
||||
{
|
||||
int err;
|
||||
|
||||
@@ -159,20 +159,17 @@ int check_access(unsigned long vaddr, unsigned long size, unsigned int flags)
|
||||
if (size >= USER_AREA_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
/* Check if in user range, but this is more up to the pager to decide */
|
||||
if (current->tid == PAGER_TID) {
|
||||
if (!(vaddr >= INITTASK_AREA_START && vaddr < INITTASK_AREA_END))
|
||||
return -EINVAL;
|
||||
} else {
|
||||
if (!(vaddr >= USER_AREA_START && vaddr < USER_AREA_END))
|
||||
return -EINVAL;
|
||||
/* Check if the address is mapped with given flags */
|
||||
if (!check_mapping(vaddr, size, flags)) {
|
||||
/* Is a page in requested? */
|
||||
if (page_in) {
|
||||
/* Ask pager if paging in is possible */
|
||||
if((err = pager_pagein_request(vaddr, size, flags)) < 0)
|
||||
return err;
|
||||
} else
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* If not mapped, ask pager whether this is possible */
|
||||
if (!check_mapping(vaddr, size, flags))
|
||||
if((err = pager_pagein_request(vaddr, size, flags)) < 0)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ int sys_time(syscall_context_t *args)
|
||||
int set = (int)args->r1;
|
||||
int retries = 20;
|
||||
|
||||
if (check_access((unsigned long)tv, sizeof(*tv), MAP_USR_RW_FLAGS) < 0)
|
||||
if (check_access((unsigned long)tv, sizeof(*tv), MAP_USR_RW_FLAGS, 1) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* Get time */
|
||||
|
||||
@@ -53,7 +53,7 @@ END_PROC(l4_kread)
|
||||
|
||||
/*
|
||||
* For clone() we need special assembler handling
|
||||
* Same signature as ipc(): @r0 = to, @r1 = from
|
||||
* 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.
|
||||
@@ -62,6 +62,11 @@ 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
|
||||
|
||||
cmp r2, #0
|
||||
1:
|
||||
bne 1b
|
||||
|
||||
ldr r12, =__l4_ipc
|
||||
mov lr, pc
|
||||
ldr pc, [r12] @ Perform the ipc()
|
||||
@@ -101,6 +106,11 @@ 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
|
||||
|
||||
cmp r2, #0
|
||||
1:
|
||||
bne 1b
|
||||
|
||||
ldr r12, =__l4_ipc
|
||||
mov lr, pc
|
||||
ldr pc, [r12]
|
||||
|
||||
@@ -52,7 +52,7 @@ int fork(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern int arch_clone(l4id_t to, l4id_t from);
|
||||
extern int arch_clone(l4id_t to, l4id_t from, unsigned int flags);
|
||||
|
||||
int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ...)
|
||||
{
|
||||
@@ -74,7 +74,7 @@ int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ...)
|
||||
write_mr(L4SYS_ARG1, flags);
|
||||
|
||||
/* Perform an ipc but with different return logic. See implementation. */
|
||||
if ((ret = arch_clone(PAGER_TID, PAGER_TID)) < 0) {
|
||||
if ((ret = arch_clone(PAGER_TID, PAGER_TID, 0)) < 0) {
|
||||
print_err("%s: L4 IPC Error: %d.\n", __FUNCTION__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -68,11 +68,42 @@ env = Environment(CC = 'arm-none-linux-gnueabi-gcc',
|
||||
CPPFLAGS = "-D__USERSPACE__",
|
||||
CPPPATH = ['#include', libl4_incpath, libposix_incpath, kernel_incpath])
|
||||
|
||||
|
||||
test_exec_ld_script = "include/test_exec_linker.lds"
|
||||
# The kernel build environment:
|
||||
test_exec_env = Environment(CC = 'arm-none-linux-gnueabi-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 = ['-O3', '-nostdlib', '-ffreestanding', '-std=gnu99', '-Wall', '-Werror'],
|
||||
LINKFLAGS = ['-nostdlib', '-T' + test_exec_ld_script, "-L" + libc_libpath, "-L" + libl4_path, \
|
||||
'-L' + libposix_libpath],
|
||||
ASFLAGS = ['-D__ASSEMBLY__'],
|
||||
PROGSUFFIX = '.axf', # The suffix to use for final executable
|
||||
ENV = {'PATH' : os.environ['PATH']}, # Inherit shell path
|
||||
LIBS = [libc_name, 'gcc', libc_name, 'libl4', 'libposix', libc_name],
|
||||
CPPFLAGS = "-D__USERSPACE__",
|
||||
CPPPATH = ['#include', libl4_incpath, libposix_incpath, kernel_incpath])
|
||||
|
||||
src = [glob("src/*.c"), glob("*.c"), glob("*.S"), glob("src/arch/arm/*.c"), glob("../libcont/*.c")]
|
||||
objs = env.Object(src)
|
||||
physical_base = env.Command(physical_base_ld_script, prev_image, get_physical_base)
|
||||
crt0_copied = env.Command("crt0.o", libc_crt0, copy_crt0)
|
||||
|
||||
test_exec_src = [glob("src/test_exec/*.c")]
|
||||
test_exec_objs = test_exec_env.Object(test_exec_src)
|
||||
test_exec_name = "test_exec"
|
||||
test_exec = test_exec_env.Program(test_exec_name, test_exec_objs + [crt0_copied])
|
||||
test_exec_env.Alias(test_exec_name, test_exec)
|
||||
|
||||
env.Depends(objs, test_exec)
|
||||
task = env.Program(task_name, objs + [crt0_copied])
|
||||
env.Alias(task_name, task)
|
||||
|
||||
# I find this to be a BUG related to SCons. SCons is still good compared to
|
||||
# notoriously horrible makefiles, but it could have been better.
|
||||
# if test_exec doesn't depend on physical_base, test_exec is compiled but
|
||||
# task complains that physical_base is not there. However we already declared
|
||||
# its dependency below.
|
||||
|
||||
env.Depends(test_exec, physical_base)
|
||||
env.Depends(task, physical_base)
|
||||
|
||||
@@ -33,9 +33,9 @@ SECTIONS
|
||||
.data : AT (ADDR(.data) - offset)
|
||||
{
|
||||
. = ALIGN(4K);
|
||||
_start_test1 = .;
|
||||
*(.test1)
|
||||
_end_test1 = .;
|
||||
_start_test_exec = .;
|
||||
*(.testexec)
|
||||
_end_test_exec = .;
|
||||
*(.data)
|
||||
}
|
||||
.bss : AT (ADDR(.bss) - offset) { *(.bss) }
|
||||
|
||||
37
tasks/test0/include/test_exec_linker.lds
Normal file
37
tasks/test0/include/test_exec_linker.lds
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Simple linker script for userspace or svc tasks.
|
||||
*
|
||||
* Copyright (C) 2007 Bahadir Balban
|
||||
*/
|
||||
|
||||
/*
|
||||
* The only catch with this linker script is that everything
|
||||
* is linked starting at virtual_base, and loaded starting
|
||||
* at physical_base. virtual_base is the predefined region
|
||||
* of virtual memory for userland applications. physical_base
|
||||
* is determined at build-time, it is one of the subsequent pages
|
||||
* that come after the kernel image's load area.
|
||||
*/
|
||||
/* USER_AREA_START, see memlayout.h */
|
||||
virtual_base = 0x10000000;
|
||||
__stack = (0x20000000 - 0x1000 - 8); /* First page before the env/args */
|
||||
INCLUDE "include/physical_base.lds"
|
||||
|
||||
/* physical_base = 0x228000; */
|
||||
offset = virtual_base - physical_base;
|
||||
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = virtual_base;
|
||||
_start_text = .;
|
||||
.text : AT (ADDR(.text) - offset) { crt0.o(.text) *(.text) }
|
||||
/* rodata is needed else your strings will link at physical! */
|
||||
.rodata : AT (ADDR(.rodata) - offset) { *(.rodata) }
|
||||
.rodata1 : AT (ADDR(.rodata1) - offset) { *(.rodata1) }
|
||||
. = ALIGN(4K);
|
||||
.data : AT (ADDR(.data) - offset) { *(.data) }
|
||||
.bss : AT (ADDR(.bss) - offset) { *(.bss) }
|
||||
_end = .;
|
||||
}
|
||||
@@ -19,7 +19,7 @@ void wait_pager(l4id_t partner)
|
||||
for (int i = 0; i < 6; i++)
|
||||
write_mr(i, i);
|
||||
l4_send(partner, L4_IPC_TAG_SYNC);
|
||||
// printf("Pager synced with us.\n");
|
||||
printf("Pager synced with us.\n");
|
||||
}
|
||||
|
||||
pid_t parent_of_all;
|
||||
|
||||
@@ -11,14 +11,14 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
extern char _start_test1[];
|
||||
extern char _end_test1[];
|
||||
extern char _start_test_exec[];
|
||||
extern char _end_test_exec[];
|
||||
|
||||
int exectest(void)
|
||||
{
|
||||
int fd;
|
||||
void *exec_start = (void *)_start_test1;
|
||||
unsigned long size = _end_test1 - _start_test1;
|
||||
void *exec_start = (void *)_start_test_exec;
|
||||
unsigned long size = _end_test_exec - _start_test_exec;
|
||||
int left, cnt;
|
||||
char *argv[5];
|
||||
char filename[128];
|
||||
|
||||
25
tasks/test0/src/test_exec/container.c
Normal file
25
tasks/test0/src/test_exec/container.c
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Container entry point for this task.
|
||||
*
|
||||
* Copyright (C) 2007-2009 Bahadir Bilgehan Balban
|
||||
*/
|
||||
|
||||
#include <l4lib/types.h>
|
||||
#include <l4lib/init.h>
|
||||
#include <l4lib/utcb.h>
|
||||
#include <posix_init.h> /* Initialisers for posix library */
|
||||
|
||||
void main(void);
|
||||
|
||||
void __container_init(void)
|
||||
{
|
||||
/* Generic L4 thread initialisation */
|
||||
__l4_init();
|
||||
|
||||
/* Initialise posix library for application */
|
||||
libposix_init();
|
||||
|
||||
/* Entry to main */
|
||||
main();
|
||||
}
|
||||
|
||||
BIN
tasks/test0/src/test_exec/container.o
Normal file
BIN
tasks/test0/src/test_exec/container.o
Normal file
Binary file not shown.
36
tasks/test0/src/test_exec/test_exec.c
Normal file
36
tasks/test0/src/test_exec/test_exec.c
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Some tests for posix syscalls.
|
||||
*
|
||||
* Copyright (C) 2007 Bahadir Balban
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <l4lib/arch/syslib.h>
|
||||
#include <l4lib/kip.h>
|
||||
#include <l4lib/utcb.h>
|
||||
#include <l4lib/ipcdefs.h>
|
||||
#include <tests.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
void wait_pager(l4id_t partner)
|
||||
{
|
||||
// printf("%s: Syncing with pager.\n", __TASKNAME__);
|
||||
for (int i = 0; i < 6; i++)
|
||||
write_mr(i, i);
|
||||
l4_send(partner, L4_IPC_TAG_SYNC);
|
||||
// printf("Pager synced with us.\n");
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
wait_pager(0);
|
||||
if (getpid() == 2) {
|
||||
printf("EXECVE TEST -- PASSED --\n", getpid());
|
||||
printf("\n(Thread %d): Continues to sync with the pager...\n", getpid());
|
||||
while (1)
|
||||
wait_pager(0);
|
||||
}
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
BIN
tasks/test0/src/test_exec/test_exec.o
Normal file
BIN
tasks/test0/src/test_exec/test_exec.o
Normal file
Binary file not shown.
5
tasks/test0/test_exec.S
Normal file
5
tasks/test0/test_exec.S
Normal file
@@ -0,0 +1,5 @@
|
||||
.section .testexec
|
||||
|
||||
.align 4
|
||||
.incbin "test_exec.axf"
|
||||
.align 4
|
||||
Reference in New Issue
Block a user