David Hu | 50711e3 | 2019-06-12 18:32:30 +0800 | [diff] [blame] | 1 | /* |
Summer Qin | dea1f2c | 2021-01-11 14:46:34 +0800 | [diff] [blame] | 2 | * Copyright (c) 2018-2021, Arm Limited. All rights reserved. |
David Hu | 50711e3 | 2019-06-12 18:32:30 +0800 | [diff] [blame] | 3 | * |
| 4 | * SPDX-License-Identifier: BSD-3-Clause |
| 5 | * |
| 6 | */ |
| 7 | #ifndef __TFM_ARCH_H__ |
| 8 | #define __TFM_ARCH_H__ |
| 9 | |
| 10 | /* This header file collects the architecture related operations. */ |
| 11 | |
Ken Liu | 1d96c13 | 2019-12-31 15:51:30 +0800 | [diff] [blame] | 12 | #include <stddef.h> |
David Hu | 50711e3 | 2019-06-12 18:32:30 +0800 | [diff] [blame] | 13 | #include <inttypes.h> |
Kevin Peng | bc5e5aa | 2019-10-16 10:55:17 +0800 | [diff] [blame] | 14 | #include "tfm_hal_device_header.h" |
David Hu | 50711e3 | 2019-06-12 18:32:30 +0800 | [diff] [blame] | 15 | #include "cmsis_compiler.h" |
| 16 | |
Ronald Cron | 312be68 | 2019-09-23 09:27:33 +0200 | [diff] [blame] | 17 | #if defined(__ARM_ARCH_8_1M_MAIN__) || \ |
| 18 | defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__) |
David Hu | 50711e3 | 2019-06-12 18:32:30 +0800 | [diff] [blame] | 19 | #include "tfm_arch_v8m.h" |
David Hu | 40455c9 | 2019-07-02 14:31:34 +0800 | [diff] [blame] | 20 | #elif defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_7M__) || \ |
| 21 | defined(__ARM_ARCH_7EM__) |
| 22 | #include "tfm_arch_v6m_v7m.h" |
David Hu | 50711e3 | 2019-06-12 18:32:30 +0800 | [diff] [blame] | 23 | #else |
| 24 | #error "Unsupported ARM Architecture." |
| 25 | #endif |
| 26 | |
| 27 | #define XPSR_T32 0x01000000 |
| 28 | |
Ken Liu | 5d73c87 | 2021-08-19 19:23:17 +0800 | [diff] [blame] | 29 | /* State context defined by architecture */ |
Ken Liu | 5a2b905 | 2019-08-15 19:03:29 +0800 | [diff] [blame] | 30 | struct tfm_state_context_t { |
David Hu | 50711e3 | 2019-06-12 18:32:30 +0800 | [diff] [blame] | 31 | uint32_t r0; |
| 32 | uint32_t r1; |
| 33 | uint32_t r2; |
| 34 | uint32_t r3; |
| 35 | uint32_t r12; |
Ken Liu | 5a2b905 | 2019-08-15 19:03:29 +0800 | [diff] [blame] | 36 | uint32_t lr; |
David Hu | 50711e3 | 2019-06-12 18:32:30 +0800 | [diff] [blame] | 37 | uint32_t ra; |
| 38 | uint32_t xpsr; |
Ken Liu | 5d73c87 | 2021-08-19 19:23:17 +0800 | [diff] [blame] | 39 | }; |
David Hu | 50711e3 | 2019-06-12 18:32:30 +0800 | [diff] [blame] | 40 | |
Ken Liu | 5d73c87 | 2021-08-19 19:23:17 +0800 | [diff] [blame] | 41 | /* Context addition to state context */ |
| 42 | struct tfm_additional_context_t { |
| 43 | uint32_t callee[8]; /* R4-R11. NOT ORDERED!! */ |
| 44 | }; |
| 45 | |
| 46 | /* Full thread context */ |
| 47 | struct full_context_t { |
| 48 | struct tfm_additional_context_t addi_ctx; |
| 49 | struct tfm_state_context_t stat_ctx; |
| 50 | }; |
| 51 | |
| 52 | /* Context control */ |
| 53 | struct context_ctrl_t { |
| 54 | uint32_t sp; /* Stack pointer (higher address) */ |
| 55 | uint32_t sp_limit; /* Stack limit (lower address) */ |
| 56 | uint32_t reserved; /* Reserved */ |
| 57 | uint32_t exc_ret; /* EXC_RETURN pattern. */ |
| 58 | }; |
| 59 | |
| 60 | /* |
| 61 | * The context on MSP when de-privileged FLIH Function calls SVC to return. |
| 62 | * It is the same when de-privileged FLIH Function is ready to run. |
| 63 | */ |
| 64 | struct context_flih_ret_t { |
| 65 | uint64_t stack_seal; /* Two words stack seal */ |
| 66 | struct tfm_additional_context_t addi_ctx; |
| 67 | uint32_t exc_ret; /* EXC_RETURN value when interrupt exception ocurrs */ |
| 68 | uint32_t psp; /* PSP when interrupt exception ocurrs */ |
| 69 | struct tfm_state_context_t state_ctx; /* ctx on SVC_PREPARE_DEPRIV_FLIH */ |
| 70 | }; |
David Hu | 50711e3 | 2019-06-12 18:32:30 +0800 | [diff] [blame] | 71 | |
David Hu | 50711e3 | 2019-06-12 18:32:30 +0800 | [diff] [blame] | 72 | /** |
| 73 | * \brief Get Link Register |
| 74 | * \details Returns the value of the Link Register (LR) |
| 75 | * \return LR value |
| 76 | */ |
TTornblom | dd233d1 | 2020-11-05 11:44:28 +0100 | [diff] [blame] | 77 | #if !defined ( __ICCARM__ ) |
David Hu | 50711e3 | 2019-06-12 18:32:30 +0800 | [diff] [blame] | 78 | __attribute__ ((always_inline)) __STATIC_INLINE uint32_t __get_LR(void) |
| 79 | { |
| 80 | register uint32_t result; |
| 81 | |
| 82 | __ASM volatile ("MOV %0, LR\n" : "=r" (result)); |
| 83 | return result; |
| 84 | } |
TTornblom | dd233d1 | 2020-11-05 11:44:28 +0100 | [diff] [blame] | 85 | #endif |
David Hu | 50711e3 | 2019-06-12 18:32:30 +0800 | [diff] [blame] | 86 | |
Ken Liu | 92ede9f | 2021-10-20 09:35:00 +0800 | [diff] [blame] | 87 | __STATIC_INLINE uint32_t __save_disable_irq(void) |
| 88 | { |
| 89 | uint32_t result; |
| 90 | |
| 91 | __ASM volatile ("mrs %0, primask \n cpsid i" : "=r" (result) :: "memory"); |
| 92 | return result; |
| 93 | } |
| 94 | |
| 95 | __STATIC_INLINE void __restore_irq(uint32_t status) |
| 96 | { |
| 97 | __ASM volatile ("msr primask, %0" :: "r" (status) : "memory"); |
| 98 | } |
| 99 | |
David Hu | 50711e3 | 2019-06-12 18:32:30 +0800 | [diff] [blame] | 100 | __attribute__ ((always_inline)) |
| 101 | __STATIC_INLINE uint32_t __get_active_exc_num(void) |
| 102 | { |
| 103 | IPSR_Type IPSR; |
| 104 | |
| 105 | /* if non-zero, exception is active. NOT banked S/NS */ |
| 106 | IPSR.w = __get_IPSR(); |
| 107 | return IPSR.b.ISR; |
| 108 | } |
| 109 | |
| 110 | __attribute__ ((always_inline)) |
| 111 | __STATIC_INLINE void __set_CONTROL_SPSEL(uint32_t SPSEL) |
| 112 | { |
| 113 | CONTROL_Type ctrl; |
| 114 | |
| 115 | ctrl.w = __get_CONTROL(); |
| 116 | ctrl.b.SPSEL = SPSEL; |
| 117 | __set_CONTROL(ctrl.w); |
| 118 | __ISB(); |
| 119 | } |
| 120 | |
Ken Liu | 5d73c87 | 2021-08-19 19:23:17 +0800 | [diff] [blame] | 121 | /* Set secure exceptions priority. */ |
Ken Liu | 50e2109 | 2020-10-14 16:42:15 +0800 | [diff] [blame] | 122 | void tfm_arch_set_secure_exception_priorities(void); |
Jamie Fox | 3ede971 | 2020-09-28 23:14:54 +0100 | [diff] [blame] | 123 | |
Ken Liu | 5d73c87 | 2021-08-19 19:23:17 +0800 | [diff] [blame] | 124 | /* Configure various extensions. */ |
Summer Qin | dea1f2c | 2021-01-11 14:46:34 +0800 | [diff] [blame] | 125 | void tfm_arch_config_extensions(void); |
Jamie Fox | 4558767 | 2020-08-17 18:31:14 +0100 | [diff] [blame] | 126 | |
Ken Liu | 5d73c87 | 2021-08-19 19:23:17 +0800 | [diff] [blame] | 127 | /* Clear float point status. */ |
Ken Liu | ce2692d | 2020-02-11 12:39:36 +0800 | [diff] [blame] | 128 | void tfm_arch_clear_fp_status(void); |
| 129 | |
Kevin Peng | 300c68d | 2021-08-12 17:40:17 +0800 | [diff] [blame] | 130 | /* |
| 131 | * This function is called after SPM has initialized. |
| 132 | * It frees the stack used by SPM initialization and do Exception Return. |
| 133 | * It does not return. |
| 134 | */ |
Ken Liu | dedbf4b | 2021-11-02 09:07:25 +0800 | [diff] [blame^] | 135 | void tfm_arch_free_msp_and_exc_ret(uint32_t msp_base, uint32_t exc_return); |
Kevin Peng | 300c68d | 2021-08-12 17:40:17 +0800 | [diff] [blame] | 136 | |
Ken Liu | 5d73c87 | 2021-08-19 19:23:17 +0800 | [diff] [blame] | 137 | /* |
| 138 | * This function sets return value on APIs that cause scheduling, for example |
| 139 | * psa_wait(), by manipulating the control context - this is usaully setting the |
| 140 | * R0 register of the thread context. |
| 141 | */ |
| 142 | void tfm_arch_set_context_ret_code(void *p_ctx_ctrl, uintptr_t ret_code); |
| 143 | |
| 144 | /* Init a thread context on thread stack and update the control context. */ |
| 145 | void tfm_arch_init_context(void *p_ctx_ctrl, |
| 146 | uintptr_t pfn, void *param, uintptr_t pfnlr, |
| 147 | uintptr_t sp_limit, uintptr_t sp); |
| 148 | |
| 149 | /* |
| 150 | * Refresh the HW (sp, splimit) according to the given control context and |
| 151 | * returns the EXC_RETURN payload (caller might need it for following codes). |
| 152 | * |
| 153 | * The p_ctx_ctrl must have been initialized by tfm_arch_init_context |
| 154 | */ |
| 155 | uint32_t tfm_arch_refresh_hardware_context(void *p_ctx_ctrl); |
| 156 | |
Ken Liu | e07c3b7 | 2021-10-14 16:19:13 +0800 | [diff] [blame] | 157 | /* |
| 158 | * Triggers scheduler. A return type is assigned in case |
| 159 | * SPM returns values by the context. |
| 160 | */ |
| 161 | uint32_t tfm_arch_trigger_pendsv(void); |
| 162 | |
| 163 | |
| 164 | /* |
| 165 | * Switch to a new stack area, lock scheduler and call function. |
| 166 | * If 'stk_base' is ZERO, stack won't be switched and re-use caller stack. |
| 167 | */ |
| 168 | uint32_t arch_non_preempt_call(uintptr_t fn_addr, uintptr_t frame_addr, |
| 169 | uint32_t stk_base, uint32_t stk_limit); |
| 170 | |
David Hu | 50711e3 | 2019-06-12 18:32:30 +0800 | [diff] [blame] | 171 | #endif |