diff --git a/arch/sandbox/cpu/cpu.c b/arch/sandbox/cpu/cpu.c index d4ad020012e..cde0b055a67 100644 --- a/arch/sandbox/cpu/cpu.c +++ b/arch/sandbox/cpu/cpu.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -164,3 +165,15 @@ ulong timer_get_boot_us(void) return (count - base_count) / 1000; } + +int setjmp(jmp_buf jmp) +{ + return os_setjmp((ulong *)jmp, sizeof(*jmp)); +} + +void longjmp(jmp_buf jmp, int ret) +{ + os_longjmp((ulong *)jmp, ret); + while (1) + ; +} diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index d76d0211a2d..5839932b005 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -628,3 +629,25 @@ void os_localtime(struct rtc_time *rt) rt->tm_yday = tm->tm_yday; rt->tm_isdst = tm->tm_isdst; } + +int os_setjmp(ulong *jmp, int size) +{ + jmp_buf dummy; + + /* + * We cannot rely on the struct name that jmp_buf uses, so use a + * local variable here + */ + if (size < sizeof(dummy)) { + printf("setjmp: jmpbuf is too small (%d bytes, need %d)\n", + size, sizeof(jmp_buf)); + return -ENOSPC; + } + + return setjmp((struct __jmp_buf_tag *)jmp); +} + +void os_longjmp(ulong *jmp, int ret) +{ + longjmp((struct __jmp_buf_tag *)jmp, ret); +} diff --git a/arch/sandbox/include/asm/setjmp.h b/arch/sandbox/include/asm/setjmp.h new file mode 100644 index 00000000000..0fb1a11f234 --- /dev/null +++ b/arch/sandbox/include/asm/setjmp.h @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) 2018 Google, Inc + * Written by Simon Glass + */ + +#ifndef _SETJMP_H_ +#define _SETJMP_H_ + +struct jmp_buf_data { + /* + * We're not sure how long this should be: + * + * amd64: 200 bytes + * arm64: 392 bytes + * armhf: 392 bytes + * + * So allow space for all of those, plus some extra. + * We don't need to worry about 16-byte alignment, since this does not + * run on Windows. + */ + ulong data[128]; +}; + +typedef struct jmp_buf_data jmp_buf[1]; + +int setjmp(jmp_buf jmp); +__noreturn void longjmp(jmp_buf jmp, int ret); + +#endif /* _SETJMP_H_ */ diff --git a/include/os.h b/include/os.h index 64e89a06c94..c8e0f52d306 100644 --- a/include/os.h +++ b/include/os.h @@ -330,4 +330,25 @@ int os_spl_to_uboot(const char *fname); */ void os_localtime(struct rtc_time *rt); +/** + * os_setjmp() - Call setjmp() + * + * Call the host system's setjmp() function. + * + * @jmp: Buffer to store current execution state + * @size: Size of buffer + * @return normal setjmp() value if OK, -ENOSPC if @size is too small + */ +int os_setjmp(ulong *jmp, int size); + +/** + * os_longjmp() - Call longjmp() + * + * Call the host system's longjmp() function. + * + * @jmp: Buffer where previous execution state was stored + * @ret: Value to pass to longjmp() + */ +void os_longjmp(ulong *jmp, int ret); + #endif