Search code examples
securityarmcortex-a8trustzone

Easiest way to access secure (TrustZone) instructions from privileged context on Cortex A8/DM3730


I have a pretty weird thing I need to do: Access some "secure" instructions for things that don't really need to be done in a secure context. In short: I need to get in to Secure Mode, but not because I want Hardware TPM-ish functionality or anything. I just need access to certain instructions that I wouldn't otherwise have.

We're doing this on Gumstix Overo FireSTORM COMs. It is my understanding these boot securely, but then somewhere (MLO? u-boot?) they switch to non-secure mode, but I could be wrong. The point is that we're certainly doing this from nonsecure (but privileged, see below) mode.

(I authored this question, about direct access to the GHB/BTB of the A8 branch predictor, if you're curious about what I'm looking to do: Write directly to the global history buffer (GHB) or BTB in the branch predictor of a ARM Cortex A8?)

Now, all of this will be done from u-boot (we've got Overo FireSTORM COMs), so luckily I have "privileged" execution. No worries there. And I've looked at other StackOverflow questions, but there doesn't seem to be anything on how, exactly, to get to secure mode. All I really wanna do is access some CP15 registers, and then go back to non-secure mode (and potentially repeat the process).

I've looked into the SMC instruction, but I can't find any documentation on how to appropriately trap the call/where the call goes to/how to set that up, etc.

Is that information anywhere?

To recap, here's what I want to do:

FROM PRIVILEGED EXECUTION: 
Do stuff
Tweak GHB // requires secure execution
Do more stuff
Tweak GHB 
Do more stuff
...
...
...
Do stuff

Any help would CERTAINLY be appreciated!

Thanks to @artlessnoise, I found this file in the u-boot source: /u-boot/arch/arm/cpu/armv7/nonsec_virt.S.

It contains the following code:

/*
* secure monitor handler
* U-boot calls this "software interrupt" in start.S
* This is executed on a "smc" instruction, we use a "smc #0" to switch
* to non-secure state.
* We use only r0 and r1 here, due to constraints in the caller.
*/
   .align  5
_secure_monitor:
   mrc     p15, 0, r1, c1, c1, 0           @ read SCR
   bic     r1, r1, #0x4e                   @ clear IRQ, FIQ, EA, nET bits
   orr     r1, r1, #0x31                   @ enable NS, AW, FW bits

#ifdef CONFIG_ARMV7_VIRT
   mrc     p15, 0, r0, c0, c1, 1           @ read ID_PFR1
   and     r0, r0, #CPUID_ARM_VIRT_MASK    @ mask virtualization bits
   cmp     r0, #(1 << CPUID_ARM_VIRT_SHIFT)
   orreq   r1, r1, #0x100                  @ allow HVC instruction
#endif

   mcr     p15, 0, r1, c1, c1, 0           @ write SCR (with NS bit set)

#ifdef CONFIG_ARMV7_VIRT
   mrceq   p15, 0, r0, c12, c0, 1          @ get MVBAR value
   mcreq   p15, 4, r0, c12, c0, 0          @ write HVBAR
#endif

   movs    pc, lr                          @ return to non-secure SVC

Presumably if I modified the mask for the mcr p15 instruction, I could simply "turn off" the move to nonsecure mode. This will probably kill u-boot, however.

So the question is, then: How do I set the appropriate vector so when I make the SMC call, I jump back into secure mode, and am able to do my GHB/BTB tinkering?

Any other help is appreciated!


Solution

  • The DM3730 on the Gumstix is a GP (general purpose) device, which means it has TrustZone disabled. There's no way you can get in to it.

    See https://stackoverflow.com/a/8028948/6839