Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:23

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSScoreCPUARMPMSAv8
0007  *
0008  * @brief This source file contains the implementation of
0009  *   _AArch32_PMSA_Initialize().
0010  */
0011 
0012 /*
0013  * Copyright (C) 2020 embedded brains GmbH & Co. KG
0014  *
0015  * Redistribution and use in source and binary forms, with or without
0016  * modification, are permitted provided that the following conditions
0017  * are met:
0018  * 1. Redistributions of source code must retain the above copyright
0019  *    notice, this list of conditions and the following disclaimer.
0020  * 2. Redistributions in binary form must reproduce the above copyright
0021  *    notice, this list of conditions and the following disclaimer in the
0022  *    documentation and/or other materials provided with the distribution.
0023  *
0024  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0025  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0026  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0027  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0028  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0029  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0030  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0031  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0032  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0033  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0034  * POSSIBILITY OF SUCH DAMAGE.
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           /* Extend the region */
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           /* Extend the region */
0146           regions[ ri ].limit = limit;
0147           break;
0148         }
0149 
0150         if ( base >= region_base && end <= region_end ) {
0151           /* The section is contained in the region */
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         /* New first region */
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       /* New last region */
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