rt/arch/arm/m/syscall-v6-v8base.S

152 lines
3.1 KiB
ArmAsm

@ vim:ft=arm
/*
* This variant of the syscall handler supports armv6-m and armv8-m.base.
*
* armv8-m.base also supports cbz while armv6-m does not, but otherwise they
* support the same subset of armv{7,8}-m that makes the save/restore procedure
* different, mainly due to the lack of stmdb and ldm.w/stm.w.
*/
#include <rt/mpu.h>
#include "exc_return.h"
#if RT_MPU_ENABLE
#define CONTROL_SIZE 4
#define controltemp r2,
#define getcontrol mrs r2, control
#define setcontrol msr control, r2
.macro mpuconfigure
ldr r1, =rt_mpu_config
ldr r1, [r1]
ldr r2, =0xE000ED98
mpuset RT_MPU_TASK_REGION_START_ID, RT_MPU_NUM_TASK_REGIONS
dsb
.endm
.macro mpuset r, n
.if \n == 0
.exitm
.endif
#if __ARM_ARCH == 8
mov r3, \r & 0xFC
str r3, [r2]
#endif
ldmia r1!, {r4-r5}
str r4, [r2, 4]
str r5, [r2, 8]
mpuset (\r + 1), (\n - 1)
.endm
#else
#define CONTROL_SIZE 0
#define controltemp
#define getcontrol
#define setcontrol
#define mpuconfigure
#endif
#if __ARM_ARCH == 8
#define PSPLIM_SIZE 4
#define psplimtemp r3,
#define getpsplim mrs r3, psplim
#define setpsplim msr psplim, r3
#define returnifnull cbz r0, .Lreturn
#else /* v6 */
#define PSPLIM_SIZE 0
#define psplimtemp
#define getpsplim
#define setpsplim
#define returnifnull cmp r0, 0; beq .Lreturn
#endif
#define CONTEXT_SIZE (32 + PSPLIM_SIZE + CONTROL_SIZE)
.syntax unified
.section .text.rt_syscall_handler,"ax",%progbits
.global rt_syscall_handler
.type rt_syscall_handler, %function
rt_syscall_handler:
bl rt_syscall_run
// If there's no new context to switch to, return early.
returnifnull
// Store the suspending task's context to its stack.
mrs r1, psp
subs r1, CONTEXT_SIZE
ldr r2, =rt_context_prev
ldr r2, [r2]
str r1, [r2]
getcontrol
getpsplim
stmia r1!, {controltemp psplimtemp r4-r7}
mov r4, r8
mov r5, r9
mov r6, r10
mov r7, r11
stmia r1!, {r4-r7}
mpuconfigure
// Load the new context returned by rt_syscall_run.
mov r1, r0
adds r0, CONTEXT_SIZE - 16
ldmia r0!, {r4-r7}
mov r8, r4
mov r9, r5
mov r10, r6
mov r11, r7
ldmia r1!, {controltemp psplimtemp r4-r7}
// Set the new stack pointer.
msr psp, r0
setcontrol
setpsplim
.Lreturn:
movs r0, TASK_INITIAL_EXC_RETURN_NEG
negs r0, r0
bx r0
.size rt_syscall_handler, .-rt_syscall_handler
.section .text.rt_start,"ax",%progbits
.global rt_start
.type rt_start, %function
rt_start:
bl rt_start_context
mpuconfigure
mov r1, r0
adds r0, CONTEXT_SIZE - 16
ldmia r0!, {r4-r7}
mov r8, r4
mov r9, r5
mov r10, r6
mov r11, r7
ldmia r1!, {controltemp psplimtemp r4-r7}
msr psp, r0
setpsplim
movs r0, 2
msr control, r0
isb
// Once we are using the process stack pointer, interrupts can be enabled.
cpsie i
// Copy pc to the psr slot so it can be popped.
ldr r0, [sp, 24]
str r0, [sp, 28]
ldr r0, [sp, 16]
mov r12, r0
ldr r0, [sp, 20]
mov lr, r0
pop {r0-r3}
add sp, 12
pop {pc}
.size rt_start, .-rt_start