(root)/
gcc-13.2.0/
libgcc/
config/
arm/
cmse.c
       1  /* ARMv8-M Security Extensions routines.
       2     Copyright (C) 2015-2023 Free Software Foundation, Inc.
       3     Contributed by ARM Ltd.
       4  
       5     This file is free software; you can redistribute it and/or modify it
       6     under the terms of the GNU General Public License as published by the
       7     Free Software Foundation; either version 3, or (at your option) any
       8     later version.
       9  
      10     This file is distributed in the hope that it will be useful, but
      11     WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     General Public License for more details.
      14  
      15     Under Section 7 of GPL version 3, you are granted additional
      16     permissions described in the GCC Runtime Library Exception, version
      17     3.1, as published by the Free Software Foundation.
      18  
      19     You should have received a copy of the GNU General Public License and
      20     a copy of the GCC Runtime Library Exception along with this program;
      21     see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
      22     <http://www.gnu.org/licenses/>.  */
      23  
      24  
      25  #if __ARM_FEATURE_CMSE & 1
      26  
      27  #include <arm_cmse.h>
      28  
      29  /* ARM intrinsic function to perform a permission check on a given
      30     address range.  See ACLE changes for ARMv8-M.  */
      31  
      32  void *
      33  __attribute__ ((warn_unused_result))
      34  cmse_check_address_range (void *p, size_t size, int flags)
      35  {
      36    cmse_address_info_t permb, perme;
      37    char *pb = (char *) p, *pe;
      38  
      39    /* Check if the range wraps around.  */
      40    if (__UINTPTR_MAX__ - (__UINTPTR_TYPE__) p < size)
      41      return NULL;
      42  
      43    /* Check if an unknown flag is present.  */
      44    int known = CMSE_MPU_UNPRIV | CMSE_MPU_READWRITE | CMSE_MPU_READ;
      45    int known_secure_level = CMSE_MPU_UNPRIV;
      46  #if __ARM_FEATURE_CMSE & 2
      47    known |= CMSE_AU_NONSECURE | CMSE_MPU_NONSECURE;
      48    known_secure_level |= CMSE_MPU_NONSECURE;
      49  #endif
      50    if (flags & (~known))
      51      return NULL;
      52  
      53    /* Execute the right variant of the TT instructions.  */
      54    pe = pb + size - 1;
      55    const int singleCheck
      56      = (((__UINTPTR_TYPE__) pb ^ (__UINTPTR_TYPE__) pe) < 32);
      57    switch (flags & known_secure_level)
      58      {
      59      case 0:
      60        permb = cmse_TT (pb);
      61        perme = singleCheck ? permb : cmse_TT (pe);
      62        break;
      63      case CMSE_MPU_UNPRIV:
      64        permb = cmse_TTT (pb);
      65        perme = singleCheck ? permb : cmse_TTT (pe);
      66        break;
      67  #if __ARM_FEATURE_CMSE & 2
      68      case CMSE_MPU_NONSECURE:
      69        permb = cmse_TTA (pb);
      70        perme = singleCheck ? permb : cmse_TTA (pe);
      71        break;
      72      case CMSE_MPU_UNPRIV | CMSE_MPU_NONSECURE:
      73        permb = cmse_TTAT (pb);
      74        perme = singleCheck ? permb : cmse_TTAT (pe);
      75        break;
      76  #endif
      77      default:
      78        /* Invalid flag, eg.  CMSE_MPU_NONSECURE specified but
      79  	 __ARM_FEATURE_CMSE & 2 == 0.  */
      80        return NULL;
      81      }
      82  
      83    /* Check that the range does not cross MPU, SAU, or IDAU boundaries.  */
      84    if (permb.value != perme.value)
      85      return NULL;
      86  
      87    /* Check the permissions on the range.  */
      88    switch (flags & (~known_secure_level))
      89      {
      90  #if __ARM_FEATURE_CMSE & 2
      91      case CMSE_MPU_READ | CMSE_MPU_READWRITE | CMSE_AU_NONSECURE:
      92      case		 CMSE_MPU_READWRITE | CMSE_AU_NONSECURE:
      93        return permb.flags.nonsecure_readwrite_ok	? p : NULL;
      94      case CMSE_MPU_READ | CMSE_AU_NONSECURE:
      95        return permb.flags.nonsecure_read_ok	? p : NULL;
      96      case CMSE_AU_NONSECURE:
      97        return permb.flags.secure			? NULL : p;
      98  #endif
      99      case CMSE_MPU_READ | CMSE_MPU_READWRITE:
     100      case		 CMSE_MPU_READWRITE:
     101        return permb.flags.readwrite_ok		? p : NULL;
     102      case CMSE_MPU_READ:
     103        return permb.flags.read_ok		? p : NULL;
     104      default:
     105        return NULL;
     106      }
     107  }
     108  
     109  
     110  #endif /* __ARM_FEATURE_CMSE & 1.  */