I am trapping IRQs that are prompted in Secure World to a Rich OS in Non Secure World over the Monitor IRQ-Handler. The Rich OS should not notice that the Interrupt was catched by the Monitor, therefore the Monitor IRQ-Handler branches, after storing and loading registers, directly to the IRQ section of the Normal World`s interrupt vector table. After executing the Normal World IRQ-Handler I want to resume in Normal World where it stopped execution at the last World switch. Therefore I am saving the respective address in the link register when switching to the Normal World IRQ-Handler. The switching is done via "MOVS pc, lr" since I need to switch from Monitor-Mode to IRQ-Mode and execute the branch atomically. However MOVS is updating the link register of the IRQ-Mode which I need to return into normal World Supervisor Mode. With the wrong value in lr I cannot properly return from Normal World IRQ-Handler.
Why is MOVS updating lr? I could not find this behavior in the ARM specs on MOVS.
Did anybody implement something like this before? What instruction could I use instead of MOVS which does not perform an update on the link register? How would you recommend trapping Interrupts to Non Secure World over Monitor whithout the Rich OS in Non Secure World knowing or caring that the Interrupt was originally catched in Monitor IRQ-Handler? Is there any template code describing handling of secure (FIQ) and non-secure (IRQ) interrupts?
Any help is appreciated. Thank you.
Thanks for your reply. I'm talking about a Cortex-A9. I am trapping IRQs into monitor whilst running in secure world.
What I want to achieve is transferring the IRQ request to normal world whithout having to adjust the Linux kernel's interrupt handling in the normal world. I want the Linux kernel to run as usual as if there is no monitor or TEE. This is why the kernel needs not to know that I catched the IRQ in monitor-mode before I issued it to the normal world. I thought jumping to the normal worlds interrupt vector table from monitor-IRQ-handler would be a good idea.Is there any other whay to achieve this?
I believe what you want to do is the standard idea for Trustzone. However there should be no need to look at the non-secure IRQ vector. I think how it is envisaged is this
The secure side can be entered either by an SMC or by a FIQ. It may sometimes also be interrupted by an IRQ or FIQ whilst already in secure mode.
Secure mode will always have IRQs disabled whilst handling FIQs or IRQs.
An IRQ if accepted stops the execution of an SMC and is handled by non-secure mode.
What happens for an IRQ is that secure mode exits back to the SMC setting the return code saying the SMC is pending or aborted, the IRQ is still outstanding and a normal interrupt happens. When the interrupt returns execution continues after the SMC call and one can test its return code to see it is pending or aborted and whether one can try again.