source: rtems/cpukit/score/cpu/arm/aarch32-psma-init.c @ 9165349d

Last change on this file since 9165349d was 854ea2b, checked in by Sebastian Huber <sebastian.huber@…>, on 12/15/20 at 09:59:21

arm: Add support for Arm PMSAv8-32

Update #4202.

  • Property mode set to 100644
File size: 5.4 KB
Line 
1/* SPDX-License-Identifier: BSD-2-Clause */
2
3/**
4 * @file
5 *
6 * @ingroup RTEMSScoreCPUARMPMSAv8
7 *
8 * @brief This source file contains the implementation of
9 *   _AArch32_PMSA_Initialize().
10 */
11
12/*
13 * Copyright (C) 2020 embedded brains GmbH (http://www.embedded-brains.de)
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 *    notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 *    notice, this list of conditions and the following disclaimer in the
22 *    documentation and/or other materials provided with the distribution.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#ifdef HAVE_CONFIG_H
38#include "config.h"
39#endif
40
41#include <rtems/score/aarch32-pmsa.h>
42
43#if __ARM_ARCH >= 8 && __ARM_ARCH_PROFILE == 'R'
44
45#include <rtems/score/aarch32-system-registers.h>
46#include <rtems/score/cpu.h>
47
48#define AARCH32_PSMA_REGION_MAX \
49  ( ( AARCH32_MPUIR_REGION_MASK >> AARCH32_MPUIR_REGION_SHIFT ) + 1 )
50
51typedef struct {
52  uint32_t base;
53  uint32_t limit;
54  uint32_t attributes;
55} AArch32_PMSA_Region;
56
57static void _AArch32_PMSA_Configure(
58  const AArch32_PMSA_Region *regions,
59  size_t                     region_used,
60  size_t                     region_max
61)
62{
63  size_t   ri;
64  uint32_t sctlr;
65
66  for ( ri = 0 ; ri < region_used; ++ri ) {
67    uint32_t prbar;
68    uint32_t prlar;
69    uint32_t attr;
70
71    prbar = regions[ ri ].base;
72    prlar = regions[ ri ].limit;
73    attr = regions[ ri ].attributes;
74
75    prbar |= ( attr >> 6 ) & 0x3fU;
76    prlar |= attr & 0x3fU;
77
78    _AArch32_Write_prselr( ri );
79    _ARM_Instruction_synchronization_barrier();
80    _AArch32_Write_prbar( prbar );
81    _AArch32_Write_prlar( prlar );
82  }
83
84  for ( ri = region_used ; ri < region_max; ++ri ) {
85    _AArch32_Write_prselr( ri );
86    _ARM_Instruction_synchronization_barrier();
87    _AArch32_Write_prbar( 0 );
88    _AArch32_Write_prlar( 0 );
89  }
90
91  _ARM_Data_synchronization_barrier();
92  sctlr = _AArch32_Read_sctlr();
93  sctlr |= AARCH32_SCTLR_M | AARCH32_SCTLR_I | AARCH32_SCTLR_C;
94  sctlr &= ~AARCH32_SCTLR_BR;
95  _AArch32_Write_sctlr( sctlr );
96  _ARM_Instruction_synchronization_barrier();
97}
98
99void _AArch32_PMSA_Initialize(
100  uint32_t                    memory_attributes_0,
101  uint32_t                    memory_attributes_1,
102  const AArch32_PMSA_Section *sections,
103  size_t                      section_count
104)
105{
106  AArch32_PMSA_Region regions[ AARCH32_PSMA_REGION_MAX ];
107  size_t ri;
108  size_t si;
109  size_t region_used;
110  size_t region_max;
111
112  _AArch32_Write_mair0( memory_attributes_0 );
113  _AArch32_Write_mair1( memory_attributes_1 );
114
115  region_max = ( _AArch32_Read_mpuir() & AARCH32_MPUIR_REGION_MASK ) >>
116    AARCH32_MPUIR_REGION_SHIFT;
117  region_used = 0;
118
119  for ( si = 0; si < section_count; ++si ) {
120    uint32_t base;
121    uint32_t limit;
122    uint32_t attr;
123
124    base = sections[ si ].begin;
125    limit = sections[ si ].end;
126    attr = sections[ si ].attributes;
127
128    if ( base == limit ) {
129      continue;
130    }
131
132    base = RTEMS_ALIGN_DOWN( base, AARCH32_PMSA_MIN_REGION_ALIGN );
133    limit = RTEMS_ALIGN_DOWN( limit - 1, AARCH32_PMSA_MIN_REGION_ALIGN );
134
135    for ( ri = 0; ri < region_used; ++ri ) {
136      uint32_t region_base;
137      uint32_t region_limit;
138      uint32_t region_attr;
139
140      region_base = regions[ ri ].base;
141      region_limit = regions[ ri ].limit;
142      region_attr = regions[ ri ].attributes;
143
144      if (
145        limit + AARCH32_PMSA_MIN_REGION_ALIGN == region_base &&
146          attr == region_attr
147      ) {
148        /* Merge section with existing region */
149        regions[ ri ].base = base;
150        break;
151      } else if (
152        base == region_limit + AARCH32_PMSA_MIN_REGION_ALIGN &&
153          attr == region_attr
154      ) {
155        /* Merge section with existing region */
156        regions[ ri ].limit = limit;
157        break;
158      } else if ( limit < region_base ) {
159        size_t i;
160
161        if ( region_used >= region_max ) {
162          return;
163        }
164
165        for ( i = ri; i < region_used; ++i ) {
166          regions[ i + 1 ] = regions[ i ];
167        }
168
169        /* New first region */
170        ++region_used;
171        regions[ ri ].base = base;
172        regions[ ri ].limit = limit;
173        regions[ ri ].attributes = attr;
174        break;
175      }
176    }
177
178    if ( ri == region_used ) {
179      if ( region_used >= region_max ) {
180        return;
181      }
182
183      /* New last region */
184      regions[ ri ].base = base;
185      regions[ ri ].limit = limit;
186      regions[ ri ].attributes = attr;
187      ++region_used;
188    }
189  }
190
191  _AArch32_PMSA_Configure( regions, region_used, region_max );
192}
193
194#endif
Note: See TracBrowser for help on using the repository browser.