Skip to content

Commit

Permalink
base-linux: add ARM support
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
cproc authored and nfeske committed May 24, 2013
1 parent 314d5c0 commit 4a9b1c6
Show file tree
Hide file tree
Showing 20 changed files with 350 additions and 11 deletions.
8 changes: 8 additions & 0 deletions base-linux/etc/specs.conf
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,16 @@
ifeq ($(shell uname -m),x86_64)
SPECS ?= genode linux_x86_64 sdl
else
ifeq ($(shell uname -m),armv6l)
SPECS ?= genode linux_arm sdl arm_v6
else
ifeq ($(shell uname -m),armv7l)
SPECS ?= genode linux_arm sdl arm_v7a
else
SPECS ?= genode linux_x86_32 sdl
endif
endif
endif

#
# If you want to build for the host platform,
Expand Down
4 changes: 4 additions & 0 deletions base-linux/lib/import/import-lx_hybrid.mk
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,12 @@ USE_HOST_LD_SCRIPT = yes
ifeq (x86_64,$(findstring x86_64,$(SPECS)))
CXX_LINK_OPT += -Wl,--dynamic-linker=/lib64/ld-linux-x86-64.so.2
else
ifeq (arm,$(findstring arm,$(SPECS)))
CXX_LINK_OPT += -Wl,--dynamic-linker=/lib/ld-linux.so.3
else
CXX_LINK_OPT += -Wl,--dynamic-linker=/lib/ld-linux.so.2
endif
endif

# because we use the host compiler's libgcc, omit the Genode toolchain's version
LD_LIBGCC =
Expand Down
4 changes: 2 additions & 2 deletions base-linux/lib/import/import-syscall.mk
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
HOST_INC_DIR += $(dir $(call select_from_repositories,src/platform/linux_syscalls.h))
HOST_INC_DIR += /usr/include

# needed for Ubuntu 11.04
# needed for Ubuntu >= 11.04
HOST_INC_DIR += /usr/include/$(shell gcc -dumpmachine)
HOST_INC_DIR += /usr/include/i386-linux-gnu
HOST_INC_DIR += /usr/include/x86_64-linux-gnu

#
# Some header files installed on GNU/Linux test for the GNU compiler. For
Expand Down
8 changes: 8 additions & 0 deletions base-linux/lib/mk/arm/base.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
include $(REP_DIR)/lib/mk/base.inc

LIBS += startup cxx

SRC_CC += thread.cc thread_linux.cc

vpath thread.cc $(BASE_DIR)/src/base/thread
vpath thread_linux.cc $(REP_DIR)/src/base/thread
5 changes: 5 additions & 0 deletions base-linux/lib/mk/arm/startup.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
LIBS += syscall

include $(BASE_DIR)/lib/mk/startup.inc

vpath crt0.s $(REP_DIR)/src/platform/arm
5 changes: 5 additions & 0 deletions base-linux/lib/mk/arm/syscall.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
REQUIRES = linux arm
SRC_S += lx_clone.S lx_syscall.S

vpath lx_clone.S $(REP_DIR)/../base-linux/src/platform/arm
vpath lx_syscall.S $(REP_DIR)/../base-linux/src/platform/arm
25 changes: 25 additions & 0 deletions base-linux/mk/spec-linux_arm.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#
# Specifics for Linux on ARM
#
SPECS += linux arm

REP_INC_DIR += src/platform/arm

ifeq ($(shell gcc -dumpmachine),arm-linux-gnueabihf)
CC_MARCH += -mfloat-abi=hard
endif

#
# We need to manually add the default linker script on the command line in case
# of standard library use. Otherwise, we were not able to extend it by the
# context area section.
#
ifeq ($(USE_HOST_LD_SCRIPT),yes)
LD_SCRIPT_STATIC = ldscripts/armelf_linux_eabi.xc
endif

#
# Include less-specific configuration
#
include $(call select_from_repositories,mk/spec-arm.mk)
include $(call select_from_repositories,mk/spec-linux.mk)
8 changes: 7 additions & 1 deletion base-linux/src/base/process/process.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
}

/*
Expand Down
66 changes: 66 additions & 0 deletions base-linux/src/platform/arm/crt0.s
Original file line number Diff line number Diff line change
@@ -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:
94 changes: 94 additions & 0 deletions base-linux/src/platform/arm/lx_clone.S
Original file line number Diff line number Diff line change
@@ -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
29 changes: 29 additions & 0 deletions base-linux/src/platform/arm/lx_syscall.S
Original file line number Diff line number Diff line change
@@ -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
14 changes: 12 additions & 2 deletions base/src/platform/arm/crt0.s
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,25 @@
.globl _start
_start:

ldr sp, .initial_sp
ldr r4, .initial_sp
str sp, [r4]

ldr sp, .stack_high
b _main

.initial_sp: .word _stack_high
.initial_sp: .word __initial_sp
.stack_high: .word _stack_high

/*--------------------------------------------------*/
.data
.globl __dso_handle
__dso_handle:
.long 0

.globl __initial_sp
__initial_sp:
.long 0

/*--- .bss (non-initialized data) ------------------*/
.section ".bss"

Expand Down
3 changes: 0 additions & 3 deletions libports/lib/mk/arm/libc-gen.mk
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,4 @@ SRC_C += $(filter-out $(FILTER_OUT_C),$(notdir $(wildcard $(LIBC_GEN_ARM_DIR)/*
# fix missing include prefix for 'ucontext.h', should be 'sys/ucontext.h'
CC_OPT_makecontext = -I$(REP_DIR)/include/libc/sys

# needed to compile setjmp.S
CC_OPT += -DSOFTFLOAT

vpath % $(LIBC_GEN_ARM_DIR)
7 changes: 7 additions & 0 deletions libports/lib/mk/arm/libc-setjmp.mk
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ SRC_S = _setjmp.S setjmp.S
#
CC_OPT += -D_STANDALONE

#
# Needed to compile on hard-float Linux
# FIXME: Floating point registers don't get saved/restored
# when using this definition!
#
CC_OPT += -D__SOFTFP__

include $(REP_DIR)/lib/mk/libc-common.inc

vpath %.S $(LIBC_GEN_ARM_DIR)
3 changes: 3 additions & 0 deletions os/lib/mk/arm/ldso_crt0_lx.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
SRC_S = crt0.s

vpath crt0.s $(REP_DIR)/src/lib/ldso/arm/linux
8 changes: 6 additions & 2 deletions os/src/lib/ldso/arm/crt0.s
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,14 @@ _start_ldso:
ldr r2, .initial_utcb
str r0, [r2]

ldr sp, .initial_sp
ldr r2, .initial_sp
str sp, [r2]

ldr sp, .stack_high
bl init_rtld
b _main

.initial_sp: .word _stack_high
.initial_sp: .word __initial_sp
.stack_high: .word _stack_high
.initial_utcb: .word _main_utcb

Loading

0 comments on commit 4a9b1c6

Please sign in to comment.