summaryrefslogtreecommitdiff
path: root/fw/midi-dials/Drivers/CMSIS/Core/Template/ARMv8-M/tz_context.c
blob: 298bbf73ec55df14b904324ad596e7ab317ad86f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/******************************************************************************
 * @file     tz_context.c
 * @brief    Context Management for Armv8-M TrustZone - Sample implementation
 * @version  V1.1.1
 * @date     10. January 2018
 ******************************************************************************/
/*
 * Copyright (c) 2016-2018 Arm Limited. All rights reserved.
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the License); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "RTE_Components.h"
#include CMSIS_device_header
#include "tz_context.h"

/// Number of process slots (threads may call secure library code)
#ifndef TZ_PROCESS_STACK_SLOTS
#define TZ_PROCESS_STACK_SLOTS     8U
#endif

/// Stack size of the secure library code
#ifndef TZ_PROCESS_STACK_SIZE
#define TZ_PROCESS_STACK_SIZE      256U
#endif

typedef struct {
  uint32_t sp_top;      // stack space top
  uint32_t sp_limit;    // stack space limit
  uint32_t sp;          // current stack pointer
} stack_info_t;

static stack_info_t ProcessStackInfo  [TZ_PROCESS_STACK_SLOTS];
static uint64_t     ProcessStackMemory[TZ_PROCESS_STACK_SLOTS][TZ_PROCESS_STACK_SIZE/8U];
static uint32_t     ProcessStackFreeSlot = 0xFFFFFFFFU;


/// Initialize secure context memory system
/// \return execution status (1: success, 0: error)
__attribute__((cmse_nonsecure_entry))
uint32_t TZ_InitContextSystem_S (void) {
  uint32_t n;

  if (__get_IPSR() == 0U) {
    return 0U;  // Thread Mode
  }

  for (n = 0U; n < TZ_PROCESS_STACK_SLOTS; n++) {
    ProcessStackInfo[n].sp = 0U;
    ProcessStackInfo[n].sp_limit = (uint32_t)&ProcessStackMemory[n];
    ProcessStackInfo[n].sp_top   = (uint32_t)&ProcessStackMemory[n] + TZ_PROCESS_STACK_SIZE;
    *((uint32_t *)ProcessStackMemory[n]) = n + 1U;
  }
  *((uint32_t *)ProcessStackMemory[--n]) = 0xFFFFFFFFU;

  ProcessStackFreeSlot = 0U;

  // Default process stack pointer and stack limit
  __set_PSPLIM((uint32_t)ProcessStackMemory);
  __set_PSP   ((uint32_t)ProcessStackMemory);

  // Privileged Thread Mode using PSP
  __set_CONTROL(0x02U);

  return 1U;    // Success
}


/// Allocate context memory for calling secure software modules in TrustZone
/// \param[in]  module   identifies software modules called from non-secure mode
/// \return value != 0 id TrustZone memory slot identifier
/// \return value 0    no memory available or internal error
__attribute__((cmse_nonsecure_entry))
TZ_MemoryId_t TZ_AllocModuleContext_S (TZ_ModuleId_t module) {
  uint32_t slot;

  (void)module; // Ignore (fixed Stack size)

  if (__get_IPSR() == 0U) {
    return 0U;  // Thread Mode
  }

  if (ProcessStackFreeSlot == 0xFFFFFFFFU) {
    return 0U;  // No slot available
  }

  slot = ProcessStackFreeSlot;
  ProcessStackFreeSlot = *((uint32_t *)ProcessStackMemory[slot]);

  ProcessStackInfo[slot].sp = ProcessStackInfo[slot].sp_top;

  return (slot + 1U);
}


/// Free context memory that was previously allocated with \ref TZ_AllocModuleContext_S
/// \param[in]  id  TrustZone memory slot identifier
/// \return execution status (1: success, 0: error)
__attribute__((cmse_nonsecure_entry))
uint32_t TZ_FreeModuleContext_S (TZ_MemoryId_t id) {
  uint32_t slot;

  if (__get_IPSR() == 0U) {
    return 0U;  // Thread Mode
  }

  if ((id == 0U) || (id > TZ_PROCESS_STACK_SLOTS)) {
    return 0U;  // Invalid ID
  }

  slot = id - 1U;

  if (ProcessStackInfo[slot].sp == 0U) {
    return 0U;  // Inactive slot
  }
  ProcessStackInfo[slot].sp = 0U;

  *((uint32_t *)ProcessStackMemory[slot]) = ProcessStackFreeSlot;
  ProcessStackFreeSlot = slot;

  return 1U;    // Success
}


/// Load secure context (called on RTOS thread context switch)
/// \param[in]  id  TrustZone memory slot identifier
/// \return execution status (1: success, 0: error)
__attribute__((cmse_nonsecure_entry))
uint32_t TZ_LoadContext_S (TZ_MemoryId_t id) {
  uint32_t slot;

  if ((__get_IPSR() == 0U) || ((__get_CONTROL() & 2U) == 0U)) {
    return 0U;  // Thread Mode or using Main Stack for threads
  }

  if ((id == 0U) || (id > TZ_PROCESS_STACK_SLOTS)) {
    return 0U;  // Invalid ID
  }

  slot = id - 1U;

  if (ProcessStackInfo[slot].sp == 0U) {
    return 0U;  // Inactive slot
  }

  // Setup process stack pointer and stack limit
  __set_PSPLIM(ProcessStackInfo[slot].sp_limit);
  __set_PSP   (ProcessStackInfo[slot].sp);

  return 1U;    // Success
}


/// Store secure context (called on RTOS thread context switch)
/// \param[in]  id  TrustZone memory slot identifier
/// \return execution status (1: success, 0: error)
__attribute__((cmse_nonsecure_entry))
uint32_t TZ_StoreContext_S (TZ_MemoryId_t id) {
  uint32_t slot;
  uint32_t sp;

  if ((__get_IPSR() == 0U) || ((__get_CONTROL() & 2U) == 0U)) {
    return 0U;  // Thread Mode or using Main Stack for threads
  }

  if ((id == 0U) || (id > TZ_PROCESS_STACK_SLOTS)) {
    return 0U;  // Invalid ID
  }

  slot = id - 1U;

  if (ProcessStackInfo[slot].sp == 0U) {
    return 0U;  // Inactive slot
  }

  sp = __get_PSP();
  if ((sp < ProcessStackInfo[slot].sp_limit) ||
      (sp > ProcessStackInfo[slot].sp_top)) {
    return 0U;  // SP out of range
  }
  ProcessStackInfo[slot].sp = sp;

  // Default process stack pointer and stack limit
  __set_PSPLIM((uint32_t)ProcessStackMemory);
  __set_PSP   ((uint32_t)ProcessStackMemory);

  return 1U;    // Success
}