This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Can't get RAM-based Secure Entry functions to work

I'm having trouble getting the Secure Entry gateway functions to work out of RAM. The nRF9160 datasheet has RAMNSC configurations, so it should be possible. We're able to get flash-based ones to work. Has anyone been able to have RAM-based Secure Entry functions?

I've confirmed the configuration of RAMNSC as well as RAMREGION in the SPU. It looks like the nRF9160 documentation has an error, however: it says the RAMNSC regions are 8K each, but there are only enough bits for 16K. Can anyone confirm if that's an error? Or perhaps it just doesn't support the full RAM range as NSC?

The only real difference I've noticed (beyond the annoying wrangling to get GCC to do what I want it to) is that there are "veneer" function calls for RAM functions that aren't used when calling the flash counterparts. In particular, it looks like the branch to the SG instruction in flash is a BL, while the branch to the SG instruction in RAM from the veneer is BX. I haven't been able to find any documentation on whether or not various branching methods work or don't work with TrustZone transitions. Is there any info on if BX will work?

Parents
  • Hi Erik,

     

    My apologies for the long waiting time. 

    I've confirmed the configuration of RAMNSC as well as RAMREGION in the SPU. It looks like the nRF9160 documentation has an error, however: it says the RAMNSC regions are 8K each, but there are only enough bits for 16K. Can anyone confirm if that's an error? Or perhaps it just doesn't support the full RAM range as NSC?

    After a bit of back-and-forth, I can confirm that the *NSC[n].SIZE registers can be configured up to 4k each.

    Each NSC function will generate a 2 word veneer (see linker symbols __sg_start / __sg_end), placed in section "sgstubs" (linker script found here). Here's an example from secure_services:

     .gnu.sgstubs.__stub
                    0x0000000000007fe0       0x18 linker stubs
                    0x0000000000007fe0                spm_firmware_info_nse
                    0x0000000000007fe8                spm_request_random_number_nse
                    0x0000000000007ff0                spm_request_read_nse
                    0x0000000000008000                __sg_end = .
                    0x0000000000000020                __sg_size = (__sg_end - __sg_start)
                    0x0000000000008000                . = ALIGN (0x8000)
                    0x0000000000000020                __nsc_size = (. - __sg_start)
                    0x0000000000000001                ASSERT (((__sg_size == 0x0) || ((((0x1 << LOG2CEIL ((0x8000 - (__sg_start % 0x8000)))) == (0x8000 - (__sg_start % 0x8000))) && ((0x8000 - (__sg_start % 0x8000)) >= 0x20)) && ((0x8000 - (__sg_start % 0x8000)) <= 0x1000))), The Non-Secure Callable region size must be a power of 2 between 32 and 4096 bytes.)

    This is a limiting factor on the total amount of NSCallable functions, where its maximum allocation is 512 functions (4096 / 8 bytes) per region.

     

    The only real difference I've noticed (beyond the annoying wrangling to get GCC to do what I want it to) is that there are "veneer" function calls for RAM functions that aren't used when calling the flash counterparts. In particular, it looks like the branch to the SG instruction in flash is a BL, while the branch to the SG instruction in RAM from the veneer is BX. I haven't been able to find any documentation on whether or not various branching methods work or don't work with TrustZone transitions. Is there any info on if BX will work?

    I am sorry, but I do not have an update for this issue yet. I'm still checking internally. Consider this item still open from our side.

     

    Kind regards,

    Håkon 

Reply
  • Hi Erik,

     

    My apologies for the long waiting time. 

    I've confirmed the configuration of RAMNSC as well as RAMREGION in the SPU. It looks like the nRF9160 documentation has an error, however: it says the RAMNSC regions are 8K each, but there are only enough bits for 16K. Can anyone confirm if that's an error? Or perhaps it just doesn't support the full RAM range as NSC?

    After a bit of back-and-forth, I can confirm that the *NSC[n].SIZE registers can be configured up to 4k each.

    Each NSC function will generate a 2 word veneer (see linker symbols __sg_start / __sg_end), placed in section "sgstubs" (linker script found here). Here's an example from secure_services:

     .gnu.sgstubs.__stub
                    0x0000000000007fe0       0x18 linker stubs
                    0x0000000000007fe0                spm_firmware_info_nse
                    0x0000000000007fe8                spm_request_random_number_nse
                    0x0000000000007ff0                spm_request_read_nse
                    0x0000000000008000                __sg_end = .
                    0x0000000000000020                __sg_size = (__sg_end - __sg_start)
                    0x0000000000008000                . = ALIGN (0x8000)
                    0x0000000000000020                __nsc_size = (. - __sg_start)
                    0x0000000000000001                ASSERT (((__sg_size == 0x0) || ((((0x1 << LOG2CEIL ((0x8000 - (__sg_start % 0x8000)))) == (0x8000 - (__sg_start % 0x8000))) && ((0x8000 - (__sg_start % 0x8000)) >= 0x20)) && ((0x8000 - (__sg_start % 0x8000)) <= 0x1000))), The Non-Secure Callable region size must be a power of 2 between 32 and 4096 bytes.)

    This is a limiting factor on the total amount of NSCallable functions, where its maximum allocation is 512 functions (4096 / 8 bytes) per region.

     

    The only real difference I've noticed (beyond the annoying wrangling to get GCC to do what I want it to) is that there are "veneer" function calls for RAM functions that aren't used when calling the flash counterparts. In particular, it looks like the branch to the SG instruction in flash is a BL, while the branch to the SG instruction in RAM from the veneer is BX. I haven't been able to find any documentation on whether or not various branching methods work or don't work with TrustZone transitions. Is there any info on if BX will work?

    I am sorry, but I do not have an update for this issue yet. I'm still checking internally. Consider this item still open from our side.

     

    Kind regards,

    Håkon 

Children
  • Were you able to confirm *NSC[n].REGION is every 4K/8K/16K? We'll be using the smallest size for *NSC[n].SIZE (32 bytes) anyway, so I'm not worried about the size limit for it. But I want to make sure the region I'm selecting is actually getting set correctly.

    I'm quite certain it can't be every 4K for the region selections, since the register won't hold more than 5 bits (confirmed after trying to put 63 in the register, but only reading back 31 after the write). But I want to make sure it's not a silicon bug where only the first half of RAM can be used for NSC entries or something.

Related