base-linux: add ARM support

This patch introduces a new platform 'linux_arm' for building and running
Genode/Linux on an ARM device.

Known limitations:

- libc 'setjmp()'/'longjmp()' doesn't currently save/restore floating
  point registers

Fixes #746.
This commit is contained in:
Christian Prochaska
2013-05-24 11:04:42 +02:00
committed by Norman Feske
parent 314d5c0975
commit 4a9b1c6aab
20 changed files with 350 additions and 11 deletions

View File

@ -70,7 +70,13 @@ Process::Process(Dataspace_capability elf_data_ds_cap,
PERR("Dynamically linked file found, but no dynamic linker binary present");
return;
}
elf_data_ds_cap = _dynamic_linker_cap;
/*
* Starting the dynamic linker directly may cause it to be loaded at the
* wrong address on ARM-Linux. But since the dynamically linked
* application has a dynamic linker (by default ld.lib.so) defined as its
* interpreter in the ELF image, it's okay to just start the application
* directly on Linux.
*/
}
/*

View File

@ -0,0 +1,66 @@
/*
* \brief Startup code for Genode applications
* \author Christian Helmuth
* \author Christian Prochaska
* \date 2006-07-06
*/
/*
* Copyright (C) 2006-2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/*--- .text (program code) -------------------------*/
.text
.globl _start
_start:
ldr r1,=__initial_sp
str sp,[r1]
/*
* environ = &argv[argc + 1]
* in Genode argc is always 1
*/
add sp,sp,#12
ldr r1,=lx_environ
str sp,[r1]
/* XXX Switch to our own stack. */
ldr sp,=_stack_high
/* Clear the frame pointer and the link register so that stack backtraces will work. */
mov fp,#0
mov lr,#0
/* Jump into init C code */
b _main
/*--------------------------------------------------*/
.data
.globl __dso_handle
__dso_handle:
.long 0
.globl __initial_sp
__initial_sp:
.long 0
/*--- .eh_frame (exception frames) -----------------*/
/*
.section .eh_frame,"aw"
.globl __EH_FRAME_BEGIN__
__EH_FRAME_BEGIN__:
*/
/*--- .bss (non-initialized data) ------------------*/
.bss
.p2align 4
.globl _stack_low
_stack_low:
.space 64*1024
.globl _stack_high
_stack_high:

View File

@ -0,0 +1,94 @@
/*
* \brief Linux clone() binding
* \author Christian Prochaska
* \date 2012-05-05
*
* based on eglibc-2.11.3/ports/sysdeps/unix/sysv/linux/arm/clone.S
*/
#define SYS_clone 120
#define SYS_exit 1
#define SYS_getpid 20
#define __ARM_EABI__ 1
#define CLONE_VM 0x00000100
#define CLONE_THREAD 0x00010000
.text
.globl lx_clone
.type lx_clone, #function
lx_clone:
@ insert the args onto the new stack
str r3, [r1, #-4]!
str r0, [r1, #-4]!
@ do the system call
@ get flags
mov r0, r2
#ifdef RESET_PID
mov ip, r2
#endif
@ new sp is already in r1
#ifdef __ARM_EABI__
stmfd sp!, {r4, r7}
#else
str r4, [sp, #-8]!
#endif
ldr r2, [sp, #8]
ldr r3, [sp, #12]
ldr r4, [sp, #16]
#ifdef __ARM_EABI__
ldr r7, =SYS_clone
swi 0x0
#else
swi SYS_clone
#endif
cmp r0, #0
beq 1f
#ifdef __ARM_EABI__
ldmfd sp!, {r4, r7}
#else
ldr r4, [sp], #8
#endif
#blt PLTJMP(C_SYMBOL_NAME(__syscall_error))
bx lr
1:
#ifdef RESET_PID
tst ip, #CLONE_THREAD
bne 3f
mov r0, #0xffff0fff
mov lr, pc
sub pc, r0, #31
mov r1, r0
tst ip, #CLONE_VM
movne r0, #-1
#ifdef __ARM_EABI__
ldr r7, =SYS_getpid
swieq 0x0
#else
swieq SYS_getpid
#endif
str r0, [r1, #PID_OFFSET]
str r0, [r1, #TID_OFFSET]
3:
#endif
@ pick the function arg and call address off the stack and execute
ldr r0, [sp, #4]
#if defined(__ARM_ARCH_4T__) && defined(__THUMB_INTERWORK__)
ldr ip, [sp], #8
mov lr, pc
bx ip
#else
mov lr, pc
ldr pc, [sp], #8
#endif
@ and we are done, passing the return value through r0
ldr r7, =SYS_exit
swi 0x0
/* tell the linker that this code does not need an executable stack */
.section .note.GNU-stack, "", %progbits

View File

@ -0,0 +1,29 @@
/*
* \brief Linux syscall() binding
* \author Christian Prochaska
* \date 2012-05-05
*
* based on eglibc-2.11.3/ports/sysdeps/unix/sysv/linux/arm/syscall.S
*
* error case:
* glibc's syscall() function returns -1 and sets errno
* lx_syscall() returns -errno
*/
.text
.globl lx_syscall
.type lx_syscall, #function
lx_syscall:
mov ip, sp
stmfd sp!, {r4, r5, r6, r7}
mov r7, r0
mov r0, r1
mov r1, r2
mov r2, r3
ldmfd ip, {r3, r4, r5, r6}
swi 0x0
ldmfd sp!, {r4, r5, r6, r7}
bx lr
/* tell the linker that this code does not need an executable stack */
.section .note.GNU-stack, "", %progbits