ARM Cortex-A32 AArch32 HYP Mode to SVC Mode Transition Issue
The ARM Cortex-A32 processor, operating in AArch32 state, supports multiple privilege levels, including Hypervisor (HYP) mode (EL2) and Supervisor (SVC) mode (EL1). Transitioning between these modes is a critical operation during system initialization, particularly when moving from a higher privilege level (HYP mode) to a lower one (SVC mode). However, this transition can fail if the processor state is not correctly configured or if the instructions used to perform the transition violate architectural constraints.
In the provided scenario, the processor remains stuck in HYP mode (CPSR = 0x600001DA) after attempting to switch to SVC mode using the eret
instruction. The failure occurs despite the code appearing to execute without errors, indicating a subtle issue with the configuration of the Saved Program Status Register (SPSR) or the use of the msr
instruction.
Incorrect Use of Banked Register MSR Instruction
The root cause of the failure lies in the misuse of the msr spsr_hyp, r0
instruction. The ARM Architecture Reference Manual (ARM ARM) specifies strict constraints on the use of banked register forms of the msr
instruction. Specifically, the banked register form of msr
is intended for accessing registers that are not ordinarily accessible in the current mode. In HYP mode, the SPSR_Hyp register is the regular SPSR for that mode, and using the banked register form to access it is architecturally undefined (UNPRED).
The ARM ARM (Section F5.2.2) explicitly states that the following registers cannot be accessed using the banked register form of msr
in HYP mode:
- Monitor mode registers (SP_mon, LR_mon, SPSR_mon)
- Current mode registers (R8_usr-R12_usr, SP_hyp, LR_usr, SPSR_hyp)
In this case, the msr spsr_hyp, r0
instruction attempts to write to the SPSR_Hyp register using the banked register form, which is not permitted. This results in an undefined behavior, causing the processor to ignore the mode change request and remain in HYP mode.
Correcting the SPSR Configuration and Using the Proper MSR Form
To resolve the issue, the msr
instruction must be replaced with the correct form that writes to the SPSR in a manner compliant with the ARM architecture. The recommended approach is to use the msr spsr_cxsf, #Mode_SVC
instruction, which directly sets the SPSR to the desired mode (SVC) without violating architectural constraints.
The corrected code should look like this:
change_to_svc:
ldr r0, =0x1d3 @ Load SVC mode value (0x1D3) into r0
msr spsr_cxsf, r0 @ Set SPSR to SVC mode using the correct MSR form
ldr r0, =continueBoot @ Load the address of the continueBoot label into r0
msr elr_hyp, r0 @ Set the Exception Link Register (ELR) for HYP mode
eret @ Execute exception return to switch to SVC mode
nop @ No operation (placeholder)
continueBoot: @ Continue with bootup
Explanation of the Corrected Code
- Loading the SVC Mode Value: The value
0x1D3
corresponds to the CPSR configuration for SVC mode with interrupts disabled. This value is loaded into registerr0
. - Setting the SPSR: The
msr spsr_cxsf, r0
instruction writes the value inr0
to the SPSR. Thespsr_cxsf
suffix indicates that the instruction operates on the entire SPSR, including the control, extension, status, and flags fields. - Setting the Exception Link Register (ELR): The address of the
continueBoot
label is loaded intor0
and then written to the ELR_Hyp register. This ensures that theeret
instruction will branch to the correct address after the mode transition. - Executing the Exception Return: The
eret
instruction performs the mode transition by restoring the CPSR from the SPSR and branching to the address in the ELR_Hyp register.
Additional Considerations
- Interrupt Handling: Ensure that interrupts are disabled during the mode transition to prevent unexpected behavior. This can be achieved by setting the appropriate bits in the CPSR value loaded into the SPSR.
- Stack Pointer Configuration: If the stack pointer (SP) is used in SVC mode, ensure that it is properly initialized before or after the mode transition.
- Debugging and Verification: Use a debugger to verify that the CPSR is correctly updated after the
eret
instruction. The CPSR should reflect the new mode (SVC) and any other configured settings (e.g., interrupt masks).
Summary of Key Points
- The banked register form of
msr
cannot be used to access the SPSR_Hyp register in HYP mode. - The correct form of the
msr
instruction for setting the SPSR ismsr spsr_cxsf, #Mode_SVC
. - The
eret
instruction performs the mode transition by restoring the CPSR from the SPSR and branching to the address in the ELR_Hyp register. - Proper initialization of the stack pointer and interrupt handling is essential for a successful mode transition.
By following these steps and ensuring compliance with the ARM architecture, the transition from HYP mode to SVC mode on the Cortex-A32 processor can be reliably achieved.