This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

cmse_check_address_range does not work for CortexM33 code built with ARM CC 6.0

Hello,

I am studying Cortex-M33 TrustZone with Armv8-M_security sample code coming from ARM Development Studio 2023.1.  When I add following code into main_s.c to test cmse_check_address_range intrinsic, but it seems does not work when running it in Armv8-M_security_FVP_M33, it always prints not in non-secure region, and checked its disassembly code, that intrinsic does not get called. Please help. 

The source code ( cmse_check_address_range is added within #if 1... #endif) is:


int __attribute__((cmse_nonsecure_entry)) ns_callable_fn1(int x)
{
     printf("Hello from Non-secure Callable Function 1!\n\r");
#if 1
     //Check a memory range is entirely in non-secure region or not
     uint32_t *p = (uint32_t *)0x00200000;
     uint32_t size = 4;
     uint32_t * vRet = 1;
     vRet = cmse_check_address_range( p, size, CMSE_MPU_NONSECURE);

     if (vRet == NULL)
         printf(" NULL returned, (%p, size=%d) is not entirely in non-secure region!\n", p, size);
     else
         printf(" (%p, size=%d) is entirely in non-secure region!\n", p, size);
#endif
     return secure_fn1(x);
}

This disassembly code is:

ns_callable_fn1
0x100012B2 : MOV r0,#0x1423
0x100012B6 : MOVT r0,#0x1000
0x100012BA : BL __2printf ; 0x1000034C
0x100012BE : MOVS r0,#1
0x100012C0 : LSLS r1,r0,#21
0x100012C2 : MOV r0,#0x13de
0x100012C6 : MOVT r0,#0x1000
0x100012CA : MOVS r2,#4
0x100012CC : BL __2printf ; 0x1000034C
0x100012D0 : B {pc}+14 ; 0x100012DE
ns_callable_fn2 + 0x36

Thanks

Parents
  • More experiment:

    1) Copy arm_cmse.h into project directory, rename it to my_arm_cmse.h

    2) Modify cmse_check_address_range(..) by adding a printf statement as below:

    static void *
    cmse_check_address_range(void *__pb, size_t __s, int __flags) {
    uintptr_t __begin = (uintptr_t)__pb;
    uintptr_t __end = __begin + __s - 1;
    printf("__pb = %p\n", __pb);       //<----------------------- added by me to make sure cmse_check_address_range gets called !!
    if (__end < __begin)
    return NULL; /* wrap around check */

    /* Check whether the range crosses a 32-bytes aligned address */
    const int __single_check = (__begin ^ __end) < 0x20u;

    ..

    3) In the main_s.c,  do the following changes to make sure my_arm_cmse.h is included and explicitly define __ARM_FEATURE_CMSE to 3

    #include <stdio.h>
    //#include <arm_cmse.h>
    #define __ARM_FEATURE_CMSE 3
    #include "my_arm_cmse.h"

    4) When int __attribute__((cmse_nonsecure_entry)) ns_callable_fn1(int x) is executed, I can see the output of "__pb=200000" from  cmse_check_address_range(), but the result of cmse_check_address_range is still wrong, check the disassembly code,  there is no TT instruction generated from intrinsics  cmse_TT/cmse_TTT/cmse_TTA/cmse_TTAT. 

    So what causes ARM CC not generating compete assembly code for cmse_check_address_range?

Reply
  • More experiment:

    1) Copy arm_cmse.h into project directory, rename it to my_arm_cmse.h

    2) Modify cmse_check_address_range(..) by adding a printf statement as below:

    static void *
    cmse_check_address_range(void *__pb, size_t __s, int __flags) {
    uintptr_t __begin = (uintptr_t)__pb;
    uintptr_t __end = __begin + __s - 1;
    printf("__pb = %p\n", __pb);       //<----------------------- added by me to make sure cmse_check_address_range gets called !!
    if (__end < __begin)
    return NULL; /* wrap around check */

    /* Check whether the range crosses a 32-bytes aligned address */
    const int __single_check = (__begin ^ __end) < 0x20u;

    ..

    3) In the main_s.c,  do the following changes to make sure my_arm_cmse.h is included and explicitly define __ARM_FEATURE_CMSE to 3

    #include <stdio.h>
    //#include <arm_cmse.h>
    #define __ARM_FEATURE_CMSE 3
    #include "my_arm_cmse.h"

    4) When int __attribute__((cmse_nonsecure_entry)) ns_callable_fn1(int x) is executed, I can see the output of "__pb=200000" from  cmse_check_address_range(), but the result of cmse_check_address_range is still wrong, check the disassembly code,  there is no TT instruction generated from intrinsics  cmse_TT/cmse_TTT/cmse_TTA/cmse_TTAT. 

    So what causes ARM CC not generating compete assembly code for cmse_check_address_range?

Children
  • Is this a bug in ARM CC (v6.21 for ADS 2023.1 and v6.18 for ADS 2022.1) which is similar to GCC Bugzilla - Bug 99157 ?

  • Hi

    My name is Stephen and I work at Arm.  Thanks for your interest in Cortex-M33 TrustZone.

    I can reproduce what you see with cmse_check_address_range(), and I'm investigating further.

    Stephen

  • Hi again

    FYI: your code that calls cmse_check_address_range() didn't compile for me.  
    I had to change:
         uint32_t * vRet = 1;
    to:
         void * vRet;

    An additional flag is required on the call, for example, change:
         vRet = cmse_check_address_range( p, size, CMSE_MPU_NONSECURE);
    to:
         vRet = cmse_check_address_range( p, size, CMSE_MPU_NONSECURE | CMSE_MPU_READ );
         
    With that change, I see a TTA instruction being generated, and get:
    Hello from Non-secure Callable Function 1!
     (00200000, size=4) is entirely in non-secure region!

    See developer.arm.com/.../TT-instruction-intrinsics
    and
    arm-software.github.io/.../cmse.html

    Hope this helps

    Stephen

  • Hi Stephen,

    Thank you for the supports on this issue.

    I tried with flag CMSE_MPU_NONSECURE | CMSE_MPU_READ, and the result was as expected.

    The disassembly code for following branch in cms_check_address_range(void *__pb, size_t __s, int __flags) is optimized by AC6 with compiler option "-O1"

    ...

    #if __ARM_CMSE_SECURE_MODE
    case CMSE_MPU_NONSECURE:
    __permb = cmse_TTA(__pb);
    __perme = __single_check ? __permb : cmse_TTA(__pe);
    break;
    ...

    If changing to use "-O0", the disassembly code matches with C code even with flags set to CMSE_MPU_NONSECURE only.

    This issue can be closed.

    Thanks