summaryrefslogtreecommitdiffstats
path: root/cpukit/score/cpu/arm/include/rtems/score/aarch32-pmsa.h
blob: 6d36de4923756d302942efb92f013ae8a5824a66 (plain) (blame)
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
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
/* SPDX-License-Identifier: BSD-2-Clause */

/**
 * @file
 *
 * @ingroup RTEMSScoreCPUARMPMSAv8
 *
 * @brief This header file provides the API to manage an Arm PMSAv8-32 based
 *   Memory Protection Unit (MPU).
 */

/*
 * Copyright (C) 2020 embedded brains GmbH (http://www.embedded-brains.de)
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _RTEMS_SCORE_AARCH32_PMSA_H
#define _RTEMS_SCORE_AARCH32_PMSA_H

#include <stddef.h>
#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @defgroup RTEMSScoreCPUARMPMSAv8 PMSAv8-32 Support
 *
 * @ingroup RTEMSScoreCPUARM
 *
 * @brief This group provides support functions to manage an Arm PMSAv8-32
 *   (Protected Memory System Architecture) based Memory Protection Unit (MPU).
 *
 * @{
 */

#define AARCH32_PMSA_MIN_REGION_ALIGN 64

#define AARCH32_PMSA_ATTR_EN 0x1U

#define AARCH32_PMSA_ATTR_IDX_SHIFT 1
#define AARCH32_PMSA_ATTR_IDX_MASK 0xeU
#define AARCH32_PMSA_ATTR_IDX( _idx ) \
  ( ( _idx ) << AARCH32_PMSA_ATTR_IDX_SHIFT )

#define AARCH32_PMSA_ATTR_XN 0x40U

#define AARCH32_PMSA_ATTR_AP_SHIFT 7
#define AARCH32_PMSA_ATTR_AP_MASK 0x18U
#define AARCH32_PMSA_ATTR_AP( _ap ) \
  ( ( _ap ) << AARCH32_PMSA_ATTR_AP_SHIFT )
#define AARCH32_PMSA_ATTR_AP_EL1_RW_EL0_NO 0x0U
#define AARCH32_PMSA_ATTR_AP_EL1_RW_EL0_RW 0x1U
#define AARCH32_PMSA_ATTR_AP_EL1_RO_EL0_NO 0x2U
#define AARCH32_PMSA_ATTR_AP_EL1_RO_EL0_RO 0x3U

#define AARCH32_PMSA_ATTR_SH_SHIFT 9
#define AARCH32_PMSA_ATTR_SH_MASK 0x600U
#define AARCH32_PMSA_ATTR_SH( _sh ) \
  ( ( _sh ) << AARCH32_PMSA_ATTR_SH_SHIFT )
#define AARCH32_PMSA_ATTR_SH_NO 0x0U
#define AARCH32_PMSA_ATTR_SH_RES 0x1U
#define AARCH32_PMSA_ATTR_SH_OUTER 0x2U
#define AARCH32_PMSA_ATTR_SH_INNER 0x3U

#define AARCH32_PMSA_MEM_DEVICE_NG_NR_NE 0x00U
#define AARCH32_PMSA_MEM_DEVICE_NG_NR_E  0x04U
#define AARCH32_PMSA_MEM_DEVICE_NG_R_E   0x08U
#define AARCH32_PMSA_MEM_DEVICE_G_R_E    0x0cU

#define AARCH32_PMSA_MEM_OUTER_WTT  0x00U
#define AARCH32_PMSA_MEM_OUTER_NC   0x40U
#define AARCH32_PMSA_MEM_OUTER_WBT  0x40U
#define AARCH32_PMSA_MEM_OUTER_WTNT 0x80U
#define AARCH32_PMSA_MEM_OUTER_WBNT 0xc0U

#define AARCH32_PMSA_MEM_OUTER_RA 0x20U
#define AARCH32_PMSA_MEM_OUTER_WA 0x10U

#define AARCH32_PMSA_MEM_INNER_WTT  0x00U
#define AARCH32_PMSA_MEM_INNER_NC   0x04U
#define AARCH32_PMSA_MEM_INNER_WBT  0x04U
#define AARCH32_PMSA_MEM_INNER_WTNT 0x08U
#define AARCH32_PMSA_MEM_INNER_WBNT 0x0cU

#define AARCH32_PMSA_MEM_INNER_RA 0x02U
#define AARCH32_PMSA_MEM_INNER_WA 0x01U

#define AARCH32_PMSA_MEM_ATTR( _ma0, _ma1, _ma2, _ma3 ) \
  ( ( _ma0 ) | ( ( _ma1 ) << 8 ) | ( ( _ma2 ) << 16 ) | ( ( _ma3 ) << 24 ) )

#define AARCH32_PMSA_MEM_ATTR_DEFAULT_CACHED \
  ( AARCH32_PMSA_MEM_OUTER_WBNT | \
    AARCH32_PMSA_MEM_OUTER_RA | \
    AARCH32_PMSA_MEM_OUTER_WA | \
    AARCH32_PMSA_MEM_INNER_WBNT | \
    AARCH32_PMSA_MEM_INNER_RA | \
    AARCH32_PMSA_MEM_INNER_WA )

#define AARCH32_PMSA_MEM_ATTR_DEFAULT_UNCACHED \
  ( AARCH32_PMSA_MEM_OUTER_NC | \
    AARCH32_PMSA_MEM_INNER_NC )

#define AARCH32_PMSA_MEM_ATTR_DEFAULT_DEVICE \
  AARCH32_PMSA_MEM_DEVICE_NG_NR_NE

#define AARCH32_PMSA_CODE_CACHED \
  ( AARCH32_PMSA_ATTR_EN | \
    AARCH32_PMSA_ATTR_AP( AARCH32_PMSA_ATTR_AP_EL1_RO_EL0_NO ) | \
    AARCH32_PMSA_ATTR_SH( AARCH32_PMSA_ATTR_SH_NO ) | \
    AARCH32_PMSA_ATTR_IDX( 0U ) )

#define AARCH32_PMSA_CODE_UNCACHED \
  ( AARCH32_PMSA_ATTR_EN | \
    AARCH32_PMSA_ATTR_AP( AARCH32_PMSA_ATTR_AP_EL1_RO_EL0_NO ) | \
    AARCH32_PMSA_ATTR_SH( AARCH32_PMSA_ATTR_SH_NO ) | \
    AARCH32_PMSA_ATTR_IDX( 1U ) )

#define AARCH32_PMSA_DATA_READ_ONLY_CACHED \
  ( AARCH32_PMSA_ATTR_EN | \
    AARCH32_PMSA_ATTR_XN | \
    AARCH32_PMSA_ATTR_AP( AARCH32_PMSA_ATTR_AP_EL1_RO_EL0_NO ) |  \
    AARCH32_PMSA_ATTR_SH( AARCH32_PMSA_ATTR_SH_NO ) | \
    AARCH32_PMSA_ATTR_IDX( 0U ) )

#define AARCH32_PMSA_DATA_READ_ONLY_UNCACHED \
  ( AARCH32_PMSA_ATTR_EN | \
    AARCH32_PMSA_ATTR_XN | \
    AARCH32_PMSA_ATTR_AP( AARCH32_PMSA_ATTR_AP_EL1_RO_EL0_NO ) | \
    AARCH32_PMSA_ATTR_SH( AARCH32_PMSA_ATTR_SH_NO ) | \
    AARCH32_PMSA_ATTR_IDX( 1U ) )

#define AARCH32_PMSA_DATA_READ_WRITE_CACHED \
  ( AARCH32_PMSA_ATTR_EN | \
    AARCH32_PMSA_ATTR_XN | \
    AARCH32_PMSA_ATTR_AP( AARCH32_PMSA_ATTR_AP_EL1_RW_EL0_NO ) | \
    AARCH32_PMSA_ATTR_SH( AARCH32_PMSA_ATTR_SH_NO ) | \
    AARCH32_PMSA_ATTR_IDX( 0U ) )

#define AARCH32_PMSA_DATA_READ_WRITE_UNCACHED \
  ( AARCH32_PMSA_ATTR_EN | \
    AARCH32_PMSA_ATTR_XN | \
    AARCH32_PMSA_ATTR_AP( AARCH32_PMSA_ATTR_AP_EL1_RW_EL0_NO ) | \
    AARCH32_PMSA_ATTR_SH( AARCH32_PMSA_ATTR_SH_NO ) | \
    AARCH32_PMSA_ATTR_IDX( 1U ) )

#define AARCH32_PMSA_DEVICE \
  ( AARCH32_PMSA_ATTR_EN | \
    AARCH32_PMSA_ATTR_XN | \
    AARCH32_PMSA_ATTR_AP( AARCH32_PMSA_ATTR_AP_EL1_RW_EL0_NO ) | \
    AARCH32_PMSA_ATTR_SH( AARCH32_PMSA_ATTR_SH_NO ) | \
    AARCH32_PMSA_ATTR_IDX( 2U ) )

/**
 * @brief The default section definitions shall be used by the BSP to define
 *   ::_AArch32_PMSA_Sections.
 *
 * In addition to the default section definitions, the BSP should provide
 * section definitions for the memory-mapped devices and other memory areas.
 */
#define AARCH32_PMSA_DEFAULT_SECTIONS \
  { \
    .begin = (uint32_t) bsp_section_fast_text_begin, \
    .end = (uint32_t) bsp_section_fast_text_end, \
    .attributes = AARCH32_PMSA_CODE_CACHED \
  }, { \
    .begin = (uint32_t) bsp_section_fast_data_begin, \
    .end = (uint32_t) bsp_section_fast_data_end, \
    .attributes = AARCH32_PMSA_DATA_READ_WRITE_CACHED \
  }, { \
    .begin = (uint32_t) bsp_section_start_begin, \
    .end = (uint32_t) bsp_section_start_end, \
    .attributes = AARCH32_PMSA_CODE_CACHED \
  }, { \
    .begin = (uint32_t) bsp_section_vector_begin, \
    .end = (uint32_t) bsp_section_vector_end, \
    .attributes = AARCH32_PMSA_CODE_CACHED \
  }, { \
    .begin = (uint32_t) bsp_section_text_begin, \
    .end = (uint32_t) bsp_section_text_end, \
    .attributes = AARCH32_PMSA_CODE_CACHED \
  }, { \
    .begin = (uint32_t) bsp_section_rodata_begin, \
    .end = (uint32_t) bsp_section_rodata_end, \
    .attributes = AARCH32_PMSA_DATA_READ_ONLY_CACHED \
  }, { \
    .begin = (uint32_t) bsp_section_data_begin, \
    .end = (uint32_t) bsp_section_data_end, \
    .attributes = AARCH32_PMSA_DATA_READ_WRITE_CACHED \
  }, { \
    .begin = (uint32_t) bsp_section_bss_begin, \
    .end = (uint32_t) bsp_section_bss_end, \
    .attributes = AARCH32_PMSA_DATA_READ_WRITE_CACHED \
  }, { \
    .begin = (uint32_t) bsp_section_rtemsstack_begin, \
    .end = (uint32_t) bsp_section_rtemsstack_end, \
    .attributes = AARCH32_PMSA_DATA_READ_WRITE_CACHED \
  }, { \
    .begin = (uint32_t) bsp_section_work_begin, \
    .end = (uint32_t) bsp_section_work_end, \
    .attributes = AARCH32_PMSA_DATA_READ_WRITE_CACHED \
  }, { \
    .begin = (uint32_t) bsp_section_stack_begin, \
    .end = (uint32_t) bsp_section_stack_end, \
    .attributes = AARCH32_PMSA_DATA_READ_WRITE_CACHED \
  }, { \
    .begin = (uint32_t) bsp_section_nocache_begin, \
    .end = (uint32_t) bsp_section_nocache_end, \
    .attributes = AARCH32_PMSA_DATA_READ_WRITE_UNCACHED \
  }, { \
    .begin = (uint32_t) bsp_section_nocachenoload_begin, \
    .end = (uint32_t) bsp_section_nocachenoload_end, \
    .attributes = AARCH32_PMSA_DATA_READ_WRITE_UNCACHED \
  }

/**
 * @brief The section definition is used to initialize the Memory Protection
 *   Unit (MPU).
 *
 * A section is empty if the begin address is equal to the end address.
 */
typedef struct {
  /**
   * @brief This member defines the begin address of the section.
   */
  uint32_t begin;

  /**
   * @brief This member defines the end address of the section.
   */
  uint32_t end;

  /**
   * @brief This member defines the attributes of the section.
   */
  uint32_t attributes;
} AArch32_PMSA_Section;

/**
 * @brief Initializes the Memory Protection Unit (MPU).
 *
 * The section definitions are used to define the regions of the MPU.  Sections
 * are merged if possible to reduce the count of used regions.  If too many
 * regions are used, then the MPU is not enabled.  Overlapping section
 * definitions result in undefined system behaviour.
 *
 * @param memory_attributes_0 are the memory attributes for MAIR0.
 *
 * @param memory_attributes_1 are the memory attributes for MAIR1.
 *
 * @param sections is the array with section definitions.
 *
 * @param section_count is the count of section definitions.
 */
void _AArch32_PMSA_Initialize(
  uint32_t                    memory_attributes_0,
  uint32_t                    memory_attributes_1,
  const AArch32_PMSA_Section *sections,
  size_t                      section_count
);

/**
 * @brief This array provides section definitions to initialize the memory
 *   protection unit (MPU).
 *
 * The BSP shall provide the section definitions with the help of
 * ::AARCH32_PMSA_DEFAULT_SECTIONS.  The section count is provided by
 * ::_AArch32_PMSA_Section_count.
 */
extern const AArch32_PMSA_Section _AArch32_PMSA_Sections[];

/**
 * @brief This constant provides the count of elements in
 * ::_AArch32_PMSA_Sections.
 */
extern const size_t _AArch32_PMSA_Section_count;

/**
 * @brief Initializes the Memory Protection Unit (MPU) using the section
 *   definitions with default memory attributes.
 *
 * Calls _AArch32_PMSA_Initialize() using ::_AArch32_PMSA_Sections and
 * ::_AArch32_PMSA_Section_count and the default memory attributes.
 */
void _AArch32_PMSA_Initialize_default( void );

/** @} */

#ifdef __cplusplus
}
#endif

#endif /* _RTEMS_SCORE_AARCH32_PMSA_H */