Hi,
I am trying to take control at EL3 level and want to run my code on Juno. I am using arm-trusted-firmware package running on Juno.
In order to achieve this I am using DS-5 debugger to breakthrough the code and setting the PC to my code but instead of executing next instruction it is jumping back to some 0x400_F000 address.
I am not sure how I can achieve this ? What i simply want is to take control at EL3 level and execute my code. I believe it is possible at BL3-1 level, is it correct ?
I found example for bare-metal applications but the control transfer is happening at EL1-NS mode whereas I need EL3 level control.
Thanks,
Hi armdev,
It isn't a great idea to "bypass" the ARM Trusted Firmware on Juno, because it controls the uploading of the firmware to the system power controller. However once it gets to EL2 or EL1N and spins around (if you're using Ash Wilding's stub, or just stop at UEFI) and you're using DS-5 (or any debugger), you have full control - the ARMv8 architecture actually defines special exception level entry and return instructions (DCPS et al.) which means it can put the core into any exception level you wish.
You could write a script that essentially sets SCTLR_EL3.M to 0 (disabling the MMU) and load code to the EL3 physical address space (i.e. loadfile EL3:0xNNNNNNNNNN), then set the "PC" to that same address. The debugger should do the right thing when it continues execution.
Let us know if you have any issues doing the above.
Ta,
Matt Sealey
Hi Matt,
I am not able to find how to execute DCPS3 instruction.
I can run rest of the script but could not find how to execute core instructions using DS-5 script.
# Change to EL3 level
# set variable $DCPS3
set variable $SCTLR_EL3.M=0
set variable $PC=0x80000000
armdev wrote: I am not able to find how to execute DCPS3 instruction. I can run rest of the script but could not find how to execute core instructions using DS-5 script. # Change to EL3 level # set variable $DCPS3 set variable $SCTLR_EL3.M=0 set variable $PC=0x80000000
armdev wrote:
Try this:
set var $AARCH64::$System::$PSTATE::$Mode.M = 13
set var $SCTLR_EL3.M = 0
set var $PC=EL3:0x80000000
The address space prefix isn't important except to make the script readable. Once you change the current PSTATE Mode field the core will be in EL3.
Note that what we're doing here is architecturally impossible, this is a debugger trick - you can't write to the current mode field, but the debugger knows that it should execute DCPS3 to get to EL3 (which is what '13' decodes to)
Matt
Correction of command -
set variable $Core::$CPSR.M=13
I am facing one more issue when I use above method to change to EL3h mode. Issue is when I read the CurrentEL value I am reading back 12 which is EL3t not EL3h. I am not sure how to resolve this ? I thought if I change mode to 13 the sp should be selected to sp_el3.
Thanks
This is normal. PSTATE.CurrentEL reports the current exception level only - if you want to know if you're in EL3h vs. EL3t then you need to also read out PSTATE.SPSel (note that it is inverted compared to the bottom bit of the faux-CPSR.M field).
I am facing another issue with this approach where I see one FIQ is always pending and this causes issues when I run my Guest OS.
I tried masking FIQs at different levels but ISR_EL1 always shows FIQ interrupt pending.
It seems that FIQ is already distributed to core when I switch mode.
Is there any way when I take control at EL2 and move to EL3 but I don't have any FIQs pending ?
I also tried following the newly posted tutorial but the commands doesn't work for me so I have added my errors in "comments" section
http://community.arm.com/docs/DOC-10206#comment-14854
I am not sure if last command with AXI and masking interrupts is doing the same ?
Please let me know if there is any way to achieve this ?
Thanks.