diff --git a/arch/arm/core/swap_helper.S b/arch/arm/core/swap_helper.S index 7705352bfc6..7d1cc48481f 100644 --- a/arch/arm/core/swap_helper.S +++ b/arch/arm/core/swap_helper.S @@ -418,6 +418,14 @@ _do_syscall: ldr r6, =K_SYSCALL_BAD valid_syscall_id: + push {r0, r1} + ldr r0, =_kernel + ldr r0, [r0, #_kernel_offset_to_current] + ldr r1, [r0, #_thread_offset_to_mode] + bic r1, #1 + /* Store (privileged) mode in thread's mode state variable */ + str r1, [r0, #_thread_offset_to_mode] + dsb /* set mode to privileged, r2 still contains value from CONTROL */ bic r2, #1 msr CONTROL, r2 @@ -427,6 +435,7 @@ valid_syscall_id: * instructions with the previous privilege. */ isb + pop {r0, r1} /* return from SVC to the modified LR - _arm_do_syscall */ bx lr diff --git a/arch/arm/core/userspace.S b/arch/arm/core/userspace.S index 996e08b08aa..c2a1fce8196 100644 --- a/arch/arm/core/userspace.S +++ b/arch/arm/core/userspace.S @@ -242,6 +242,14 @@ dispatch_syscall: ldr ip, [sp,#8] msr PSP, ip + push {r0, r1} + ldr r0, =_kernel + ldr r0, [r0, #_kernel_offset_to_current] + ldr r1, [r0, #_thread_offset_to_mode] + orrs r1, r1, #1 + /* Store (unprivileged) mode in thread's mode state variable */ + str r1, [r0, #_thread_offset_to_mode] + dsb /* drop privileges by setting bit 0 in CONTROL */ mrs ip, CONTROL orrs ip, ip, #1 @@ -252,6 +260,7 @@ dispatch_syscall: * instructions with the previous privilege. */ isb + pop {r0, r1} /* Zero out volatile (caller-saved) registers so as to not leak state from * kernel mode. The C calling convention for the syscall handler will