From 6abdf735355b751acf943089ae79afd371c852fe Mon Sep 17 00:00:00 2001 From: Peter Kalbus Date: Wed, 2 Feb 2022 23:36:23 +0100 Subject: [PATCH] sim: Initial support on MacOS M1 and Linux AARCH64 based hosts. --- arch/sim/Kconfig | 4 + arch/sim/include/inttypes.h | 3 +- arch/sim/include/limits.h | 20 ++-- arch/sim/include/setjmp.h | 35 +++++++ arch/sim/src/Makefile | 2 + arch/sim/src/sim/up_hostmemory.c | 8 ++ arch/sim/src/sim/up_initialstate.c | 13 ++- arch/sim/src/sim/up_vfork_arm64.S | 116 ++++++++++++++++++++++ boards/sim/sim/sim/README.txt | 30 ++++++ libs/libc/machine/sim/Make.defs | 4 + libs/libc/machine/sim/arch_setjmp_arm64.S | 92 +++++++++++++++++ tools/sethost.sh | 16 +-- 12 files changed, 322 insertions(+), 21 deletions(-) create mode 100644 arch/sim/src/sim/up_vfork_arm64.S create mode 100644 libs/libc/machine/sim/arch_setjmp_arm64.S diff --git a/arch/sim/Kconfig b/arch/sim/Kconfig index 4d76cf615b0..c3b1b310cf5 100644 --- a/arch/sim/Kconfig +++ b/arch/sim/Kconfig @@ -23,6 +23,10 @@ config HOST_ARM bool "arm" select ARCH_HAVE_STACKCHECK +config HOST_ARM64 + bool "arm64" + select ARCH_HAVE_STACKCHECK + endchoice # Host CPU Type config ARCH_CHIP diff --git a/arch/sim/include/inttypes.h b/arch/sim/include/inttypes.h index de370b48820..3e08442427c 100644 --- a/arch/sim/include/inttypes.h +++ b/arch/sim/include/inttypes.h @@ -104,7 +104,8 @@ # define UINT16_C(x) x # define UINT32_C(x) x ## u -#if defined(CONFIG_HOST_X86_64) && !defined(CONFIG_SIM_M32) +#if (defined(CONFIG_HOST_X86_64) && !defined(CONFIG_SIM_M32)) || \ + defined(CONFIG_HOST_ARM64) # define PRIdPTR "ld" # define PRIiPTR "li" # define PRIoPTR "lo" diff --git a/arch/sim/include/limits.h b/arch/sim/include/limits.h index 921d5219424..608675084fa 100644 --- a/arch/sim/include/limits.h +++ b/arch/sim/include/limits.h @@ -54,14 +54,15 @@ /* These change on 32-bit and 64-bit platforms */ -#if !defined(CONFIG_HOST_X86_64) || defined(CONFIG_SIM_M32) -# define LONG_MIN (-LONG_MAX - 1) -# define LONG_MAX 2147483647L -# define ULONG_MAX 4294967295UL -#else +#if (defined(CONFIG_HOST_X86_64) && !defined(CONFIG_SIM_M32)) || \ + defined(CONFIG_HOST_ARM64) # define LONG_MIN (-LONG_MAX - 1) # define LONG_MAX 9223372036854775807L # define ULONG_MAX 18446744073709551615UL +#else +# define LONG_MIN (-LONG_MAX - 1) +# define LONG_MAX 2147483647L +# define ULONG_MAX 4294967295UL #endif #define LLONG_MIN (-LLONG_MAX - 1) @@ -71,12 +72,13 @@ /* A pointer is 4 or 8 bytes */ #define PTR_MIN (-PTR_MAX - 1) -#if !defined(CONFIG_HOST_X86_64) || defined(CONFIG_SIM_M32) -# define PTR_MAX 2147483647 -# define UPTR_MAX 4294967295U -#else +#if (defined(CONFIG_HOST_X86_64) && !defined(CONFIG_SIM_M32)) || \ + defined(CONFIG_HOST_ARM64) # define PTR_MAX 9223372036854775807LL # define UPTR_MAX 18446744073709551615ULL +#else +# define PTR_MAX 2147483647 +# define UPTR_MAX 4294967295U #endif #endif /* __ARCH_SIM_INCLUDE_LIMITS_H */ diff --git a/arch/sim/include/setjmp.h b/arch/sim/include/setjmp.h index eb95709264d..20f8bdfbfee 100644 --- a/arch/sim/include/setjmp.h +++ b/arch/sim/include/setjmp.h @@ -41,6 +41,7 @@ # define XCPTCONTEXT_SIZE (8 * XCPTCONTEXT_REGS) # ifdef __ASSEMBLY__ + # define JB_RBX (0*8) # define JB_RSP (1*8) # define JB_RBP (2*8) @@ -51,6 +52,7 @@ # define JB_RSI (7*8) # else + # define JB_RBX (0) # define JB_RSP (1) # define JB_RBP (2) @@ -75,6 +77,7 @@ # define XCPTCONTEXT_SIZE (4 * XCPTCONTEXT_REGS) # ifdef __ASSEMBLY__ + # define JB_EBX (0*4) # define JB_ESI (1*4) # define JB_EDI (2*4) @@ -83,6 +86,7 @@ # define JB_PC (5*4) # else + # define JB_EBX (0) # define JB_ESI (1) # define JB_EDI (2) @@ -97,12 +101,42 @@ # define JB_FP JB_EBP #elif defined(CONFIG_HOST_ARM) + # define XCPTCONTEXT_REGS 16 # define XCPTCONTEXT_SIZE (4 * XCPTCONTEXT_REGS) # define JB_FP 7 # define JB_SP 8 # define JB_PC 9 + +#elif defined(CONFIG_HOST_ARM64) + +# define XCPTCONTEXT_REGS 32 +# define XCPTCONTEXT_SIZE (8 * XCPTCONTEXT_REGS) + +# ifdef __ASSEMBLY__ + +# define JB_X19_X20 #0x00 +# define JB_X21_X22 #0x10 +# define JB_X23_X24 #0x20 +# define JB_X25_X26 #0x30 +# define JB_X27_X28 #0x40 +# define JB_X29_XLR #0x50 +# define JB_XFP_XSP #0x60 + +# define JB_D08_D09 #0x70 +# define JB_D10_D11 #0x80 +# define JB_D12_D13 #0x90 +# define JB_D14_D15 #0xA0 + +# else + +# define JB_PC (11) +# define JB_FP (12) +# define JB_SP (13) + +# endif /* __ASSEMBLY__ */ + #endif /**************************************************************************** @@ -113,6 +147,7 @@ typedef unsigned long xcpt_reg_t; typedef xcpt_reg_t jmp_buf[XCPTCONTEXT_REGS]; + #endif /**************************************************************************** diff --git a/arch/sim/src/Makefile b/arch/sim/src/Makefile index a26b0fe9ec4..a7a4c12a722 100644 --- a/arch/sim/src/Makefile +++ b/arch/sim/src/Makefile @@ -49,6 +49,8 @@ else ifeq ($(CONFIG_HOST_X86),y) ASRCS += up_vfork_x86.S else ifeq ($(CONFIG_HOST_ARM),y) ASRCS += up_vfork_arm.S +else ifeq ($(CONFIG_HOST_ARM64),y) + ASRCS += up_vfork_arm64.S endif AOBJS = $(ASRCS:.S=$(OBJEXT)) diff --git a/arch/sim/src/sim/up_hostmemory.c b/arch/sim/src/sim/up_hostmemory.c index 0d8ddb18d9f..5875c8e8281 100644 --- a/arch/sim/src/sim/up_hostmemory.c +++ b/arch/sim/src/sim/up_hostmemory.c @@ -63,8 +63,16 @@ void *host_alloc_heap(size_t sz) { void *p; +#if defined(CONFIG_HOST_MACOS) && defined(CONFIG_HOST_ARM64) + /* see: https://developer.apple.com/forums/thread/672804 */ + + p = mmap(NULL, sz, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_SHARED, -1, 0); +#else p = mmap(NULL, sz, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0); +#endif + if (p == MAP_FAILED) { return NULL; diff --git a/arch/sim/src/sim/up_initialstate.c b/arch/sim/src/sim/up_initialstate.c index fe719d385ae..a257b5d1cf6 100644 --- a/arch/sim/src/sim/up_initialstate.c +++ b/arch/sim/src/sim/up_initialstate.c @@ -82,12 +82,19 @@ void up_initial_state(struct tcb_s *tcb) * Thus, we need to emulate the effect of a CALL here, by subtracting * sizeof(xcpt_reg_t), which is the amount a CALL would move RSP to store * the return address. + * + * Note: On ARM64 architectures the return address is passed via LR + * register. No extra adjustment for the stack needed. */ - tcb->xcp.regs[JB_SP] = (xcpt_reg_t)tcb->stack_base_ptr + - tcb->adj_stack_size - - sizeof(xcpt_reg_t); + tcb->xcp.regs[JB_SP] = (xcpt_reg_t)tcb->stack_base_ptr +#if !defined(CONFIG_HOST_ARM64) + - sizeof(xcpt_reg_t) +#endif + + tcb->adj_stack_size; + tcb->xcp.regs[JB_PC] = (xcpt_reg_t)tcb->start; + #ifdef CONFIG_SIM_ASAN __asan_unpoison_memory_region(tcb->stack_alloc_ptr, tcb->adj_stack_size); #endif diff --git a/arch/sim/src/sim/up_vfork_arm64.S b/arch/sim/src/sim/up_vfork_arm64.S new file mode 100644 index 00000000000..1a863e1ec63 --- /dev/null +++ b/arch/sim/src/sim/up_vfork_arm64.S @@ -0,0 +1,116 @@ +/**************************************************************************** + * arch/sim/src/sim/up_vfork_arm64.S + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ***************************************************************************/ + +/**************************************************************************** + * Included Files + ***************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ***************************************************************************/ + +#if defined(CONFIG_HOST_MACOS) + #define SYMBOL(x) _##x +#else + #define SYMBOL(x) x +#endif + +/**************************************************************************** + * Public Symbols + ***************************************************************************/ + + .file "up_vfork_arm64.S" + .globl SYMBOL(up_vfork) + .globl SYMBOL(setjmp) + +/**************************************************************************** + * Public Functions + ***************************************************************************/ + +/**************************************************************************** + * Name: vfork + * + * Description: + * The vfork() function has the same effect as fork(), except that the + * behavior is undefined if the process created by vfork() either modifies + * any data other than a variable of type pid_t used to store the return + * value from vfork(), or returns from the function in which vfork() was + * called, or calls any other function before successfully calling _exit() + * or one of the exec family of functions. + * + * This thin layer implements vfork by simply calling up_vfork() with the + * vfork() context as an argument. The overall sequence is: + * + * 1) User code calls vfork(). vfork() collects context information and + * transfers control up up_vfork(). + * 2) up_vfork() and calls nxtask_setup_vfork(). + * 3) nxtask_setup_vfork() allocates and configures the child task's TCB. + * This consists of: + * - Allocation of the child task's TCB. + * - Initialization of file descriptors and streams + * - Configuration of environment variables + * - Allocate and initialize the stack + * - Setup the input parameters for the task. + * - Initialization of the TCB (including call to up_initial_state()) + * 4) up_vfork() provides any additional operating context. up_vfork must: + * - Initialize special values in any CPU registers that were not + * already configured by up_initial_state() + * 5) up_vfork() then calls nxtask_start_vfork() + * 6) nxtask_start_vfork() then executes the child thread. + * + * Input Parameters: + * None + * + * Returned Value: + * Upon successful completion, vfork() returns 0 to the child process and + * returns the process ID of the child process to the parent process. + * Otherwise, -1 is returned to the parent, no child process is created, + * and errno is set to indicate the error. + * + ***************************************************************************/ + + .text + .globl SYMBOL(vfork) + .align 4 + +SYMBOL(vfork): + + stp x29, x30, [sp] /* save FP/LR register */ + sub sp, sp, #XCPTCONTEXT_SIZE /* area from stack for setjmp() */ + + mov x0, sp /* pass stack area to setjmp() */ + bl SYMBOL(setjmp) /* save register for longjmp() */ + + subs x0, x0, #1 /* 0: parent / 1: child */ + cbz x0, 1f /* child --> return */ + + mov x0, sp /* pass stack area to up_vfork() */ + bl SYMBOL(up_vfork) /* further process task creation */ + +1: + add sp, sp, #XCPTCONTEXT_SIZE /* release area from stack */ + ldp x29, x30, [sp] /* restore FP/LR register */ + + ret + + .end diff --git a/boards/sim/sim/sim/README.txt b/boards/sim/sim/sim/README.txt index e203a358c9b..f3295362973 100644 --- a/boards/sim/sim/sim/README.txt +++ b/boards/sim/sim/sim/README.txt @@ -472,6 +472,7 @@ Common Configuration Information CONFIG_HOST_WINDOWS=n CONFIG_HOST_X86=y CONFIG_HOST_X86_64=n + CONFIG_HOST_ARM64=n b. Linux, 64-bit CPU, 32-bit build @@ -479,6 +480,7 @@ Common Configuration Information CONFIG_HOST_WINDOWS=n CONFIG_HOST_X86=n CONFIG_HOST_X86_64=y + CONFIG_HOST_ARM64=n CONFIG_SIM_X8664_MICROSOFT=n CONFIG_SIM_X8664_SYSTEMV=y CONFIG_SIM_M32=y @@ -489,6 +491,7 @@ Common Configuration Information CONFIG_HOST_WINDOWS=n CONFIG_HOST_X86=n CONFIG_HOST_X86_64=y + CONFIG_HOST_ARM64=n CONFIG_SIM_X8664_MICROSOFT=n CONFIG_SIM_X8664_SYSTEMV=y CONFIG_SIM_M32=n @@ -500,6 +503,7 @@ Common Configuration Information CONFIG_WINDOWS_CYGWIN=y CONFIG_HOST_X86=y CONFIG_HOST_X86_64=n + CONFIG_HOST_ARM64=n e. Cygwin64, 64-bit, 32-bit build @@ -512,6 +516,7 @@ Common Configuration Information CONFIG_WINDOWS_CYGWIN=y CONFIG_HOST_X86=n CONFIG_HOST_X86_64=y + CONFIG_HOST_ARM64=n CONFIG_SIM_X8664_MICROSOFT=y CONFIG_SIM_X8664_SYSTEMV=n CONFIG_SIM_M32=n @@ -523,6 +528,31 @@ Common Configuration Information CONFIG_HOST_WINDOWS=n CONFIG_HOST_X86=n CONFIG_HOST_X86_64=y + CONFIG_HOST_ARM64=n + CONFIG_SIM_X8664_MICROSOFT=n + CONFIG_SIM_X8664_SYSTEMV=y + CONFIG_SIM_M32=n + + h. macOS M1, 64-bit, 64-bit build + + CONFIG_HOST_LINUX=n + CONFIG_HOST_MACOS=y + CONFIG_HOST_WINDOWS=n + CONFIG_HOST_X86=n + CONFIG_HOST_X86_64=n + CONFIG_HOST_ARM64=y + CONFIG_SIM_X8664_MICROSOFT=n + CONFIG_SIM_X8664_SYSTEMV=y + CONFIG_SIM_M32=n + + i. Linux ARM64, 64-bit, 64-bit build + + CONFIG_HOST_LINUX=y + CONFIG_HOST_MACOS=n + CONFIG_HOST_WINDOWS=n + CONFIG_HOST_X86=n + CONFIG_HOST_X86_64=n + CONFIG_HOST_ARM64=y CONFIG_SIM_X8664_MICROSOFT=n CONFIG_SIM_X8664_SYSTEMV=y CONFIG_SIM_M32=n diff --git a/libs/libc/machine/sim/Make.defs b/libs/libc/machine/sim/Make.defs index d478341f3c8..d4067597eeb 100644 --- a/libs/libc/machine/sim/Make.defs +++ b/libs/libc/machine/sim/Make.defs @@ -48,6 +48,10 @@ else ifeq ($(CONFIG_HOST_ARM),y) ifeq ($(CONFIG_ARCH_SETJMP_H),y) ASRCS += arch_setjmp_arm.S endif +else ifeq ($(CONFIG_HOST_ARM64),y) +ifeq ($(CONFIG_ARCH_SETJMP_H),y) +ASRCS += arch_setjmp_arm64.S +endif endif DEPPATH += --dep-path machine/sim diff --git a/libs/libc/machine/sim/arch_setjmp_arm64.S b/libs/libc/machine/sim/arch_setjmp_arm64.S new file mode 100644 index 00000000000..e3f06a1a2ea --- /dev/null +++ b/libs/libc/machine/sim/arch_setjmp_arm64.S @@ -0,0 +1,92 @@ +/**************************************************************************** + * libs/libc/machine/sim/arch_setjmp_arm64.S + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#if defined(CONFIG_HOST_MACOS) + #define SYMBOL(x) _##x +#else + #define SYMBOL(x) x +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + + .text + .globl SYMBOL(setjmp) + .align 4 + +SYMBOL(setjmp): + + stp x19, x20, [x0, JB_X19_X20] + stp x21, x22, [x0, JB_X21_X22] + stp x23, x24, [x0, JB_X23_X24] + stp x25, x26, [x0, JB_X25_X26] + stp x27, x28, [x0, JB_X27_X28] + stp x29, lr, [x0, JB_X29_XLR] + mov x1, sp /* STP can't access SP */ + stp fp, x1, [x0, JB_XFP_XSP] + stp d8, d9, [x0, JB_D08_D09] + stp d10, d11, [x0, JB_D10_D11] + stp d12, d13, [x0, JB_D12_D13] + stp d14, d15, [x0, JB_D14_D15] + + mov x0,#0 /* return value */ + ret + + .text + .globl SYMBOL(longjmp) + .align 4 + +SYMBOL(longjmp): + + ldp x19, x20, [x0, JB_X19_X20] + ldp x21, x22, [x0, JB_X21_X22] + ldp x23, x24, [x0, JB_X23_X24] + ldp x25, x26, [x0, JB_X25_X26] + ldp x27, x28, [x0, JB_X27_X28] + ldp x29, lr, [x0, JB_X29_XLR] + ldp fp, x2, [x0, JB_XFP_XSP] + ldp d8, d9, [x0, JB_D08_D09] + ldp d10, d11, [x0, JB_D10_D11] + ldp d12, d13, [x0, JB_D12_D13] + ldp d14, d15, [x0, JB_D14_D15] + mov sp, x2 /* LDP can't access SP */ + + mov x0, x1 + cmp x0, #0 + b.ne 1f /* return 1, if val is 0 */ + + mov x0,#1 /* return value */ + +1: + ret + + .end diff --git a/tools/sethost.sh b/tools/sethost.sh index 12cb93cde1e..fbeca61302d 100755 --- a/tools/sethost.sh +++ b/tools/sethost.sh @@ -112,10 +112,10 @@ fi if [ -z "$cpu" ]; then case $(uname -m) in arm64) - cpu=arm + cpu=arm64 ;; aarch64) - cpu=arm + cpu=arm64 ;; *) # Assume x86_64 as default @@ -164,9 +164,9 @@ if [ "X$host" == "Xlinux" -o "X$host" == "Xmacos" -o "X$host" == "Xbsd" ]; then kconfig-tweak --file $nuttx/.config --disable CONFIG_HOST_BSD kconfig-tweak --file $nuttx/.config --enable CONFIG_HOST_LINUX - if [ "X$cpu" == "Xarm" ]; then - echo " Select CONFIG_HOST_ARM=y" - kconfig-tweak --file $nuttx/.config --enable CONFIG_HOST_ARM + if [ "X$cpu" == "Xarm64" ]; then + echo " Select CONFIG_HOST_ARM64=y" + kconfig-tweak --file $nuttx/.config --enable CONFIG_HOST_ARM64 fi elif [ "X$host" == "Xbsd" ]; then @@ -181,9 +181,9 @@ if [ "X$host" == "Xlinux" -o "X$host" == "Xmacos" -o "X$host" == "Xbsd" ]; then kconfig-tweak --file $nuttx/.config --disable CONFIG_HOST_BSD kconfig-tweak --file $nuttx/.config --enable CONFIG_HOST_MACOS - if [ "X$cpu" == "Xarm" ]; then - echo " Select CONFIG_HOST_ARM=y" - kconfig-tweak --file $nuttx/.config --enable CONFIG_HOST_ARM + if [ "X$cpu" == "Xarm64" ]; then + echo " Select CONFIG_HOST_ARM64=y" + kconfig-tweak --file $nuttx/.config --enable CONFIG_HOST_ARM64 fi fi