mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-25 00:11:07 +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)
|
ifeq ($(shell uname -m),x86_64)
|
||||||
SPECS ?= genode linux_x86_64 sdl
|
SPECS ?= genode linux_x86_64 sdl
|
||||||
else
|
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
|
SPECS ?= genode linux_x86_32 sdl
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
#
|
#
|
||||||
# If you want to build for the host platform,
|
# 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)))
|
ifeq (x86_64,$(findstring x86_64,$(SPECS)))
|
||||||
CXX_LINK_OPT += -Wl,--dynamic-linker=/lib64/ld-linux-x86-64.so.2
|
CXX_LINK_OPT += -Wl,--dynamic-linker=/lib64/ld-linux-x86-64.so.2
|
||||||
else
|
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
|
CXX_LINK_OPT += -Wl,--dynamic-linker=/lib/ld-linux.so.2
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
# because we use the host compiler's libgcc, omit the Genode toolchain's version
|
# because we use the host compiler's libgcc, omit the Genode toolchain's version
|
||||||
LD_LIBGCC =
|
LD_LIBGCC =
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
HOST_INC_DIR += $(dir $(call select_from_repositories,src/platform/linux_syscalls.h))
|
HOST_INC_DIR += $(dir $(call select_from_repositories,src/platform/linux_syscalls.h))
|
||||||
HOST_INC_DIR += /usr/include
|
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/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
|
# 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");
|
PERR("Dynamically linked file found, but no dynamic linker binary present");
|
||||||
return;
|
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
|
.globl _start
|
||||||
_start:
|
_start:
|
||||||
|
|
||||||
ldr sp, .initial_sp
|
ldr r4, .initial_sp
|
||||||
|
str sp, [r4]
|
||||||
|
|
||||||
|
ldr sp, .stack_high
|
||||||
b _main
|
b _main
|
||||||
|
|
||||||
.initial_sp: .word _stack_high
|
.initial_sp: .word __initial_sp
|
||||||
|
.stack_high: .word _stack_high
|
||||||
|
|
||||||
|
/*--------------------------------------------------*/
|
||||||
|
.data
|
||||||
.globl __dso_handle
|
.globl __dso_handle
|
||||||
__dso_handle:
|
__dso_handle:
|
||||||
.long 0
|
.long 0
|
||||||
|
|
||||||
|
.globl __initial_sp
|
||||||
|
__initial_sp:
|
||||||
|
.long 0
|
||||||
|
|
||||||
/*--- .bss (non-initialized data) ------------------*/
|
/*--- .bss (non-initialized data) ------------------*/
|
||||||
.section ".bss"
|
.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'
|
# fix missing include prefix for 'ucontext.h', should be 'sys/ucontext.h'
|
||||||
CC_OPT_makecontext = -I$(REP_DIR)/include/libc/sys
|
CC_OPT_makecontext = -I$(REP_DIR)/include/libc/sys
|
||||||
|
|
||||||
# needed to compile setjmp.S
|
|
||||||
CC_OPT += -DSOFTFLOAT
|
|
||||||
|
|
||||||
vpath % $(LIBC_GEN_ARM_DIR)
|
vpath % $(LIBC_GEN_ARM_DIR)
|
||||||
|
@ -7,6 +7,13 @@ SRC_S = _setjmp.S setjmp.S
|
|||||||
#
|
#
|
||||||
CC_OPT += -D_STANDALONE
|
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
|
include $(REP_DIR)/lib/mk/libc-common.inc
|
||||||
|
|
||||||
vpath %.S $(LIBC_GEN_ARM_DIR)
|
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
|
ldr r2, .initial_utcb
|
||||||
str r0, [r2]
|
str r0, [r2]
|
||||||
|
|
||||||
ldr sp, .initial_sp
|
ldr r2, .initial_sp
|
||||||
|
str sp, [r2]
|
||||||
|
|
||||||
|
ldr sp, .stack_high
|
||||||
bl init_rtld
|
bl init_rtld
|
||||||
b _main
|
b _main
|
||||||
|
|
||||||
.initial_sp: .word _stack_high
|
.initial_sp: .word __initial_sp
|
||||||
|
.stack_high: .word _stack_high
|
||||||
.initial_utcb: .word _main_utcb
|
.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))
|
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_ */
|
#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
|
||||||
@echo " <platform> can be:"
|
@echo " <platform> can be:"
|
||||||
@echo " 'linux_x86'"
|
@echo " 'linux_x86'"
|
||||||
|
@echo " 'linux_arm'"
|
||||||
@echo " 'fiasco_x86'"
|
@echo " 'fiasco_x86'"
|
||||||
@echo " 'pistachio_x86'"
|
@echo " 'pistachio_x86'"
|
||||||
@echo " 'okl4_x86'"
|
@echo " 'okl4_x86'"
|
||||||
|
Loading…
Reference in New Issue
Block a user