1

I am booting Android on an IMX53 Sabre tablet. I am trying to initialize stacks for the different processor modes. The following is my monitor initialization code:

@ Install Secure Monitor
@ -----------------------
ldr r1, =ns_image                   @ R1 is used
str r0, [r1]
ldr r0, =tz_monitor                    @ Get address of Monitors vector table
mcr p15, 0, r0, c12, c0, 1          @ Write Monitor Vector Base Address Register

@ Save Secure state
@ ------------------
ldr    r0, =S_STACK_LIMIT           @ Get address of Secure state stack
stmfd  r0!, {r4-r12}                @ Save general purpose registers
@ ADD support for SPs
mrs    r1, cpsr                     @ Also get a copy of the CPSR
stmfd  r0!, {r1, lr}                @ Save CPSR and LR


ldr r1, =STACK_ADDR

msr cpsr_c, #Mode_FIQ | I_Bit | F_Bit 
sub sp, r1, #Offset_FIQ_Stack

msr cpsr_c, #Mode_IRQ | I_Bit | F_Bit 
sub sp, r1, #Offset_IRQ_Stack

msr cpsr_c, #Mode_ABT | I_Bit | F_Bit 
sub sp, r1, #Offset_ABT_Stack

msr cpsr_c, #Mode_UND | I_Bit | F_Bit  
sub sp, r1, #Offset_UND_Stack   

msr cpsr_c, #Mode_SYS | I_Bit | F_Bit 
sub sp, r1, #Offset_SYS_Stack

msr cpsr_c, #Mode_SVC | I_Bit | F_Bit 
sub sp, r1, #Offset_SVC_Stack

msr cpsr_c, #Mode_MON | I_Bit | F_Bit 
sub sp, r1, #Offset_MON_Stack


cps    #Mode_MON                    @ Move to Monitor mode after saving Secure state


@ Save Secure state stack pointer
@ --------------------------------
ldr r1, =S_STACK_SP                 @ Get address of global
str r0, [r1]                        @ Save pointer


@ Set up initial NS state stack pointer
@ --------------------------------------
ldr r0, =NS_STACK_SP                @ Get address of global
ldr r1, =NS_STACK_LIMIT             @ Get top of Normal state stack (assuming FD model)
str r1, [r0]                        @ Save pointer


@ Set up exception return information
@ ------------------------------------
@IMPORT  ns_image

ldr lr, ns_image                    @ ns_image
msr spsr_cxsf, #Mode_SVC            @ Set SPSR to be SVC mode

@ Switch to Normal world
@ -----------------------
mrc p15, 0, r4, c1, c1, 0           @ Read Secure Configuration Register data
bic r4, #0x66
orr r4, #0x19
//orr r4, #NS_BIT                     @ Set NS bit
mcr p15, 0, r4, c1, c1, 0           @ Write Secure Configuration Register data

@ Clear general purpose registers
@ --------------------------------
mov r0,  #0
mov r1,  #0
mov r2,  #0
mov r3,  #0
mov r4,  #0
mov r5,  #0
mov r6,  #0
mov r7,  #0
mov r8,  #0
mov r9,  #0
mov r10, #0
mov r11, #0
mov r12, #0

movs pc, lr

Android booting happens fine with this, but I am not sure if the stack pointers are set up correctly, as I am not able to use them as described at IMX53 external abort. Are the stack initializations correct?

Other relevant code snippets:

.equ Mode_USR, 0x10 @ User Mode
.equ Mode_FIQ, 0x11 @ Fast Interrupt Mode
.equ Mode_IRQ, 0x12 @ Interrupt Mode
.equ Mode_SVC, 0x13 @ Supervisor Mode
.equ Mode_ABT, 0x17 @ Abort Mode
.equ Mode_UND, 0x1B @ Undefined Mode
.equ Mode_SYS, 0x1F @ System Mode
.equ Mode_MON, 0x16 @ Monitor Mode
.equ STACK_ADDR,    0xa0000000

.equ I_Bit,    0x80 @ IRQ interrupts disabled
.equ F_Bit,    0x40 @ FIQ interrupts disabled
.equ NS_BIT,   0x1



/* memory reserved (in bytes) for stacks of different mode */
.equ Len_FIQ_Stack,  64
.equ Len_IRQ_Stack,  64
.equ Len_ABT_Stack,  64
.equ Len_UND_Stack,  64
.equ Len_SVC_Stack,  64
.equ Len_USR_Stack,  64
.equ Len_MON_Stack,  64
.equ Len_SYS_Stack,  64

.equ Offset_FIQ_Stack, 0
.equ Offset_IRQ_Stack, Offset_FIQ_Stack + Len_FIQ_Stack
.equ Offset_ABT_Stack, Offset_IRQ_Stack + Len_IRQ_Stack
.equ Offset_UND_Stack, Offset_ABT_Stack + Len_ABT_Stack
.equ Offset_SVC_Stack, Offset_UND_Stack + Len_UND_Stack
.equ Offset_USR_Stack, Offset_SVC_Stack + Len_SVC_Stack
.equ Offset_MON_Stack, Offset_USR_Stack + Len_USR_Stack
.equ Offset_SYS_Stack, Offset_MON_Stack + Len_MON_Stack
Community
  • 1
  • 1
rijurekha
  • 21
  • 3
  • 1
    The mode stacks are **NOT** banked between worlds. You can initialize them, but then when Linux boots, it will change them. That is your problem in the other question!?! You need to make a 'world context' that saves/restores the mode registers in use when you take a monitor exception. The only register you can rely on is the `SP_Mon`; Linux can not change it. – artless noise Apr 07 '17 at 13:25
  • That is good to know. But I am a bit confused here, whether non-banked stack pointers is the problem in my other question. If we do not do anything in the handler (no printf, nothing), then why do we need stack pointers to save and restore anything in the handler? As you said, `subs pc ,r14, #4` alone should be enough, just to give back control, if the processor had populated the `r14` or `lr` and the `spsr` correctly on exception. The `spsr` copied back to `cpsr` with the `s` in `subs`, should take care of the processor mode change as well. Can you explain your thoughts here a bit more? – rijurekha Apr 07 '17 at 15:34
  • Yes, the `subs pc, r14, #4` should work. However, the other code might not where you use stack. Also, you can not use anything else in the 'secure world'. Ie, no SMC call, etc. You have interrupts enable and if not masked, they will be taken by the secure handler when they occur with IRQ_sp, etc. Unless you always stay in monitor mode; but that is not good for other reasons. It seems like I had the mode zero issue when the secure world/normal world stacks conflicted. See: [ARM Linux exception stacks](http://stackoverflow.com/questions/22928904/linux-kernel-arm-exception-stack-init) – artless noise Apr 09 '17 at 14:57
  • `init_monitor` starts in `SW`. Should I allocate an `S_STACK` here, to store all the mode specific `sp` on a world switch? Then I initialize 8 `sp` for `SW` with `msr cpsr_c, #Mode_FIQ | I_Bit | F_Bit` to change between modes? After each initialization, I should push the `sp` value to `S_STACK`? Then I set an `NS_STACK`, set `NS` bit, initialize 7 stacks for `NW` (not the `sp_mon`) and store them in the `NS_STACK`? I understand, how in `smc`, I should save one world and restore the other using these stacks, but how to use these in the abort handler where I don't intend to do anything? – rijurekha Apr 10 '17 at 12:21

0 Answers0