1

the basic world switch flow is:

set FIQ to monitor mode

  1. normal world -> FIQ triggered
    1. -> enter monitor mode (do switch to Secure world, restore Secure world context)
    2. -> in Secure world sys mode
    3. -> FIQ is not clear, enter FIQ handler in Secure world

step3 and step 4, after we restore the target context, arm will trigger the exception to enter the exception is the behavior correct? (if we dont branch to FIQ handle in monitor mode vector table)

we need flow like below: (no world context switch case, just enter monitor mode to check if we need world switch, and enter irq exception from monitor mode directly. we need this because of our hw limitation, we only have IRQ in our chip)

set IRQ to monitor mode

  1. normal world user mode -> IRQ triggered
    1. -> enter monitor, do something we want to hook, check if we need context switch, prepare some spsr/lr for IRQ mode
  2. -> enter normal world IRQ mode, irq handling
  3. -> irq done, return back to user mode

for non-world switch case, we would like to let the normal world os does not know about the monitor mode, just though he enters the irq mode directly and return from irq mode. for world switch case, just switch it in the monitor mode.

or it's just do the irq_handle in the monitor mode?

eq.
normal world OS usr mode -> irq -> usr mode
normal world OS usr mode -> monitor to irq handler -> usr mode

is the flow possible and well design?

user487363
  • 153
  • 1
  • 4
  • 11
  • It might help if you cited a specific SOC that you are using (and provided a link to a reference PDF)? – artless noise Dec 20 '16 at 14:31
  • it's a non-popular SOC. In our develop environment, GIC only have IRQ connection to arm core, without FIQ . we would like to run two os in each world. Linux on normal world, rtos on secure world. Both OS have individual interrupts, basically we want them run separately. ARM has one recommend design, IRQ for normal world FIQ in normal world switch to secure world vice verse. But we have only IRQ, so we need to seek if any good solution for IRQ only case. – user487363 Dec 21 '16 at 02:12
  • I believe that 'group 0' interrupts are FIQ and 'group 1' are IRQ. Ie, you classify the interrupts with the DIST in the GIC to be either secure or normal (and therefore FIQ/IRQ). The documents aren't clear on what 'group 0' and 'group 1' mean (See **GICD_IGROUPR** and **GICC_CTLR** w. bit `FIQEnb`). You may have to re-write some RTOS code, especially the system timer to be independant. Also any 'pinctrl' in Linux needs to sync with the RTOS (for security and race reasons). – artless noise Dec 21 '16 at 18:15
  • thank you very much, i understand. i will also check the FIQ of GIC status in the SoC. – user487363 Dec 22 '16 at 03:48
  • The term 'FIQn' is a physical line. Your hardware might not have this. To be clear, the **regular** interrupt sources can be routed to either IRQ or FIQ. As I remember, the GICC_CTRL.FIQEnb will cause group 0 to be all FIQ, but it maybe different for some versions of GIC. – artless noise Dec 22 '16 at 14:20

1 Answers1

3

is the flow possible and well design?

It is possible. 'well designed' is subjective. It has several fails or non-ideal issues. I guess your system doesn't have a GIC; which is a trustzone aware interrupt controller. The GIC has banked registers which allow the normal world OS to use it (almost) as if it was in the secure world.

It is not clear from you question whether you want the secure world to have interrupts? I guess from the statement 'for non-world switch case...'. If you only have interrupts handled by the normal world, things are simple. Don't branch to monitor mode on an IRQ (or FIQ). There is a register to set this behaviour (SCR/security configuration register).

For the dual world interrupt case, you have two issues.

  1. You need to trust the normal world OS.
  2. Interrupt latency will be increased.

You must always take the interrupt in monitor mode. The monitor must check the interrupt controller source to see what world the interrupt belongs to. It may need to do a world switch depending on the world. This will increase interrupt latency. As well, both the normal and secure world will be dealing with the same interrupt controller registers. So you have malicious security concerns and non-malicious race conditions with multiple interrupt drivers trying to manipulate registers (RMW). Generally, if your chip doesn't have a GIC, but the CPU supports TrustZone, the your system hasn't been well thought through for TrustZone use. The L1/L2 cache controllers must also be TrustZone aware and you possible have issue there as well.

If you have Linux (or some other open source OS in the normal world), it would be better to replace the normal world interrupt driver with a 'virtual' interrupt driver. The normal world virtual IRQ code would use the SMC instruction to set virtual registers and register IRQ routines for specific interrupts. The secure world/monitor IRQ code would then branch directly to the decoded IRQ routine.


With a GIC, set the group 0 (secure world) interrupts as FIQ and group 1 (normal world) as IRQ using the GICC_CTLR bit FIQEnb. Ie, you classify the interrupts with the DIST in the GIC to be either secure or normal (and therefore FIQ/IRQ).

You have to work through scheduling issues and how you want the different OS's to pre-empt. Normally (easiest) is to always have the secure OS running, but this means that some Linux (normal world) interrupts may be very delayed by the secure world (RTOS) main line code.

artless noise
  • 21,212
  • 6
  • 68
  • 105
  • it's a non-popular SOC. In our develop environment, GIC only have IRQ connection to arm core, without FIQ . we would like to run two os in each world. Linux on normal world, rtos on secure world. Both OS have individual interrupts, basically we want them run separately. ARM has one recommend design, IRQ for normal world FIQ in normal world switch to secure world vice verse. But we have only IRQ, so we need to seek if any good solution for IRQ only case – user487363 Dec 21 '16 at 02:13
  • we may have different irq handle for two worlds. Like IRQ 1~100 is for normal world OS, IRQ 101~200 is for Secure world OS. It's slightly like visualization, but we dont have hypervisor, and user the monitor mode to achieve this. – user487363 Dec 21 '16 at 02:16
  • So we are confused about the IRQ routing path. we are not sure if the monitor mode branch to two irq handle is fine, like the lr/spsr register. if irq is triggered in usr mode to monitor mode, the lr/spsr is from usr mode, but how to change mode to irq mode / run irq code and keep the return state(lr/spsr) to usr mode? maybe we can push the lr/spsr to irq_sp in monitor mode and change CPSR to irq mode then branch to os's exception vector's irq entry (with some modification in OS's interrupt entry function) ? – user487363 Dec 21 '16 at 02:27
  • You can use `CPSID` to change modes. If there is no way an exception can occur, you can alter the IRQ mode in the 'Secure world' by briefly changing to IRQ mode. The registers are shared between worlds, so **IF** the secure world needs the lr_irq/sp_irq, you need some context block to save these. However, if IRQ is exclusive to the normal world, there is no issue. From secure world monitor, use `CPS` to IRQ and alter SP/LR (use unbanked registers r1-r12 to transfer) and then go back to monitor mode and return to the normal world IRQ. – artless noise Jan 23 '17 at 14:31
  • This [question on banked registers](http://stackoverflow.com/questions/22080918/trustzone-monitor-mode-and-ifar-ifsr-dfar-dfsr) is also probably very useful to people looking at this question. Ie, I am in monitor mode (secure world) and want to look at normal world CP15 registers that are banked (have a normal and secure world version). – artless noise Jan 23 '17 at 14:48