1. You are using two applications? One of them is Linux? What kind of Linux? What kernel? Second of them is MQX? Is it true?
I am running two OS's. One is a stock Linux. The 2nd is MQX with modified interrupt handling, no DMA, no NEON, etc. However, that really doesn't matter to the problem.
2. Both applications are runnign simultaneously and working with some exceptions? OK?
Yes. Trustzone works with three sets of vector tables. Again, it really doesn't matter.
3. When you unmask EA in Linux, then everything is OK? But when you unmask EA in MQX, then fault?
No. This is incorrect. EA is mask/unmasked in the secure world (MQX), then there is no issue; there is no issue with the secure world (or a regular Vybrid boot) When the 'normal' world first executes, there is some 'EA' signaled to the CPU. If the normal world is allowed to mask EA (configured via TrustZone) and it is always masked, then there is no issue. However, Linux wishes to unmask the EA; normally it is quite far into the boot process. I modified the Monitor/TrustZone to not allow the normal world (Linux OR bare metal) to not be able to mask EA and to trap these to the monitor. [Aside: After this, I disable the trap to monitor on EA and allow Linux (normal world) to mask/unmask and everything is fine]. In all cases, the monitor gets the EA with the 'lr' set to the first instruction + 8. Ie, there seems to be some EA signaled as soon as the first instruction executes. The only way to clear it, is to take the exception in the monitor and return. After doing this, everything can work as normal. The MQX exeception table has nothing to do with it. There are three exception tables,
- Linux (normal world)
- MQX (secure world)
- Monitor
It is configured which mode takes the exceptions when an abort happens. I have tried several permutations. I don't have trouble handling the execption. I want to know WHY does the first normal world instruction cause an external abort? It certainly could be something that I need to set up before executing in the 'normal world', but I have no way to figure out what it is. There are many sub-systems to the Vybrid and I can't really know what device caused the exception. The normal world banked FAR is bogus and set with whatever I initially write to it before starting the 'normal world'. The symptoms are the same whether Linux runs or a bare metal application. It is does not needed to have two OS's running. Just setup an environment to run a small routine in the 'normal world'; interrupts do not need to be handled in the 'normal world' as a pure polling system also exhibit the problem.
So perhaps, the CAAM, the L1/L2 cache, TZASC, etc are triggering an EA (I haven't explicitly configured every peripherals in the system). Or maybe there is some spurious EA signaled when the normal world first starts. I want to know what peripheral/sub-system it is and if it can be prevented or if I must trap the first instruction to execute. Perhaps I will execute some 'trusted' code in the normal world to get rid of the spurious EA (if that is the case). I believe that I read the ISR,
| |
asm(" mrc p15, 0, %0, c12, c1, 0\n" : "=r"(tmp)); /* ISR */ |
And it does not appear until the normal world executes (bit 8) and it stays until someone takes an EA exception and then it is cleared and does not re-occur.