From f04eedb60dda7c4ba11d01c9c5d0f3af8cf753b6 Mon Sep 17 00:00:00 2001 From: Hubert Badocha Date: Thu, 28 Nov 2024 15:49:23 +0100 Subject: [PATCH] fork: return value in child Due to exiting on different stack than current's thread in fork in child the return value was not set by threads_setupUserReturn. JIRA: RTOS-979 --- hal/armv7a/_interrupts.S | 20 +++++++++----------- hal/armv7a/exceptions.c | 4 ++-- hal/armv7m/stm32/_init.S | 1 + hal/armv8m/mcx/_init.S | 3 +++ hal/armv8m/nrf/_init.S | 3 +++ hal/armv8r/_interrupts.S | 22 ++++++++++------------ hal/armv8r/exceptions.c | 4 ++-- hal/ia32/_exceptions.S | 7 +++++-- hal/ia32/_interrupts.S | 4 ++-- hal/riscv64/_interrupts.S | 3 +-- hal/riscv64/exceptions.c | 4 ++-- hal/sparcv8leon/_traps.S | 1 + hal/sparcv8leon/exceptions.c | 4 ++-- proc/threads.c | 5 ++--- proc/threads.h | 2 +- syscalls.c | 4 ++-- 16 files changed, 48 insertions(+), 43 deletions(-) diff --git a/hal/armv7a/_interrupts.S b/hal/armv7a/_interrupts.S index 0a343d459..6781c8cb9 100644 --- a/hal/armv7a/_interrupts.S +++ b/hal/armv7a/_interrupts.S @@ -259,31 +259,29 @@ _interrupts_dispatch: .type _syscalls_dispatch, %function _syscalls_dispatch: stmfd sp, {r0-r4}^ - sub r1, sp, #0x14 + sub r2, sp, #0x14 mrs r3, spsr - mov r2, lr + mov r1, lr tst r3, #THUMB_STATE - ldreq r0, [r2, #-4] + ldreq r0, [r1, #-4] biceq r0, r0, #0xff000000 - ldrneh r0, [r2, #-2] + ldrneh r0, [r1, #-2] bicne r0, r0, #0xff00 mrc p15, 0, r4, c13, c0, 4 /* TPIDRPRW */ cpsie af, #SYS_MODE /* Store CPU state onto kernel stack */ - stmfd r4!, {r2} + stmfd r4!, {r1} stmfd r4!, {r5-r14} - mov r2, sp + mov r1, sp mov sp, r4 ldmfd r1, {r4-r8} push {r3-r8} push_fpu_state r4 - sub r1, sp, #8 - push {r1} - push {r1} - - mov r1, r2 + sub r2, sp, #8 + push {r2} + push {r2} cpsie if diff --git a/hal/armv7a/exceptions.c b/hal/armv7a/exceptions.c index 308ead1b4..fbe6968a9 100644 --- a/hal/armv7a/exceptions.c +++ b/hal/armv7a/exceptions.c @@ -116,7 +116,7 @@ static void exceptions_defaultHandler(unsigned int n, exc_context_t *ctx) } -extern void threads_setupUserReturn(void *retval); +extern void threads_setupUserReturn(void *retval, cpu_context_t *ctx); void exceptions_dispatch(unsigned int n, exc_context_t *ctx) @@ -130,7 +130,7 @@ void exceptions_dispatch(unsigned int n, exc_context_t *ctx) /* Handle signals if necessary */ if (hal_cpuSupervisorMode(&ctx->cpuCtx) == 0) { - threads_setupUserReturn((void *)ctx->cpuCtx.r0); + threads_setupUserReturn((void *)ctx->cpuCtx.r0, &ctx->cpuCtx); } } diff --git a/hal/armv7m/stm32/_init.S b/hal/armv7m/stm32/_init.S index 9165cb329..387a9c23b 100644 --- a/hal/armv7m/stm32/_init.S +++ b/hal/armv7m/stm32/_init.S @@ -127,6 +127,7 @@ _syscall_dispatch: /* Copy arguments back to the user stack */ stmdb r0!, {r1-r4} mov r1, r0 + mov r2, sp ldrb r0, [r7, #-3] /* Prepare pseudo context */ diff --git a/hal/armv8m/mcx/_init.S b/hal/armv8m/mcx/_init.S index 0320328e7..7ee9f5a09 100644 --- a/hal/armv8m/mcx/_init.S +++ b/hal/armv8m/mcx/_init.S @@ -139,6 +139,9 @@ _syscall_dispatch: _syscallend: /* return value in r0 */ + mov r1, sp + blx threads_setupUserReturn + ldr lr, [sp, #8] /* psp */ add lr, lr, #(8 * 4) msr psp, lr diff --git a/hal/armv8m/nrf/_init.S b/hal/armv8m/nrf/_init.S index 4667e213e..8ef02db42 100644 --- a/hal/armv8m/nrf/_init.S +++ b/hal/armv8m/nrf/_init.S @@ -139,6 +139,9 @@ _syscall_dispatch: _syscallend: /* return value in r0 */ + mov r1, sp + blx threads_setupUserReturn + ldr lr, [sp, #8] /* psp */ add lr, lr, #(8 * 4) msr psp, lr diff --git a/hal/armv8r/_interrupts.S b/hal/armv8r/_interrupts.S index 801c41471..0dd3f806e 100644 --- a/hal/armv8r/_interrupts.S +++ b/hal/armv8r/_interrupts.S @@ -259,31 +259,29 @@ _interrupts_dispatch: .type _syscalls_dispatch, %function _syscalls_dispatch: stmfd sp, {r0-r4}^ - sub r1, sp, #0x14 + sub r2, sp, #0x14 mrs r3, spsr - mov r2, lr + mov r1, lr tst r3, #THUMB_STATE - ldreq r0, [r2, #-4] + ldreq r0, [r1, #-4] biceq r0, r0, #0xff000000 - ldrneh r0, [r2, #-2] + ldrneh r0, [r1, #-2] bicne r0, r0, #0xff00 mrc p15, 0, r4, c13, c0, 4 /* TPIDRPRW */ cpsie af, #MODE_SYS /* Store CPU state onto kernel stack */ - stmfd r4!, {r2} + stmfd r4!, {r1} stmfd r4!, {r5-r14} - mov r2, sp + mov r1, sp mov sp, r4 - ldmfd r1, {r4-r8} + ldmfd r2, {r4-r8} push {r3-r8} push_fpu_state r4 - sub r1, sp, #8 - push {r1} - push {r1} - - mov r1, r2 + sub r2, sp, #8 + push {r2} + push {r2} cpsie if diff --git a/hal/armv8r/exceptions.c b/hal/armv8r/exceptions.c index b0da21620..b2b4a0d33 100644 --- a/hal/armv8r/exceptions.c +++ b/hal/armv8r/exceptions.c @@ -118,7 +118,7 @@ static void exceptions_defaultHandler(unsigned int n, exc_context_t *ctx) } -extern void threads_setupUserReturn(void *retval); +extern void threads_setupUserReturn(void *retval, cpu_context_t *ctx); void exceptions_dispatch(unsigned int n, exc_context_t *ctx) @@ -135,7 +135,7 @@ void exceptions_dispatch(unsigned int n, exc_context_t *ctx) /* Handle signals if necessary */ if (hal_cpuSupervisorMode(&ctx->cpuCtx) == 0) { - threads_setupUserReturn((void *)ctx->cpuCtx.r0); + threads_setupUserReturn((void *)ctx->cpuCtx.r0, &ctx->cpuCtx); } } diff --git a/hal/ia32/_exceptions.S b/hal/ia32/_exceptions.S index 62ed2f68a..c8e4db7f0 100644 --- a/hal/ia32/_exceptions.S +++ b/hal/ia32/_exceptions.S @@ -169,11 +169,14 @@ sym: addl $4, %esp;\ testl %eax, %eax;\ jnz exception_popContext;\ + /* cpu_context_t */;\ + leal 28(%esp), %eax;\ /* return value */ ;\ - movl 56(%esp), %eax;\ + movl 56(%esp), %ebx;\ pushl %eax;\ + pushl %ebx;\ call threads_setupUserReturn;\ - addl $4, %esp;\ + addl $8, %esp;\ ;\ jmp exception_popContext diff --git a/hal/ia32/_interrupts.S b/hal/ia32/_interrupts.S index 61eff65fb..b1f3974bc 100644 --- a/hal/ia32/_interrupts.S +++ b/hal/ia32/_interrupts.S @@ -213,13 +213,13 @@ _interrupts_syscall: movw %dx, %ds movw %dx, %es movl (4 * CTXPUSHL + 12)(%esp), %edx + pushl %esp pushl %edx pushl %eax sti call syscalls_dispatch cli - addl $8, %esp - movl %eax, (4 * CTXPUSHL - EAX_OFFSET)(%esp) /* Save return value to eax in context */ + addl $12, %esp jmp interrupts_popContextUnlocked .size _interrupts_syscall, .-_interrupts_syscall diff --git a/hal/riscv64/_interrupts.S b/hal/riscv64/_interrupts.S index 7c8a778df..66d5c715a 100644 --- a/hal/riscv64/_interrupts.S +++ b/hal/riscv64/_interrupts.S @@ -281,10 +281,9 @@ _interrupts_notIrq: sd s2, 248(sp) mv a0, a7 /* syscall number */ ld a1, 288(sp) /* ustack */ - + mv a2, sp csrs sstatus, SSTATUS_SIE call syscalls_dispatch - sd a0, 56(sp) csrc sstatus, SSTATUS_SIE tail _interrupts_returnUnlocked diff --git a/hal/riscv64/exceptions.c b/hal/riscv64/exceptions.c index c21b5ca0a..de194dc6f 100644 --- a/hal/riscv64/exceptions.c +++ b/hal/riscv64/exceptions.c @@ -174,7 +174,7 @@ inline ptr_t hal_exceptionsPC(exc_context_t *ctx) } -extern void threads_setupUserReturn(void *retval); +extern void threads_setupUserReturn(void *retval, cpu_context_t *ctx); void exceptions_dispatch(unsigned int n, cpu_context_t *ctx) @@ -195,7 +195,7 @@ void exceptions_dispatch(unsigned int n, cpu_context_t *ctx) /* Handle signals if necessary */ if (hal_cpuSupervisorMode(ctx) == 0) { - threads_setupUserReturn((void *)ctx->a0); + threads_setupUserReturn((void *)ctx->a0, ctx); } } diff --git a/hal/sparcv8leon/_traps.S b/hal/sparcv8leon/_traps.S index 68fabff2a..dd2e380b0 100644 --- a/hal/sparcv8leon/_traps.S +++ b/hal/sparcv8leon/_traps.S @@ -673,6 +673,7 @@ s_wovfl_done: FPU_SAVE s_fpu_done: + mov %sp, %o2 /* cpu_context_t * */ /* allocate stack frame for syscall handler */ sub %sp, 0x60, %sp mov %g4, %o0 /* syscall number */ diff --git a/hal/sparcv8leon/exceptions.c b/hal/sparcv8leon/exceptions.c index 280a169e3..633e5ec8b 100644 --- a/hal/sparcv8leon/exceptions.c +++ b/hal/sparcv8leon/exceptions.c @@ -153,7 +153,7 @@ __attribute__((noreturn)) static void exceptions_defaultHandler(unsigned int n, } -extern void threads_setupUserReturn(void *retval); +extern void threads_setupUserReturn(void *retval, cpu_context_t *ctx); void exceptions_dispatch(unsigned int n, exc_context_t *ctx) @@ -167,7 +167,7 @@ void exceptions_dispatch(unsigned int n, exc_context_t *ctx) /* Handle signals if necessary */ if (hal_cpuSupervisorMode(&ctx->cpuCtx) == 0) { - threads_setupUserReturn((void *)ctx->cpuCtx.o0); + threads_setupUserReturn((void *)ctx->cpuCtx.o0, &ctx->cpuCtx); } } diff --git a/proc/threads.c b/proc/threads.c index 1b9280c9d..46044f182 100644 --- a/proc/threads.c +++ b/proc/threads.c @@ -1482,10 +1482,10 @@ static int _threads_checkSignal(thread_t *selected, process_t *proc, cpu_context } -void threads_setupUserReturn(void *retval) +void threads_setupUserReturn(void *retval, cpu_context_t *ctx) { spinlock_ctx_t sc; - cpu_context_t *ctx, *signalCtx; + cpu_context_t *signalCtx; void *f; void *kstackTop; thread_t *thread; @@ -1494,7 +1494,6 @@ void threads_setupUserReturn(void *retval) thread = _proc_current(); kstackTop = thread->kstack + thread->kstacksz; - ctx = kstackTop - sizeof(*ctx); signalCtx = (void *)((char *)hal_cpuGetUserSP(ctx) - sizeof(*signalCtx)); hal_cpuSetReturnValue(ctx, retval); diff --git a/proc/threads.h b/proc/threads.h index f98206f7b..bbae1fb88 100644 --- a/proc/threads.h +++ b/proc/threads.h @@ -211,7 +211,7 @@ extern int _threads_init(vm_map_t *kmap, vm_object_t *kernel); extern int threads_sigpost(process_t *process, thread_t *thread, int sig); -extern void threads_setupUserReturn(void *retval); +extern void threads_setupUserReturn(void *retval, cpu_context_t *ctx); #endif diff --git a/syscalls.c b/syscalls.c index 6f2b11a32..6b90bb2f7 100644 --- a/syscalls.c +++ b/syscalls.c @@ -1854,7 +1854,7 @@ const void *const syscalls[] = { SYSCALLS(SYSCALLS_NAME) }; const char *const syscall_strings[] = { SYSCALLS(SYSCALLS_STRING) }; -void *syscalls_dispatch(int n, char *ustack) +void *syscalls_dispatch(int n, char *ustack, cpu_context_t *ctx) { void *retval; @@ -1868,7 +1868,7 @@ void *syscalls_dispatch(int n, char *ustack) proc_threadEnd(); } - threads_setupUserReturn(retval); + threads_setupUserReturn(retval, ctx); return retval; }