1 /* 2 * (C) Copyright 2016 3 * Alexander Graf <agraf@suse.de> 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #ifndef _SETJMP_H_ 9 #define _SETJMP_H_ 1 10 11 struct jmp_buf_data { 12 ulong target; 13 ulong regs[5]; 14 int ret; 15 }; 16 17 typedef struct jmp_buf_data jmp_buf[1]; 18 19 static inline int setjmp(jmp_buf jmp) 20 { 21 jmp->ret = 0; 22 23 #ifdef CONFIG_ARM64 24 asm volatile( 25 "adr x1, jmp_target\n" 26 "str x1, %0\n" 27 "stp x26, x27, %1\n" 28 "stp x28, x29, %2\n" 29 "mov x1, sp\n" 30 "str x1, %3\n" 31 "jmp_target: " 32 : "=m" (jmp->target), "=m" (jmp->regs[0]), 33 "=m" (jmp->regs[2]), "=m" (jmp->regs[4]) 34 : 35 : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", 36 "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", 37 "x16", "x17", "x18", "x19", "x20", "x21", "x22", 38 "x23", "x24", "x25", /* x26, x27, x28, x29, sp */ 39 "x30", "cc", "memory"); 40 #else 41 asm volatile( 42 #if CONFIG_IS_ENABLED(SYS_THUMB_BUILD) 43 ".align 2\n" 44 "adr r0, jmp_target\n" 45 "add r0, r0, $1\n" 46 #else 47 "adr r0, jmp_target\n" 48 #endif 49 "mov r1, %0\n" 50 "mov r2, sp\n" 51 "stm r1!, {r0, r2, r4, r5, r6, r7}\n" 52 ".align 2\n" 53 "jmp_target: \n" 54 : 55 : "l" (&jmp->target) 56 : "r0", "r1", "r2", "r3", /* "r4", "r5", "r6", "r7", */ 57 "r8", "r9", "r10", "r11", /* sp, */ "ip", "lr", 58 "cc", "memory"); 59 #endif 60 61 return jmp->ret; 62 } 63 64 static inline __noreturn void longjmp(jmp_buf jmp, int ret) 65 { 66 jmp->ret = ret; 67 68 #ifdef CONFIG_ARM64 69 asm volatile( 70 "ldr x0, %0\n" 71 "ldr x1, %3\n" 72 "mov sp, x1\n" 73 "ldp x26, x27, %1\n" 74 "ldp x28, x25, %2\n" 75 "mov x29, x25\n" 76 "br x0\n" 77 : 78 : "m" (jmp->target), "m" (jmp->regs[0]), "m" (jmp->regs[2]), 79 "m" (jmp->regs[4]) 80 : "x0", "x1", "x25", "x26", "x27", "x28"); 81 #else 82 asm volatile( 83 "mov r1, %0\n" 84 "ldm r1!, {r0, r2, r4, r5, r6, r7}\n" 85 "mov sp, r2\n" 86 "bx r0\n" 87 : 88 : "l" (&jmp->target) 89 : "r1"); 90 #endif 91 92 while (1) { } 93 } 94 95 96 #endif /* _SETJMP_H_ */ 97