Path: blob/main/contrib/llvm-project/clang/lib/Headers/arm_cmse.h
35233 views
//===---- arm_cmse.h - Arm CMSE support -----------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef __ARM_CMSE_H9#define __ARM_CMSE_H1011#if (__ARM_FEATURE_CMSE & 0x1)12#include <stddef.h>13#include <stdint.h>1415#define __ARM_CMSE_SECURE_MODE (__ARM_FEATURE_CMSE & 0x2)16#define CMSE_MPU_READWRITE 1 /* checks if readwrite_ok field is set */17#define CMSE_AU_NONSECURE 2 /* checks if permissions have secure field unset */18#define CMSE_MPU_UNPRIV 4 /* sets T flag on TT insrtuction */19#define CMSE_MPU_READ 8 /* checks if read_ok field is set */20#define CMSE_MPU_NONSECURE 16 /* sets A flag, checks if secure field unset */21#define CMSE_NONSECURE (CMSE_AU_NONSECURE | CMSE_MPU_NONSECURE)2223#define cmse_check_pointed_object(p, f) \24cmse_check_address_range((p), sizeof(*(p)), (f))2526#if defined(__cplusplus)27extern "C" {28#endif2930typedef union {31struct cmse_address_info {32#ifdef __ARM_BIG_ENDIAN33/* __ARM_BIG_ENDIAN */34#if (__ARM_CMSE_SECURE_MODE)35unsigned idau_region : 8;36unsigned idau_region_valid : 1;37unsigned secure : 1;38unsigned nonsecure_readwrite_ok : 1;39unsigned nonsecure_read_ok : 1;40#else41unsigned : 12;42#endif43unsigned readwrite_ok : 1;44unsigned read_ok : 1;45#if (__ARM_CMSE_SECURE_MODE)46unsigned sau_region_valid : 1;47#else48unsigned : 1;49#endif50unsigned mpu_region_valid : 1;51#if (__ARM_CMSE_SECURE_MODE)52unsigned sau_region : 8;53#else54unsigned : 8;55#endif56unsigned mpu_region : 8;5758#else /* __ARM_LITTLE_ENDIAN */59unsigned mpu_region : 8;60#if (__ARM_CMSE_SECURE_MODE)61unsigned sau_region : 8;62#else63unsigned : 8;64#endif65unsigned mpu_region_valid : 1;66#if (__ARM_CMSE_SECURE_MODE)67unsigned sau_region_valid : 1;68#else69unsigned : 1;70#endif71unsigned read_ok : 1;72unsigned readwrite_ok : 1;73#if (__ARM_CMSE_SECURE_MODE)74unsigned nonsecure_read_ok : 1;75unsigned nonsecure_readwrite_ok : 1;76unsigned secure : 1;77unsigned idau_region_valid : 1;78unsigned idau_region : 8;79#else80unsigned : 12;81#endif82#endif /*__ARM_LITTLE_ENDIAN */83} flags;84unsigned value;85} cmse_address_info_t;8687static cmse_address_info_t __attribute__((__always_inline__, __nodebug__))88cmse_TT(void *__p) {89cmse_address_info_t __u;90__u.value = __builtin_arm_cmse_TT(__p);91return __u;92}93static cmse_address_info_t __attribute__((__always_inline__, __nodebug__))94cmse_TTT(void *__p) {95cmse_address_info_t __u;96__u.value = __builtin_arm_cmse_TTT(__p);97return __u;98}99100#if __ARM_CMSE_SECURE_MODE101static cmse_address_info_t __attribute__((__always_inline__, __nodebug__))102cmse_TTA(void *__p) {103cmse_address_info_t __u;104__u.value = __builtin_arm_cmse_TTA(__p);105return __u;106}107static cmse_address_info_t __attribute__((__always_inline__, __nodebug__))108cmse_TTAT(void *__p) {109cmse_address_info_t __u;110__u.value = __builtin_arm_cmse_TTAT(__p);111return __u;112}113#endif114115#define cmse_TT_fptr(p) cmse_TT(__builtin_bit_cast(void *, (p)))116#define cmse_TTT_fptr(p) cmse_TTT(__builtin_bit_cast(void *, (p)))117118#if __ARM_CMSE_SECURE_MODE119#define cmse_TTA_fptr(p) cmse_TTA(__builtin_bit_cast(void *, (p)))120#define cmse_TTAT_fptr(p) cmse_TTAT(__builtin_bit_cast(void *, (p)))121#endif122123static void *__attribute__((__always_inline__))124cmse_check_address_range(void *__pb, size_t __s, int __flags) {125uintptr_t __begin = (uintptr_t)__pb;126uintptr_t __end = __begin + __s - 1;127128if (__end < __begin)129return NULL; /* wrap around check */130131/* Check whether the range crosses a 32-bytes aligned address */132const int __single_check = (__begin ^ __end) < 0x20u;133134/* execute the right variant of the TT instructions */135void *__pe = (void *)__end;136cmse_address_info_t __permb, __perme;137switch (__flags & (CMSE_MPU_UNPRIV | CMSE_MPU_NONSECURE)) {138case 0:139__permb = cmse_TT(__pb);140__perme = __single_check ? __permb : cmse_TT(__pe);141break;142case CMSE_MPU_UNPRIV:143__permb = cmse_TTT(__pb);144__perme = __single_check ? __permb : cmse_TTT(__pe);145break;146#if __ARM_CMSE_SECURE_MODE147case CMSE_MPU_NONSECURE:148__permb = cmse_TTA(__pb);149__perme = __single_check ? __permb : cmse_TTA(__pe);150break;151case CMSE_MPU_UNPRIV | CMSE_MPU_NONSECURE:152__permb = cmse_TTAT(__pb);153__perme = __single_check ? __permb : cmse_TTAT(__pe);154break;155#endif156/* if CMSE_NONSECURE is specified w/o __ARM_CMSE_SECURE_MODE */157default:158return NULL;159}160161/* check that the range does not cross MPU, SAU, or IDAU region boundaries */162if (__permb.value != __perme.value)163return NULL;164#if !(__ARM_CMSE_SECURE_MODE)165/* CMSE_AU_NONSECURE is only supported when __ARM_FEATURE_CMSE & 0x2 */166if (__flags & CMSE_AU_NONSECURE)167return NULL;168#endif169170/* check the permission on the range */171switch (__flags & ~(CMSE_MPU_UNPRIV | CMSE_MPU_NONSECURE)) {172#if (__ARM_CMSE_SECURE_MODE)173case CMSE_MPU_READ | CMSE_MPU_READWRITE | CMSE_AU_NONSECURE:174case CMSE_MPU_READWRITE | CMSE_AU_NONSECURE:175return __permb.flags.nonsecure_readwrite_ok ? __pb : NULL;176177case CMSE_MPU_READ | CMSE_AU_NONSECURE:178return __permb.flags.nonsecure_read_ok ? __pb : NULL;179180case CMSE_AU_NONSECURE:181return __permb.flags.secure ? NULL : __pb;182#endif183case CMSE_MPU_READ | CMSE_MPU_READWRITE:184case CMSE_MPU_READWRITE:185return __permb.flags.readwrite_ok ? __pb : NULL;186187case CMSE_MPU_READ:188return __permb.flags.read_ok ? __pb : NULL;189190default:191return NULL;192}193}194195#if __ARM_CMSE_SECURE_MODE196static int __attribute__((__always_inline__, __nodebug__))197cmse_nonsecure_caller(void) {198return !((uintptr_t)__builtin_return_address(0) & 1);199}200201#define cmse_nsfptr_create(p) \202__builtin_bit_cast(__typeof__(p), \203(__builtin_bit_cast(uintptr_t, p) & ~(uintptr_t)1))204205#define cmse_is_nsfptr(p) ((__builtin_bit_cast(uintptr_t, p) & 1) == 0)206207#endif /* __ARM_CMSE_SECURE_MODE */208209void __attribute__((__noreturn__)) cmse_abort(void);210#if defined(__cplusplus)211}212#endif213214#endif /* (__ARM_FEATURE_CMSE & 0x1) */215216#endif /* __ARM_CMSE_H */217218219