Dear sirs,
I'm reading arm v8a specification. I found that when arm is in aarch32 state, only a few exceptions can switch to aarch64 depending on the configuration in the registers. the exceptions are as follows.
abort, physical async abort, physical FIQ and physical IRQ
while other exceptions are still processed in aarch32 state.
My questions are as follows.
Q1: Is my understanding correct?
Q2: If Q1 is yes, why these exceptions can be processed and others can not such as underfined instruction, svc, hvc?
Q3: What is the usage case for switch between aarch32 and aarch64?
In addition, exception return from higher exception level after reset can switch to aarch32, right?
cray
Hi Martin,
Thanks for your answer.
you said Any exception could potentially cause a change of Execution state. But I read all the exception processing pseudocode in aarch32. the variable route_to_aarch64 only exists in a few exceptions such as abort. look at the following pseudocode.
if route_to_aarch64 then
AArch64.Abort(ZeroExtend(vaddress), fault);
Only the abort, physical async abort, physical FIQ and physical IRQ exceptions have this pseudocode. How do you explain this condition? Thanks.
I should have been a little more precise. Any exception type in AArch32 state could potentially lead to Execution state changing to AArch64. No exception taken while in AArch64 will result in Execution state changing to AArch32.
For exceptions returns the reverse is true. An exception return in AArch64 might cause execution state to change to AArch32. No exception return in AArch32 can lead to Execution state changing to AArch64(\*).
For both exceptions and exception returns, a change of Execution state can only occur if there is also a change in EL. That is an exception from EL0 to EL1 could lead to a change in Execution state. But an exception from EL1 to EL1 could not.
Let's take one example of an exception not on your list. The pseudo code for the A32/T32 for SVC says:
if ConditionPassed() then EncodingSpecificOperations(); AArch32.CallSupervisor(imm32<15:0>);
Following the chain down:
AArch32.CallSupervisor(bits(16) immediate) ... if AArch32.GeneralExceptionsToAArch64() then AArch64.CallSupervisor(immediate); else AArch32.TakeSVCException(immediate);
So based on on the return value of GeneralExceptionsToAArch64(), either the AArch32 or AArch64 pseudo code gets called. Looking at GeneralExceptionsToAArch64():
boolean AArch32.GeneralExceptionsToAArch64() return ((PSTATE.EL == EL0 && !ELUsingAArch32(EL1)) || (HaveEL(EL2) && !IsSecure() && !ELUsingAArch32(EL2) && HCR_EL2.TGE == '1'));
So the conditions for SVC are:
* Taking SVC from EL0 to EL1, where EL1 is using AArch64 (defined by either SCR_EL3.RW or HCR_EL2.RW depending on Security state)
* Taking SVC from NS.EL0/NS.EL1 when EL2 is using AArch64 (defined by SCR_EL3.RW) and HCR_EL2.TGE==1
(\*) Well, maybe indirectly. The exception return might trigger an exception, and the exception might cause a switch to AArch64. But it is the exception, not the exception return, which is actually causing the Execution state change.
To further expand on Martin's response, for the synchronous exceptions this "interworking" layer exists before the pseudocode function for taking the exception (TakeXXXException). So functions like AArch32.Abort and AArch32.CallSupervisor as in Martin's examples. For the asynchronous exceptions there is a layer of implied pseudocode that is not in the manual. This for instance includes the checks whether the asynchronous exception is masked. However, since this layer of code does not appear in the manual, the route_to_aarch64 is included in the TakeXXXException() function. So it is there for the asynchronous exceptions, but not the synchronous ones.
Dear Martin and Michael,
Thanks very much for your response. This question troubled me for a long time. The architecture manual is so long that I have not read all of it.
I should dig into it to find more information. Now I'm very happy to get the right answer.