diff --git a/arch/arm/core/CMakeLists.txt b/arch/arm/core/CMakeLists.txt index 7d20b1a0991..4312c3b4e2a 100644 --- a/arch/arm/core/CMakeLists.txt +++ b/arch/arm/core/CMakeLists.txt @@ -23,3 +23,4 @@ zephyr_library_sources_ifdef(CONFIG_USERSPACE userspace.S) add_subdirectory_ifdef(CONFIG_CPU_CORTEX_M cortex_m) add_subdirectory_ifdef(CONFIG_CPU_HAS_MPU cortex_m/mpu) +add_subdirectory_ifdef(CONFIG_CPU_CORTEX_M_HAS_CMSE cortex_m/cmse) diff --git a/arch/arm/core/cortex_m/Kconfig b/arch/arm/core/cortex_m/Kconfig index 2011c480b08..0107ef67490 100644 --- a/arch/arm/core/cortex_m/Kconfig +++ b/arch/arm/core/cortex_m/Kconfig @@ -166,6 +166,12 @@ config CPU_CORTEX_M0_HAS_VECTOR_TABLE_REMAP This option signifies the Cortex-M0 has some mechanisms that can map the vector table to SRAM +config CPU_CORTEX_M_HAS_CMSE + bool + default n + help + This option signifies the Cortex-M CPU has the CMSE intrinsics. + config ARMV6_M_ARMV8_M_BASELINE bool # Omit prompt to signify "hidden" option diff --git a/arch/arm/core/cortex_m/cmse/CMakeLists.txt b/arch/arm/core/cortex_m/cmse/CMakeLists.txt new file mode 100644 index 00000000000..a8cb69dc28f --- /dev/null +++ b/arch/arm/core/cortex_m/cmse/CMakeLists.txt @@ -0,0 +1 @@ +zephyr_sources(arm_core_cmse.c) diff --git a/arch/arm/core/cortex_m/cmse/arm_core_cmse.c b/arch/arm/core/cortex_m/cmse/arm_core_cmse.c new file mode 100644 index 00000000000..9b7b0d1807f --- /dev/null +++ b/arch/arm/core/cortex_m/cmse/arm_core_cmse.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2018 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +int arm_cmse_mpu_region_get(u32_t addr, u8_t *p_region) +{ + cmse_address_info_t addr_info = cmse_TT((void *)addr); + + if (addr_info.flags.mpu_region_valid) { + *p_region = addr_info.flags.mpu_region; + } + + return addr_info.flags.mpu_region_valid; +} + +static int arm_cmse_addr_read_write_ok(u32_t addr, int force_npriv, int rw) +{ + cmse_address_info_t addr_info; + if (force_npriv) { + addr_info = cmse_TTT((void *)addr); + } else { + addr_info = cmse_TT((void *)addr); + } + + return rw ? addr_info.flags.readwrite_ok : addr_info.flags.read_ok; +} + +int arm_cmse_addr_read_ok(u32_t addr, int force_npriv) +{ + return arm_cmse_addr_read_write_ok(addr, force_npriv, 0); +} + +int arm_cmse_addr_readwrite_ok(u32_t addr, int force_npriv) +{ + return arm_cmse_addr_read_write_ok(addr, force_npriv, 1); +} diff --git a/arch/arm/include/cortex_m/cmse.h b/arch/arm/include/cortex_m/cmse.h new file mode 100644 index 00000000000..f61f9dc556f --- /dev/null +++ b/arch/arm/include/cortex_m/cmse.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2018 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief ARM Core CMSE API + * + * CMSE API for Cortex-M23/M33 CPUs. + */ + +#ifndef _ARM_CORTEXM_CMSE__H_ +#define _ARM_CORTEXM_CMSE__H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _ASMLANGUAGE + +/* nothing */ + +#else + +#include +#include + +/* + * Address information retrieval based on the TT instructions. + * + * The TT instructions are used to check the access permissions that different + * security states and privilege levels have on memory at a specified address + */ + +/** + * @brief Get the MPU region number of an address + * + * Get the MPU region that the address maps to. Return non-zero + * to indicate that a valid MPU region was retrieved, and store the + * MPU region information in the supplied location. + * + * Note: + * Obtained region is valid only if: + * - the function is called from privileged mode + * - the MPU is implemented and enabled + * - the given address matches a single, enabled MPU region + * + * @param addr The address for which the MPU region is requested + * @param p_region Output pointer to the location to store the MPU region + * + * @return non-zero if @ref region contains a valid MPU region, otherwise 0. + */ +int arm_cmse_mpu_region_get(u32_t addr, u8_t *p_region); + +/** + * @brief Read accessibility of an address + * + * Evaluates whether a specified memory location can be read according to the + * permissions of the current state MPU and the specified operation mode. + * + * This function shall always return zero: + * - if executed from an unprivileged mode, + * - if the address matches multiple MPU regions. + * + * @param addr The address for which the readability is requested + * @param force_npriv Instruct to return the readability of the address + * for unprivileged access, regardless of whether the current + * mode is privileged or unprivileged. + * + * @return 1 if address is readable, 0 otherwise. + */ +int arm_cmse_addr_read_ok(u32_t addr, int force_npriv); + +/** + * @brief Read and Write accessibility of an address + * + * Evaluates whether a specified memory location can be read/written according + * to the permissions of the current state MPU and the specified operation + * mode. + * + * This function shall always return zero: + * - if executed from an unprivileged mode, + * - if the address matches multiple MPU regions. + * + * @param addr The address for which the RW ability is requested + * @param force_npriv Instruct to return the RW ability of the address + * for unprivileged access, regardless of whether the current + * mode is privileged or unprivileged. + * + * @return 1 if address is Read and Writable, 0 otherwise. + */ +int arm_cmse_addr_readwrite_ok(u32_t addr, int force_npriv); + +#endif /* _ASMLANGUAGE */ + +#ifdef __cplusplus +} +#endif + +#endif /* _ARM_CORTEXM_CMSE__H_ */