I am implementing a small OS as a university project in a A9 chip (a Xilinx Zynq). I am using trustzone to implement some features and I want to pass through SVC calls from user mode directly to monitor, so I issue an SMC in my SVC handler. Here it is a version of the vector table plus handler which works (I removed other handler code for simplicity):
secure_vectors:ldr pc, _secure_resetb _secure_undefb _secure_svcb _secure_prefAbortb _secure_dataAbortb . /* reserved for HYP mode - not supported */b _secure_irqb . /* reserved for MON mode */
_secure_undef:b ._secure_svc:smc #0movs pc, lr_secure_prefAbort:b ._secure_dataAbort:b ._secure_irq:b
However, I am having an issue if I position my handler code immediately after the vector table. If I position the handler as below, sometimes the SMC call is not issued. When debugging I step through the instruction, but it is as if it never happened since the monitor vector table does not receive the SMC exception:
_secure_svc:smc #0movs pc, lr_secure_undef:b ._secure_prefAbort:b ._secure_dataAbort:b ._secure_irq:b
Even a "NOP" instruction before the handler solves the problem:
nop_secure_svc:smc #0movs pc, lr_secure_undef:b ._secure_prefAbort:b ._secure_dataAbort:b ._secure_irq:b
I really don't understand why this happens. Am I missing missing something obvious?
Thanks for your reply. In my question, I said it "sometimes" does not work. But actually, it never does.
Here is the disassembly of the working case:
00000000 <__secure_vectors_start>: 0: e59ff030 ldr pc, [pc, #48] ; 38 <_secure_reset> 4: ea000005 b 20 <_secure_undef> 8: ea000005 b 24 <_secure_svc> c: ea000006 b 2c <_secure_prefAbort> 10: ea000006 b 30 <_secure_dataAbort> 14: eafffffe b 14 <AP0+0x4> 18: ea000005 b 34 <_secure_irq> 1c: eafffffe b 1c <S_DEVICE_PRIVILEGED+0x5> 00000020 <_secure_undef>: 20: eafffffe b 20 <_secure_undef> 00000024 <_secure_svc>: 24: e1600070 smc 0 28: e1b0f00e movs pc, lr 0000002c <_secure_prefAbort>: 2c: eafffffe b 2c <_secure_prefAbort> 00000030 <_secure_dataAbort>: 30: eafffffe b 30 <_secure_dataAbort> 00000034 <_secure_irq>: 34: eafffffe b 34 <_secure_irq> 00000038 <_secure_reset>: 38: 00100000 .word 0x00100000
Here it is the other working version, with the nop instruction:
Disassembly of section .secure_vectors: 00000000 <__secure_vectors_start>: 0: e59ff034 ldr pc, [pc, #52] ; 3c <_secure_reset> 4: ea000008 b 2c <_secure_undef> 8: ea000005 b 24 <_secure_svc> c: ea000007 b 30 <_secure_prefAbort> 10: ea000007 b 34 <_secure_dataAbort> 14: eafffffe b 14 <AP0+0x4> 18: ea000006 b 38 <_secure_irq> 1c: eafffffe b 1c <S_DEVICE_PRIVILEGED+0x5> 20: e320f000 nop {0} 00000024 <_secure_svc>: 24: e1600070 smc 0 28: e1b0f00e movs pc, lr 0000002c <_secure_undef>: 2c: eafffffe b 2c <_secure_undef> 00000030 <_secure_prefAbort>: 30: eafffffe b 30 <_secure_prefAbort> 00000034 <_secure_dataAbort>: 34: eafffffe b 34 <_secure_dataAbort> 00000038 <_secure_irq>: 38: eafffffe b 38 <_secure_irq> 0000003c <_secure_reset>: 3c: 00100000 .word 0x00100000
Here it is of the not working one:
Disassembly of section .secure_vectors: 00000000 <__secure_vectors_start>: 0: e59ff030 ldr pc, [pc, #48] ; 38 <_secure_reset> 4: ea000007 b 28 <_secure_undef> 8: ea000004 b 20 <_secure_svc> c: ea000006 b 2c <_secure_prefAbort> 10: ea000006 b 30 <_secure_dataAbort> 14: eafffffe b 14 <AP0+0x4> 18: ea000005 b 34 <_secure_irq> 1c: eafffffe b 1c <S_DEVICE_PRIVILEGED+0x5> 00000020 <_secure_svc>: 20: e1600070 smc 0 24: e1b0f00e movs pc, lr 00000028 <_secure_undef>: 28: eafffffe b 28 <_secure_undef> 0000002c <_secure_prefAbort>: 2c: eafffffe b 2c <_secure_prefAbort> 00000030 <_secure_dataAbort>: 30: eafffffe b 30 <_secure_dataAbort> 00000034 <_secure_irq>: 34: eafffffe b 34 <_secure_irq> 00000038 <_secure_reset>: 38: 00100000 .word 0x00100000