diff --git a/arch/Kconfig b/arch/Kconfig index 746b97c1ae1..d1fd94c5dd1 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -144,6 +144,7 @@ config ARCH_X86_64 select ARCH_TOOLCHAIN_GNU select ARCH_HAVE_BACKTRACE select ARCH_HAVE_FORK + select ARCH_HAVE_SETJMP ---help--- x86-64 architectures. diff --git a/arch/x86_64/include/setjmp.h b/arch/x86_64/include/setjmp.h new file mode 100644 index 00000000000..6186d51cfa0 --- /dev/null +++ b/arch/x86_64/include/setjmp.h @@ -0,0 +1,106 @@ +/**************************************************************************** + * arch/x86_64/include/setjmp.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_X86_64_INCLUDE_SETJUMP_H +#define __ARCH_X86_64_INCLUDE_SETJUMP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + + /* Storage order: %rbx, %rsp, %rbp, %r12, %r13, %r14, %r15, %rip */ + +# define XCPTCONTEXT_REGS 9 +# define XCPTCONTEXT_SIZE (8 * XCPTCONTEXT_REGS) + +# ifdef __ASSEMBLY__ + +# define JB_RBX (0*8) +# define JB_RSP (1*8) +# define JB_RBP (2*8) +# define JB_R12 (3*8) +# define JB_R13 (4*8) +# define JB_R14 (5*8) +# define JB_R15 (6*8) +# define JB_RIP (7*8) +# define JB_FLAG (8*8) + +# else + +# define JB_RBX (0) +# define JB_RSP (1) +# define JB_RBP (2) +# define JB_R12 (3) +# define JB_R13 (4) +# define JB_R14 (5) +# define JB_R15 (6) +# define JB_RIP (7) +# define JB_FLAG (8) + +# endif /* __ASSEMBLY__ */ + +/* Compatibility definitions */ + +# define JB_FP JB_RBP +# define JB_SP JB_RSP +# define JB_PC JB_RIP + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +typedef unsigned long xcpt_reg_t; +typedef xcpt_reg_t jmp_buf[XCPTCONTEXT_REGS]; + +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +int setjmp(jmp_buf env); +void longjmp(jmp_buf env, int val) noreturn_function; + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* !__ASSEMBLY__ */ +#endif /* __ARCH_X86_64_INCLUDE_SETJUMP_H */ diff --git a/libs/libc/machine/x86_64/CMakeLists.txt b/libs/libc/machine/x86_64/CMakeLists.txt index 67807c391fc..da64023619a 100644 --- a/libs/libc/machine/x86_64/CMakeLists.txt +++ b/libs/libc/machine/x86_64/CMakeLists.txt @@ -28,4 +28,8 @@ if(CONFIG_LIBC_ARCH_ELF) list(APPEND SRCS arch_elf.c) endif() +if(CONFIG_ARCH_SETJMP_H) + list(APPEND SRCS arch_setjmp_x86_64.S) +endif() + target_sources(c PRIVATE ${SRCS}) diff --git a/libs/libc/machine/x86_64/Make.defs b/libs/libc/machine/x86_64/Make.defs index 120b9ca0041..2e7c4b03808 100644 --- a/libs/libc/machine/x86_64/Make.defs +++ b/libs/libc/machine/x86_64/Make.defs @@ -24,6 +24,9 @@ ifeq ($(CONFIG_LIBC_ARCH_ELF),y) CSRCS += arch_elf64.c endif +ifeq ($(CONFIG_ARCH_SETJMP_H),y) +ASRCS += arch_setjmp_x86_64.S +endif ifeq ($(CONFIG_X86_64_MEMCMP),y) ASRCS += arch_memcmp.S endif diff --git a/libs/libc/machine/x86_64/arch_setjmp_x86_64.S b/libs/libc/machine/x86_64/arch_setjmp_x86_64.S new file mode 100644 index 00000000000..acba19fb42b --- /dev/null +++ b/libs/libc/machine/x86_64/arch_setjmp_x86_64.S @@ -0,0 +1,119 @@ +/************************************************************************** + * libs/libc/machine/x86_64/arch_setjmp_x86_64.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 + +/************************************************************************** + * Pre-processor Definitions + **************************************************************************/ + +# define REGS %rdi + +#ifdef __CYGWIN__ +# define SYMBOL(s) _##s +#elif defined(__ELF__) +# define SYMBOL(s) s +#else +# define SYMBOL(s) _##s +#endif + +/************************************************************************** + * Public Functions + **************************************************************************/ + + .text + .align 4 + .globl SYMBOL(setjmp) +#ifdef __ELF__ + .type SYMBOL(setjmp), @function +#endif +SYMBOL(setjmp): + + /* Get the return address, adjusting the stack pointer */ + + pop %rsi + + /* Set up the return value */ + + xorl %eax,%eax + + /* Save 1: rbx */ + + movq %rbx, JB_RBX(REGS) + + /* Save 2: Value of the rsp *after* returning */ + + movq %rsp, JB_RSP(REGS) + + /* Fix up the return stack */ + + push %rsi + + /* Save registers */ + /* Storage order: %rbx, %rsp, %rbp, %r12, %r13, %r14, %r15, %rip */ + + movq %rbp, JB_RBP(REGS) /* Save 3: rbp */ + movq %r12, JB_R12(REGS) /* Save 4: r12 */ + movq %r13, JB_R13(REGS) /* Save 5: r13 */ + movq %r14, JB_R14(REGS) /* Save 6: r14 */ + movq %r15, JB_R15(REGS) /* Save 7: r15 */ + movq %rsi, JB_RIP(REGS) /* Save 8: Return address */ + + ret + +#ifdef __ELF__ + .size SYMBOL(setjmp), . - SYMBOL(setjmp) +#endif + + .align 4 + .globl SYMBOL(longjmp) +#ifdef __ELF__ + .type SYMBOL(longjmp), @function +#endif +SYMBOL(longjmp): + + /* Setup return value */ + + movl %esi,%eax + testl %eax,%eax + jnz 1f + incl %eax + + /* Restore registers */ +1: + movq JB_RBX(REGS),%rbx /* Load 1: rbx */ + movq JB_RSP(REGS),%rsp /* Load 2: rsp */ + movq JB_RBP(REGS),%rbp /* Load 3: rdi */ + movq JB_R12(REGS),%r12 /* Load 4: r12 */ + movq JB_R13(REGS),%r13 /* Load 5: r13 */ + movq JB_R14(REGS),%r14 /* Load 6: r14 */ + movq JB_R15(REGS),%r15 /* Load 7: rbp */ + + /* Jump to the saved return address (rip) */ + + jmp *JB_RIP(REGS) + +#ifdef __ELF__ + .size SYMBOL(longjmp), . - SYMBOL(longjmp) +#endif