152 lines
3.1 KiB
ArmAsm
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
|