File indexing completed on 2025-05-11 08:24:23
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 #ifdef HAVE_CONFIG_H
0038 #include "config.h"
0039 #endif
0040
0041 #include <rtems/score/aarch32-pmsa.h>
0042
0043 #if __ARM_ARCH >= 8 && __ARM_ARCH_PROFILE == 'R'
0044
0045 #include <rtems/score/aarch32-system-registers.h>
0046 #include <rtems/score/cpu.h>
0047
0048 #define AARCH32_PMSA_REGION_MAX \
0049 ( ( AARCH32_MPUIR_REGION_MASK >> AARCH32_MPUIR_REGION_SHIFT ) + 1 )
0050
0051 static void _AArch32_PMSA_Configure(
0052 const AArch32_PMSA_Region *regions,
0053 size_t region_used,
0054 size_t region_max
0055 )
0056 {
0057 size_t ri;
0058 uint32_t sctlr;
0059
0060 for ( ri = 0 ; ri < region_used; ++ri ) {
0061 uint32_t prbar;
0062 uint32_t prlar;
0063 uint32_t attr;
0064
0065 prbar = regions[ ri ].base;
0066 prlar = regions[ ri ].limit;
0067 attr = regions[ ri ].attributes;
0068
0069 prbar |= ( attr >> 6 ) & 0x3fU;
0070 prlar |= attr & 0x3fU;
0071
0072 _AArch32_Write_prselr( ri );
0073 _ARM_Instruction_synchronization_barrier();
0074 _AArch32_Write_prbar( prbar );
0075 _AArch32_Write_prlar( prlar );
0076 }
0077
0078 for ( ri = region_used ; ri < region_max; ++ri ) {
0079 _AArch32_Write_prselr( ri );
0080 _ARM_Instruction_synchronization_barrier();
0081 _AArch32_Write_prbar( 0 );
0082 _AArch32_Write_prlar( 0 );
0083 }
0084
0085 _ARM_Data_synchronization_barrier();
0086 sctlr = _AArch32_Read_sctlr();
0087 sctlr |= AARCH32_SCTLR_M | AARCH32_SCTLR_I | AARCH32_SCTLR_C;
0088 sctlr &= ~( AARCH32_SCTLR_A | AARCH32_SCTLR_BR );
0089 _AArch32_Write_sctlr( sctlr );
0090 _ARM_Instruction_synchronization_barrier();
0091 }
0092
0093 size_t _AArch32_PMSA_Map_sections_to_regions(
0094 const AArch32_PMSA_Section *sections,
0095 size_t section_count,
0096 AArch32_PMSA_Region *regions,
0097 size_t region_max
0098 )
0099 {
0100 size_t ri;
0101 size_t si;
0102 size_t region_used;
0103
0104 region_used = 0;
0105
0106 for ( si = 0; si < section_count; ++si ) {
0107 uint32_t base;
0108 uint32_t end;
0109 uint32_t attr;
0110 uint32_t limit;
0111
0112 base = sections[ si ].begin;
0113 end = sections[ si ].end;
0114 attr = sections[ si ].attributes;
0115
0116 if ( base == end ) {
0117 continue;
0118 }
0119
0120 base = RTEMS_ALIGN_DOWN( base, AARCH32_PMSA_MIN_REGION_ALIGN );
0121 end = RTEMS_ALIGN_UP( end, AARCH32_PMSA_MIN_REGION_ALIGN );
0122 limit = end - AARCH32_PMSA_MIN_REGION_ALIGN;
0123
0124 for ( ri = 0; ri < region_used; ++ri ) {
0125 uint32_t region_base;
0126 uint32_t region_limit;
0127 uint32_t region_attr;
0128
0129 region_base = regions[ ri ].base;
0130 region_limit = regions[ ri ].limit;
0131 region_attr = regions[ ri ].attributes;
0132
0133 if ( attr == region_attr ) {
0134 uint32_t region_end;
0135
0136 if ( end - region_base <= AARCH32_PMSA_MIN_REGION_ALIGN ) {
0137
0138 regions[ ri ].base = base;
0139 break;
0140 }
0141
0142 region_end = region_limit + AARCH32_PMSA_MIN_REGION_ALIGN;
0143
0144 if ( region_end - base <= AARCH32_PMSA_MIN_REGION_ALIGN ) {
0145
0146 regions[ ri ].limit = limit;
0147 break;
0148 }
0149
0150 if ( base >= region_base && end <= region_end ) {
0151
0152 break;
0153 }
0154 }
0155
0156 if ( base <= region_base ) {
0157 size_t i;
0158
0159 if ( region_used >= region_max ) {
0160 return 0;
0161 }
0162
0163 for ( i = region_used; i > ri; --i ) {
0164 regions[ i ] = regions[ i - 1 ];
0165 }
0166
0167
0168 ++region_used;
0169 regions[ ri ].base = base;
0170 regions[ ri ].limit = limit;
0171 regions[ ri ].attributes = attr;
0172 break;
0173 }
0174 }
0175
0176 if ( ri == region_used ) {
0177 if ( region_used >= region_max ) {
0178 return 0;
0179 }
0180
0181
0182 ++region_used;
0183 regions[ ri ].base = base;
0184 regions[ ri ].limit = limit;
0185 regions[ ri ].attributes = attr;
0186 }
0187 }
0188
0189 return region_used;
0190 }
0191
0192 void _AArch32_PMSA_Initialize(
0193 uint32_t memory_attributes_0,
0194 uint32_t memory_attributes_1,
0195 const AArch32_PMSA_Section *sections,
0196 size_t section_count
0197 )
0198 {
0199 AArch32_PMSA_Region regions[ AARCH32_PMSA_REGION_MAX ];
0200 size_t region_max;
0201 size_t region_used;
0202
0203 _AArch32_Write_mair0( memory_attributes_0 );
0204 _AArch32_Write_mair1( memory_attributes_1 );
0205
0206 region_max = ( _AArch32_Read_mpuir() & AARCH32_MPUIR_REGION_MASK ) >>
0207 AARCH32_MPUIR_REGION_SHIFT;
0208
0209 region_used = _AArch32_PMSA_Map_sections_to_regions(
0210 sections,
0211 section_count,
0212 regions,
0213 region_max
0214 );
0215
0216 if ( region_used > 0 ) {
0217 _AArch32_PMSA_Configure( regions, region_used, region_max );
0218 }
0219 }
0220
0221 #endif