Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===---- arm_cmse.h - Arm CMSE support -----------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8.  
  9. #ifndef __ARM_CMSE_H
  10. #define __ARM_CMSE_H
  11.  
  12. #if (__ARM_FEATURE_CMSE & 0x1)
  13. #include <stddef.h>
  14. #include <stdint.h>
  15.  
  16. #define __ARM_CMSE_SECURE_MODE (__ARM_FEATURE_CMSE & 0x2)
  17. #define CMSE_MPU_READWRITE 1 /* checks if readwrite_ok field is set */
  18. #define CMSE_AU_NONSECURE  2 /* checks if permissions have secure field unset */
  19. #define CMSE_MPU_UNPRIV    4 /* sets T flag on TT insrtuction */
  20. #define CMSE_MPU_READ      8 /* checks if read_ok field is set */
  21. #define CMSE_MPU_NONSECURE 16 /* sets A flag, checks if secure field unset */
  22. #define CMSE_NONSECURE (CMSE_AU_NONSECURE | CMSE_MPU_NONSECURE)
  23.  
  24. #define cmse_check_pointed_object(p, f) \
  25.   cmse_check_address_range((p), sizeof(*(p)), (f))
  26.  
  27. #if defined(__cplusplus)
  28. extern "C" {
  29. #endif
  30.  
  31. typedef union {
  32.   struct cmse_address_info {
  33. #ifdef __ARM_BIG_ENDIAN
  34.     /* __ARM_BIG_ENDIAN */
  35. #if (__ARM_CMSE_SECURE_MODE)
  36.     unsigned idau_region : 8;
  37.     unsigned idau_region_valid : 1;
  38.     unsigned secure : 1;
  39.     unsigned nonsecure_readwrite_ok : 1;
  40.     unsigned nonsecure_read_ok : 1;
  41. #else
  42.     unsigned : 12;
  43. #endif
  44.     unsigned readwrite_ok : 1;
  45.     unsigned read_ok : 1;
  46. #if (__ARM_CMSE_SECURE_MODE)
  47.     unsigned sau_region_valid : 1;
  48. #else
  49.     unsigned : 1;
  50. #endif
  51.     unsigned mpu_region_valid : 1;
  52. #if (__ARM_CMSE_SECURE_MODE)
  53.     unsigned sau_region : 8;
  54. #else
  55.     unsigned : 8;
  56. #endif
  57.     unsigned mpu_region : 8;
  58.  
  59. #else /* __ARM_LITTLE_ENDIAN */
  60.     unsigned mpu_region : 8;
  61. #if (__ARM_CMSE_SECURE_MODE)
  62.     unsigned sau_region : 8;
  63. #else
  64.     unsigned : 8;
  65. #endif
  66.     unsigned mpu_region_valid : 1;
  67. #if (__ARM_CMSE_SECURE_MODE)
  68.     unsigned sau_region_valid : 1;
  69. #else
  70.     unsigned : 1;
  71. #endif
  72.     unsigned read_ok : 1;
  73.     unsigned readwrite_ok : 1;
  74. #if (__ARM_CMSE_SECURE_MODE)
  75.     unsigned nonsecure_read_ok : 1;
  76.     unsigned nonsecure_readwrite_ok : 1;
  77.     unsigned secure : 1;
  78.     unsigned idau_region_valid : 1;
  79.     unsigned idau_region : 8;
  80. #else
  81.     unsigned : 12;
  82. #endif
  83. #endif /*__ARM_LITTLE_ENDIAN */
  84.   } flags;
  85.   unsigned value;
  86. } cmse_address_info_t;
  87.  
  88. static cmse_address_info_t __attribute__((__always_inline__, __nodebug__))
  89. cmse_TT(void *__p) {
  90.   cmse_address_info_t __u;
  91.   __u.value = __builtin_arm_cmse_TT(__p);
  92.   return __u;
  93. }
  94. static cmse_address_info_t __attribute__((__always_inline__, __nodebug__))
  95. cmse_TTT(void *__p) {
  96.   cmse_address_info_t __u;
  97.   __u.value = __builtin_arm_cmse_TTT(__p);
  98.   return __u;
  99. }
  100.  
  101. #if __ARM_CMSE_SECURE_MODE
  102. static cmse_address_info_t __attribute__((__always_inline__, __nodebug__))
  103. cmse_TTA(void *__p) {
  104.   cmse_address_info_t __u;
  105.   __u.value = __builtin_arm_cmse_TTA(__p);
  106.   return __u;
  107. }
  108. static cmse_address_info_t __attribute__((__always_inline__, __nodebug__))
  109. cmse_TTAT(void *__p) {
  110.   cmse_address_info_t __u;
  111.   __u.value = __builtin_arm_cmse_TTAT(__p);
  112.   return __u;
  113. }
  114. #endif
  115.  
  116. #define cmse_TT_fptr(p) cmse_TT(__builtin_bit_cast(void *, (p)))
  117. #define cmse_TTT_fptr(p) cmse_TTT(__builtin_bit_cast(void *, (p)))
  118.  
  119. #if __ARM_CMSE_SECURE_MODE
  120. #define cmse_TTA_fptr(p) cmse_TTA(__builtin_bit_cast(void *, (p)))
  121. #define cmse_TTAT_fptr(p) cmse_TTAT(__builtin_bit_cast(void *, (p)))
  122. #endif
  123.  
  124. static void *__attribute__((__always_inline__))
  125. cmse_check_address_range(void *__pb, size_t __s, int __flags) {
  126.   uintptr_t __begin = (uintptr_t)__pb;
  127.   uintptr_t __end = __begin + __s - 1;
  128.  
  129.   if (__end < __begin)
  130.     return NULL; /* wrap around check */
  131.  
  132.   /* Check whether the range crosses a 32-bytes aligned address */
  133.   const int __single_check = (__begin ^ __end) < 0x20u;
  134.  
  135.   /* execute the right variant of the TT instructions */
  136.   void *__pe = (void *)__end;
  137.   cmse_address_info_t __permb, __perme;
  138.   switch (__flags & (CMSE_MPU_UNPRIV | CMSE_MPU_NONSECURE)) {
  139.   case 0:
  140.     __permb = cmse_TT(__pb);
  141.     __perme = __single_check ? __permb : cmse_TT(__pe);
  142.     break;
  143.   case CMSE_MPU_UNPRIV:
  144.     __permb = cmse_TTT(__pb);
  145.     __perme = __single_check ? __permb : cmse_TTT(__pe);
  146.     break;
  147. #if __ARM_CMSE_SECURE_MODE
  148.   case CMSE_MPU_NONSECURE:
  149.     __permb = cmse_TTA(__pb);
  150.     __perme = __single_check ? __permb : cmse_TTA(__pe);
  151.     break;
  152.   case CMSE_MPU_UNPRIV | CMSE_MPU_NONSECURE:
  153.     __permb = cmse_TTAT(__pb);
  154.     __perme = __single_check ? __permb : cmse_TTAT(__pe);
  155.     break;
  156. #endif
  157.   /* if CMSE_NONSECURE is specified w/o __ARM_CMSE_SECURE_MODE */
  158.   default:
  159.     return NULL;
  160.   }
  161.  
  162.   /* check that the range does not cross MPU, SAU, or IDAU region boundaries */
  163.   if (__permb.value != __perme.value)
  164.     return NULL;
  165. #if !(__ARM_CMSE_SECURE_MODE)
  166.   /* CMSE_AU_NONSECURE is only supported when __ARM_FEATURE_CMSE & 0x2 */
  167.   if (__flags & CMSE_AU_NONSECURE)
  168.     return NULL;
  169. #endif
  170.  
  171.   /* check the permission on the range */
  172.   switch (__flags & ~(CMSE_MPU_UNPRIV | CMSE_MPU_NONSECURE)) {
  173. #if (__ARM_CMSE_SECURE_MODE)
  174.   case CMSE_MPU_READ | CMSE_MPU_READWRITE | CMSE_AU_NONSECURE:
  175.   case CMSE_MPU_READWRITE | CMSE_AU_NONSECURE:
  176.     return __permb.flags.nonsecure_readwrite_ok ? __pb : NULL;
  177.  
  178.   case CMSE_MPU_READ | CMSE_AU_NONSECURE:
  179.     return __permb.flags.nonsecure_read_ok ? __pb : NULL;
  180.  
  181.   case CMSE_AU_NONSECURE:
  182.     return __permb.flags.secure ? NULL : __pb;
  183. #endif
  184.   case CMSE_MPU_READ | CMSE_MPU_READWRITE:
  185.   case CMSE_MPU_READWRITE:
  186.     return __permb.flags.readwrite_ok ? __pb : NULL;
  187.  
  188.   case CMSE_MPU_READ:
  189.     return __permb.flags.read_ok ? __pb : NULL;
  190.  
  191.   default:
  192.     return NULL;
  193.   }
  194. }
  195.  
  196. #if __ARM_CMSE_SECURE_MODE
  197. static int __attribute__((__always_inline__, __nodebug__))
  198. cmse_nonsecure_caller(void) {
  199.   return !((uintptr_t)__builtin_return_address(0) & 1);
  200. }
  201.  
  202. #define cmse_nsfptr_create(p)                                                  \
  203.   __builtin_bit_cast(__typeof__(p),                                            \
  204.                      (__builtin_bit_cast(uintptr_t, p) & ~(uintptr_t)1))
  205.  
  206. #define cmse_is_nsfptr(p) ((__builtin_bit_cast(uintptr_t, p) & 1) == 0)
  207.  
  208. #endif /* __ARM_CMSE_SECURE_MODE */
  209.  
  210. void __attribute__((__noreturn__)) cmse_abort(void);
  211. #if defined(__cplusplus)
  212. }
  213. #endif
  214.  
  215. #endif /* (__ARM_FEATURE_CMSE & 0x1) */
  216.  
  217. #endif /* __ARM_CMSE_H */
  218.