/*
* Copyright ( c ) 2013 - 2015 , Google Inc . All rights reserved
*
* Permission is hereby granted , free of charge , to any person obtaining
* a copy of this software and associated documentation files
* ( the " Software " ) , to deal in the Software without restriction ,
* including without limitation the rights to use , copy , modify , merge ,
* publish , distribute , sublicense , and / or sell copies of the Software ,
* and to permit persons to whom the Software is furnished to do so ,
* subject to the following conditions :
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND ,
* EXPRESS OR IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY , FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT .
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM , DAMAGES OR OTHER LIABILITY , WHETHER IN AN ACTION OF CONTRACT ,
* TORT OR OTHERWISE , ARISING FROM , OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE .
*/
#include <asm.h>
#include <lib/sm/monitor.h>
#include <lib/sm/smcall.h>
#include <lib/sm/sm_err.h>
#include <kernel/vm.h>
/*
* Monitor stacks :
* secure context
* non - secure context
*
* Context :
* mon_lr
* usr / sys_sp , usr / sys_lr
* und_spsr , und_sp , und_lr
* abt_spsr , abt_sp , abt_lr
* svc_spsr , svc_sp , svc_lr
* irq_spsr , irq_sp , irq_lr
* fiq_spsr , fiq_r8 - fiq_lr
* r4 - r11 , lr
* r0 - r3 , ip
* lr , spsr
*
*/
#define CONTEXT_SIZE_RETURN (2 * 4 )
#define CONTEXT_SIZE_SCRATCH_GEN_REGS ((5 + 9 ) * 4 )
#define CONTEXT_SIZE_MODE_REGS_MON_RETURN ((8 + 3 + 3 + 3 + 3 + 2 + 1 ) * 4 )
#define CONTEXT_SIZE (CONTEXT_SIZE_RETURN + CONTEXT_SIZE_SCRATCH_GEN_REGS + CONTEXT_SIZE_MODE_REGS_MON_RETURN)
#define MONITOR_STACK_SIZE (CONTEXT_SIZE * 2 )
.macro SAVE_CONTEXT_RETURN
srsdb sp!, #MODE_MON /* srsfd alias not recognized by current assembler */
.endm
.macro SAVE_CONTEXT_GEN_REGS
push {r4-r11, lr}
.endm
.macro SAVE_CONTEXT_SCRATCH_REGS
push {r0-r3, ip}
.endm
.macro SAVE_CONTEXT
SAVE_CONTEXT_RETURN
SAVE_CONTEXT_SCRATCH_REGS
SAVE_CONTEXT_GEN_REGS
.endm
.macro SAVE_CONTEXT_MODE_REGS
mov r4, sp
cps #MODE_FIQ
mrs r5, spsr
stmfd r4!, {r5, r8-lr}
cps #MODE_IRQ
mrs r5, spsr
stmfd r4!, {r5, sp, lr}
cps #MODE_SVC
mrs r5, spsr
stmfd r4!, {r5, sp, lr}
cps #MODE_ABT
mrs r5, spsr
stmfd r4!, {r5, sp, lr}
cps #MODE_UND
mrs r5, spsr
stmfd r4!, {r5, sp, lr}
cps #MODE_SYS
stmfd r4!, {sp, lr}
cps #MODE_MON
mov sp, r4
.endm
.macro SAVE_RETURN_ADDR reg
push {\reg}
.endm
.macro RESTORE_RETURN_ADDR reg
pop {\reg}
.endm
.macro RESTORE_CONTEXT_MODE_REGS
mov r4, sp
cps #MODE_SYS
ldmfd r4!, {sp, lr}
cps #MODE_UND
ldmfd r4!, {r5, sp, lr}
msr spsr, r5
cps #MODE_ABT
ldmfd r4!, {r5, sp, lr}
msr spsr, r5
cps #MODE_SVC
ldmfd r4!, {r5, sp, lr}
msr spsr, r5
cps #MODE_IRQ
ldmfd r4!, {r5, sp, lr}
msr spsr, r5
cps #MODE_FIQ
ldmfd r4!, {r5, r8-lr}
msr spsr, r5
cps #MODE_MON
mov sp, r4
.endm
.macro RESTORE_CONTEXT_GEN_REGS
pop {r4-r11, lr}
.endm
.macro RESTORE_CONTEXT_SCRATCH_REGS
pop {r0-r3, ip}
.endm
.macro RESTORE_CONTEXT_AND_RETURN
RESTORE_CONTEXT_GEN_REGS
add sp, sp, #5 * 4
rfefd sp!
.endm
.p2align 5
.globl monitor_vector_table
monitor_vector_table:
nop /* RESET */
b . /* UNDEF */
b .Lmon_smcall /* SWI */
b . /* IABORT */
b . /* DABORT */
nop /* reserved */
b . /* IRQ */
b .Lmon_fiq_entry /* FIQ */
/*
* Called in monitor mode
* return address in mon - lr
* ns - return address in svc - lr
*/
FUNCTION(monitor_reset)
/* figure out our cpu number */
mrc p15, 0 , r11, c0, c0, 5 /* read MPIDR */
/* mask off the bottom 12 bits to test cluster number:cpu number */
ubfx r11, r11, #0 , #12
/* return if cpu >= SMP_MAX_CPUS */
cmp r11, #SMP_MAX_CPUS
bxge lr
/* find cpu specifc stack offset */
mov ip, #MONITOR_STACK_SIZE
mul r11, r11,ip
adr sp, monitor_reset /* sp = paddr */
ldr ip, =monitor_reset /* ip = vaddr */
sub ip, sp, ip /* ip = phys_offset */
ldr sp, =mon_ns_stack_top /* sp = ns_stack vaddr */
add sp, sp, ip /* sp = ns_stack paddr */
/* apply per-cpu stack offset */
sub sp, sp, r11
/* Save non-secure return address, mode and registers */
cps #MODE_SVC
msr spsr_cfsx, #MODE_SVC_IRQ_DISABLED
SAVE_CONTEXT_RETURN
cps #MODE_MON
SAVE_CONTEXT_SCRATCH_REGS
SAVE_CONTEXT_GEN_REGS
SAVE_CONTEXT_MODE_REGS
ldr r4, =platform_mon_initial_ns_return
SAVE_RETURN_ADDR r4
sub sp, sp, ip /* sp = sp vaddr */
/* Initialize NS mode CPU context registers */
mrc p15, 0 , r4, c12, c0, 0 /* r4 = VBAR */
mrc p15, 0 , r5, c2, c0, 0 /* r5 = TTBR0 */
mrc p15, 0 , r6, c2, c0, 1 /* r6 = TTBR1 */
mrc p15, 0 , r7, c3, c0, 0 /* r7 = DACR */
mrc p15, 0 , r8, c1, c0, 0 /* r8 = SCTLR */
SWITCH_SCR_TO_NONSECURE r9
mcr p15, 0 , r4, c12, c0, 0 /* VBAR = r4 */
mcr p15, 0 , r5, c2, c0, 0 /* TTBR0 = r5 */
mcr p15, 0 , r6, c2, c0, 1 /* TTBR1 = r6 */
mcr p15, 0 , r7, c3, c0, 0 /* DACR = r7 */
mcr p15, 0 , r8, c1, c0, 0 /* SCTLR = r8 */
SWITCH_SCR_TO_SECURE r9
bx lr
FUNCTION(monitor_init_mmu_on)
bx lr
.Lmon_invalid_ns_return_addr:
b .
FUNCTION(mon_initial_ns_return)
cmp lr, #~0
strne lr, [sp, #CONTEXT_SIZE_SCRATCH_GEN_REGS]
b .Lmon_smcall_initial_ns_return
/* direction in flags */
.Lmon_smcall_from_secure:
adreq lr, .Lmon_smcall_secure_return
.Lmon_context_switch:
SAVE_CONTEXT_MODE_REGS
SAVE_RETURN_ADDR lr
addeq sp, sp, #(CONTEXT_SIZE) /* secure => non-secure */
subne sp, sp, #(CONTEXT_SIZE) /* non-secure => secure */
RESTORE_RETURN_ADDR lr
RESTORE_CONTEXT_MODE_REGS
bx lr
.Lmon_smcall:
SAVE_CONTEXT
mrc p15, 0 , r4, c1, c1, 0 /* r4 = SCR */
tst r4, #0 x1
beq .Lmon_smcall_from_secure
SWITCH_SCR_TO_SECURE r4
bl .Lmon_context_switch
.Lmon_smcall_initial_ns_return:
.weak platform_mon_initial_ns_return
platform_mon_initial_ns_return:
RESTORE_CONTEXT_GEN_REGS
ldr lr, [sp]
/* Handle SMC_FC_FIQ_EXIT from non-secure */
cmp lr, #SMC_FC_FIQ_EXIT
beq .Lmon_fiq_exit_return
SWITCH_SCR_TO_NONSECURE r3
mov r0, r1 /* secure os passes the return code in r1 */
add sp, sp, #5 * 4
rfefd sp!
.Lmon_smcall_secure_return:
RESTORE_CONTEXT_AND_RETURN
.Lmon_fiq_entry:
SAVE_CONTEXT
mrc p15, 0 , r4, c1, c1, 0 /* r4 = SCR */
tst r4, #0 x1
beq . /* fiqs are not trapped in secure mode */
ldr r0, =SMC_FC_FIQ_ENTER
SWITCH_SCR_TO_SECURE r4
bl .Lmon_context_switch
SWITCH_SCR_TO_NONSECURE r4
RESTORE_CONTEXT_GEN_REGS
ldr lr, [sp, #(5 * 4 )]
cmp r1, #0 /* secure os passes the return code in r1 */
subne lr, lr, #4
bne .Lmon_fiq_return
ldr r0, [sp, #(6 * 4 )] /* load saved spsr */
mov r1, lr
mov r2, #0 x91 /* fiq mode with IRQ disabled */
str r2, [sp, #(6 * 4 )] /* store spsr */
mrc p15, 0 , r3, c1, c0, 0 /* r3 = Non-secure SCTLR */
tst r3, #(1 << 13 ) /* Non-secure SCTLR.V */
ldrne lr, =0 xffff0000
mrceq p15, 0 , lr, c12, c0, 0 /* lr = VBAR (if not using Hivecs) */
add lr, lr, #0 x1c /* fiq vector offset */
SWITCH_SCR_TO_SECURE r2
/* Set fiq mode lr and spsr */
cps #MODE_FIQ
msr spsr_cfsx, r0
mov lr, r1
cps #MODE_MON
SWITCH_SCR_TO_NONSECURE r2
.Lmon_fiq_return:
str lr, [sp, #(5 * 4 )]
RESTORE_CONTEXT_SCRATCH_REGS
rfefd sp!
.Lmon_fiq_exit_return:
/* Retrieve FIQ mode spsr, lr and restore r0 from FIQ mode r12 */
cps #MODE_FIQ
mov r0, r12 /* restore r0 used for smc number */
mrs r1, spsr
mov r2, lr
cps #MODE_MON
str r2, [sp, #(5 * 4 )] /* save return addr */
/* don't allow return to monitor mode */
and r2, r1, #0 x1f
cmp r2, #MODE_MON
moveq r1, #MODE_UND
str r1, [sp, #(6 * 4 )] /* store spsr */
SWITCH_SCR_TO_NONSECURE r3
mov lr, r0
RESTORE_CONTEXT_SCRATCH_REGS
mov r0, lr
rfefd sp!
.data
.align 3
/* Monitor stack for primary cpu */
LOCAL_DATA(mon_ns_stack)
.skip MONITOR_STACK_SIZE * SMP_MAX_CPUS
LOCAL_DATA(mon_ns_stack_top)
Messung V0.5 in Prozent C=89 H=95 G=91
¤ Dauer der Verarbeitung: 0.18 Sekunden
(vorverarbeitet am 2026-06-27)
¤
*© Formatika GbR, Deutschland