mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 21:57:55 +00:00
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:
parent
314d5c0975
commit
4a9b1c6aab
@ -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,
|
||||
|
@ -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 =
|
||||
|
@ -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
|
||||
|
8
base-linux/lib/mk/arm/base.mk
Normal file
8
base-linux/lib/mk/arm/base.mk
Normal file
@ -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
base-linux/lib/mk/arm/startup.mk
Normal file
5
base-linux/lib/mk/arm/startup.mk
Normal file
@ -0,0 +1,5 @@
|
||||
LIBS += syscall
|
||||
|
||||
include $(BASE_DIR)/lib/mk/startup.inc
|
||||
|
||||
vpath crt0.s $(REP_DIR)/src/platform/arm
|
5
base-linux/lib/mk/arm/syscall.mk
Normal file
5
base-linux/lib/mk/arm/syscall.mk
Normal file
@ -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
base-linux/mk/spec-linux_arm.mk
Normal file
25
base-linux/mk/spec-linux_arm.mk
Normal file
@ -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)
|
@ -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.
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
|
66
base-linux/src/platform/arm/crt0.s
Normal file
66
base-linux/src/platform/arm/crt0.s
Normal 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:
|
94
base-linux/src/platform/arm/lx_clone.S
Normal file
94
base-linux/src/platform/arm/lx_clone.S
Normal 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
|
29
base-linux/src/platform/arm/lx_syscall.S
Normal file
29
base-linux/src/platform/arm/lx_syscall.S
Normal 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
|
@ -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"
|
||||
|
||||
|
@ -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,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
os/lib/mk/arm/ldso_crt0_lx.mk
Normal file
3
os/lib/mk/arm/ldso_crt0_lx.mk
Normal file
@ -0,0 +1,3 @@
|
||||
SRC_S = crt0.s
|
||||
|
||||
vpath crt0.s $(REP_DIR)/src/lib/ldso/arm/linux
|
@ -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
|
||||
|
||||
|
58
os/src/lib/ldso/arm/linux/crt0.s
Normal file
58
os/src/lib/ldso/arm/linux/crt0.s
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* \brief Startup code for ld.lib.so (linux_arm)
|
||||
* \author Christian Prochaska
|
||||
* \date 2012-07-06
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 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) -------------------------*/
|
||||
.section ".text.crt0"
|
||||
|
||||
.globl _start_ldso
|
||||
_start_ldso:
|
||||
|
||||
ldr sl, .L_GOT
|
||||
.L_GOT_OFF:
|
||||
add sl, pc, sl
|
||||
|
||||
ldr r1, .initial_sp
|
||||
ldr r1, [sl, r1]
|
||||
str sp, [r1]
|
||||
|
||||
/*
|
||||
* environ = &argv[argc + 1]
|
||||
* in Genode argc is always 1
|
||||
*/
|
||||
add sp, sp,#12
|
||||
ldr r1, .lx_environ
|
||||
ldr r1, [sl, r1]
|
||||
str sp, [r1]
|
||||
|
||||
/* XXX Switch to our own stack. */
|
||||
ldr r1, .stack_high
|
||||
ldr sp, [sl, r1]
|
||||
|
||||
/* relocate ldso */
|
||||
mov r1, #0
|
||||
bl init_rtld
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
||||
.L_GOT: .word _GLOBAL_OFFSET_TABLE_ - (.L_GOT_OFF + 8)
|
||||
.initial_sp: .word __initial_sp(GOT)
|
||||
.lx_environ: .word lx_environ(GOT)
|
||||
.stack_high: .word _stack_high(GOT)
|
@ -18,7 +18,15 @@
|
||||
*/
|
||||
void call_main(void (*func)(void))
|
||||
{
|
||||
func();
|
||||
extern long __initial_sp;
|
||||
|
||||
asm volatile ("mov %%sp, %0;"
|
||||
"bx %1;"
|
||||
:
|
||||
: "r" (__initial_sp),
|
||||
"r" (func)
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
|
||||
#endif /* _ARM__CALL_MAIN_H_ */
|
||||
|
1
tool/builddir/etc/build.conf.linux_arm
Normal file
1
tool/builddir/etc/build.conf.linux_arm
Normal file
@ -0,0 +1 @@
|
||||
REPOSITORIES = $(GENODE_DIR)/base-linux
|
@ -20,6 +20,7 @@ usage:
|
||||
@echo
|
||||
@echo " <platform> can be:"
|
||||
@echo " 'linux_x86'"
|
||||
@echo " 'linux_arm'"
|
||||
@echo " 'fiasco_x86'"
|
||||
@echo " 'pistachio_x86'"
|
||||
@echo " 'okl4_x86'"
|
||||
|
Loading…
Reference in New Issue
Block a user