source: rtems/bsps/powerpc/qoriq/start/mmu-config.c @ eea21eac

5
Last change on this file since eea21eac was eea21eac, checked in by Sebastian Huber <sebastian.huber@…>, on Dec 13, 2019 at 5:18:36 AM

bsps: Rework work area initialization

The work area initialization was done by the BSP through
bsp_work_area_initialize(). This approach predated the system
initialization through the system initialization linker set. The
workspace and C program heap were unconditionally initialized. The aim
is to support RTEMS application configurations which do not need the
workspace and C program heap. In these configurations, the workspace
and C prgram heap should not get initialized.

Change all bsp_work_area_initialize() to implement _Memory_Get()
instead. Move the dirty memory, sbrk(), per-CPU data, workspace, and
malloc() heap initialization into separate system initialization steps.
This makes it also easier to test the individual initialization steps.

This change adds a dependency to _Heap_Extend() to all BSPs. This
dependency will be removed in a follow up change.

Update #3838.

  • Property mode set to 100644
File size: 8.4 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup RTEMSBSPsPowerPCQorIQMMU
5 *
6 * @brief MMU implementation.
7 */
8
9/*
10 * Copyright (c) 2011, 2018 embedded brains GmbH.  All rights reserved.
11 *
12 *  embedded brains GmbH
13 *  Dornierstr. 4
14 *  82178 Puchheim
15 *  Germany
16 *  <rtems@embedded-brains.de>
17 *
18 * The license and distribution terms for this file may be
19 * found in the file LICENSE in this distribution or at
20 * http://www.rtems.org/license/LICENSE.
21 */
22
23#include <bsp.h>
24#include <bsp/bootcard.h>
25#include <bsp/fdt.h>
26#include <bsp/linker-symbols.h>
27#include <bsp/mmu.h>
28#include <bsp/qoriq.h>
29
30#include <sys/param.h>
31
32#include <libfdt.h>
33
34#include <rtems/config.h>
35#include <rtems/sysinit.h>
36
37#define TEXT __attribute__((section(".bsp_start_text")))
38#define DATA __attribute__((section(".bsp_start_data")))
39
40typedef struct {
41        uintptr_t begin;
42        uintptr_t size;
43        uint32_t mas2;
44        uint32_t mas3;
45        uint32_t mas7;
46} entry;
47
48#define ENTRY_X(b, s) { \
49        .begin = (uintptr_t) b, \
50        .size = (uintptr_t) s, \
51        .mas2 = 0, \
52        .mas3 = FSL_EIS_MAS3_SX \
53}
54
55#define ENTRY_R(b, s) { \
56        .begin = (uintptr_t) b, \
57        .size = (uintptr_t) s, \
58        .mas2 = 0, \
59        .mas3 = FSL_EIS_MAS3_SR \
60}
61
62#ifdef RTEMS_SMP
63  #define ENTRY_RW_MAS2 FSL_EIS_MAS2_M
64#else
65  #define ENTRY_RW_MAS2 0
66#endif
67
68#define ENTRY_RW(b, s) { \
69        .begin = (uintptr_t) b, \
70        .size = (uintptr_t) s, \
71        .mas2 = ENTRY_RW_MAS2, \
72        .mas3 = FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW \
73}
74
75#define ENTRY_IO(b, s) { \
76        .begin = (uintptr_t) b, \
77        .size = (uintptr_t) s, \
78        .mas2 = FSL_EIS_MAS2_I | FSL_EIS_MAS2_G, \
79        .mas3 = FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW \
80}
81
82#define ENTRY_DEV(b, s) { \
83        .begin = (uintptr_t) b, \
84        .size = (uintptr_t) s, \
85        .mas2 = FSL_EIS_MAS2_I | FSL_EIS_MAS2_G, \
86        .mas3 = FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW, \
87        .mas7 = QORIQ_MMU_DEVICE_MAS7 \
88}
89
90/*
91 * MMU entry for BMan and QMan software portals.
92 *
93 * The M bit must be set if stashing is used, see 3.3.8.6 DQRR Entry Stashing
94 * and 3.3.8 Software Portals in T4240DPAARM.
95 *
96 * The G bit must be set, otherwise ECC errors in the QMan software portals
97 * will occur.  No documentation reference for this is available.
98 */
99#define ENTRY_DEV_CACHED(b, s) { \
100        .begin = (uintptr_t) b, \
101        .size = (uintptr_t) s, \
102        .mas2 = FSL_EIS_MAS2_M | FSL_EIS_MAS2_G, \
103        .mas3 = FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW, \
104        .mas7 = QORIQ_MMU_DEVICE_MAS7 \
105}
106
107#define WORKSPACE_ENTRY_INDEX 0
108
109static entry DATA config[] = {
110        /* Must be first entry, see WORKSPACE_ENTRY_INDEX */
111        ENTRY_RW(bsp_section_work_begin, bsp_section_work_size),
112
113        #if defined(RTEMS_MULTIPROCESSING) && \
114            defined(QORIQ_INTERCOM_AREA_BEGIN) && \
115            defined(QORIQ_INTERCOM_AREA_SIZE)
116                {
117                        .begin = QORIQ_INTERCOM_AREA_BEGIN,
118                        .size = QORIQ_INTERCOM_AREA_SIZE,
119                        .mas2 = FSL_EIS_MAS2_M,
120                        .mas3 = FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW
121                },
122        #endif
123        ENTRY_X(bsp_section_start_begin, bsp_section_start_size),
124        ENTRY_R(bsp_section_fast_text_load_begin, bsp_section_fast_text_size),
125        ENTRY_X(bsp_section_fast_text_begin, bsp_section_fast_text_size),
126        ENTRY_X(bsp_section_text_begin, bsp_section_text_size),
127        ENTRY_R(bsp_section_rodata_load_begin, bsp_section_rodata_size),
128        ENTRY_R(bsp_section_rodata_begin, bsp_section_rodata_size),
129        ENTRY_R(bsp_section_fast_data_load_begin, bsp_section_fast_data_size),
130        ENTRY_RW(bsp_section_fast_data_begin, bsp_section_fast_data_size),
131        ENTRY_R(bsp_section_data_load_begin, bsp_section_data_size),
132        ENTRY_RW(bsp_section_data_begin, bsp_section_data_size),
133        ENTRY_RW(bsp_section_sbss_begin, bsp_section_sbss_size),
134        ENTRY_RW(bsp_section_bss_begin, bsp_section_bss_size),
135        ENTRY_RW(bsp_section_rtemsstack_begin, bsp_section_rtemsstack_size),
136        ENTRY_RW(bsp_section_stack_begin, bsp_section_stack_size),
137        ENTRY_IO(bsp_section_nocache_begin, bsp_section_nocache_size),
138        ENTRY_IO(bsp_section_nocachenoload_begin, bsp_section_nocachenoload_size),
139#ifndef QORIQ_IS_HYPERVISOR_GUEST
140#if QORIQ_CHIP_IS_T_VARIANT(QORIQ_CHIP_VARIANT)
141        /* BMan Portals */
142        ENTRY_DEV_CACHED(&qoriq_bman_portal[0][0], sizeof(qoriq_bman_portal[0])),
143        ENTRY_DEV(&qoriq_bman_portal[1][0], sizeof(qoriq_bman_portal[1])),
144        /* QMan Portals */
145        ENTRY_DEV_CACHED(&qoriq_qman_portal[0][0], sizeof(qoriq_qman_portal[0])),
146        ENTRY_DEV(&qoriq_qman_portal[1][0], sizeof(qoriq_qman_portal[1])),
147#endif
148        ENTRY_DEV(&qoriq, sizeof(qoriq))
149#endif
150};
151
152static DATA char memory_path[] = "/memory";
153
154#ifdef QORIQ_IS_HYPERVISOR_GUEST
155static void TEXT add_dpaa_bqman_portals(
156        qoriq_mmu_context *context,
157        const void *fdt,
158        const char *compatible
159)
160{
161        int node;
162
163        node = -1;
164
165        while (true) {
166                const void *val;
167                int len;
168                uintptr_t paddr;
169                uintptr_t size;
170
171                node = fdt_node_offset_by_compatible(fdt, node, compatible);
172                if (node < 0) {
173                        break;
174                }
175
176                val = fdt_getprop(fdt, node, "reg", &len);
177                if (len != 32) {
178                        continue;
179                }
180
181                paddr = (uintptr_t) fdt64_to_cpu(((fdt64_t *) val)[0]);
182                size = (uintptr_t) fdt64_to_cpu(((fdt64_t *) val)[1]);
183
184                qoriq_mmu_add(
185                        context,
186                        paddr,
187                        paddr + size - 1,
188                        0,
189                        FSL_EIS_MAS2_M | FSL_EIS_MAS2_G,
190                        FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW,
191                        QORIQ_MMU_DEVICE_MAS7
192                );
193
194                paddr = (uintptr_t) fdt64_to_cpu(((fdt64_t *) val)[2]);
195                size = (uintptr_t) fdt64_to_cpu(((fdt64_t *) val)[3]);
196
197                qoriq_mmu_add(
198                        context,
199                        paddr,
200                        paddr + size - 1,
201                        0,
202                        FSL_EIS_MAS2_I | FSL_EIS_MAS2_G,
203                        FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW,
204                        QORIQ_MMU_DEVICE_MAS7
205                );
206        }
207}
208
209static void TEXT add_dpaa_bpool(qoriq_mmu_context *context, const void *fdt)
210{
211        int node;
212
213        node = -1;
214
215        while (true) {
216                const void *val;
217                int len;
218                uintptr_t config_count;
219                uintptr_t size;
220                uintptr_t paddr;
221
222                node = fdt_node_offset_by_compatible(fdt, node, "fsl,bpool");
223                if (node < 0) {
224                        break;
225                }
226
227                val = fdt_getprop(fdt, node, "fsl,bpool-ethernet-cfg", &len);
228                if (len != 24) {
229                        continue;
230                }
231
232                config_count = (uintptr_t) fdt64_to_cpu(((fdt64_t *) val)[0]);
233                size = (uintptr_t) fdt64_to_cpu(((fdt64_t *) val)[1]);
234                paddr = (uintptr_t) fdt64_to_cpu(((fdt64_t *) val)[2]);
235
236                qoriq_mmu_add(
237                        context,
238                        paddr,
239                        paddr + config_count * size - 1,
240                        0,
241                        FSL_EIS_MAS2_M,
242                        FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW,
243                        0
244                );
245        }
246}
247#endif
248
249static void TEXT config_fdt_adjust(const void *fdt)
250{
251        int node;
252
253        node = fdt_path_offset_namelen(
254                fdt,
255                memory_path,
256                (int) sizeof(memory_path) - 1
257        );
258
259        if (node >= 0) {
260                int len;
261                const void *val;
262                uint64_t mem_begin;
263                uint64_t mem_size;
264
265                val = fdt_getprop(fdt, node, "reg", &len);
266                if (len == 8) {
267                        mem_begin = fdt32_to_cpu(((fdt32_t *) val)[0]);
268                        mem_size = fdt32_to_cpu(((fdt32_t *) val)[1]);
269                } else if (len == 16) {
270                        mem_begin = fdt64_to_cpu(((fdt64_t *) val)[0]);
271                        mem_size = fdt64_to_cpu(((fdt64_t *) val)[1]);
272                } else {
273                        mem_begin = 0;
274                        mem_size = 0;
275                }
276
277#ifndef __powerpc64__
278                mem_size = MIN(mem_size, 0x80000000U);
279#endif
280
281                if (
282                        mem_begin == 0
283                                && mem_size > (uintptr_t) bsp_section_work_end
284                                && (uintptr_t) bsp_section_nocache_end
285                                        < (uintptr_t) bsp_section_work_end
286                ) {
287                        /* Assign new value to allow a bsp_restart() */
288                        config[WORKSPACE_ENTRY_INDEX].size = (uintptr_t) mem_size
289                                - (uintptr_t) bsp_section_work_begin;
290                }
291        }
292}
293
294void TEXT qoriq_mmu_config(bool boot_processor, int first_tlb, int scratch_tlb)
295{
296        qoriq_mmu_context context;
297        const void *fdt;
298        int max_count;
299        int i;
300
301        for (i = 0; i < QORIQ_TLB1_ENTRY_COUNT; ++i) {
302                if (i != scratch_tlb) {
303                        qoriq_tlb1_invalidate(i);
304                }
305        }
306
307        fdt = bsp_fdt_get();
308        qoriq_mmu_context_init(&context);
309
310#ifdef QORIQ_IS_HYPERVISOR_GUEST
311        add_dpaa_bqman_portals(&context, fdt, "fsl,bman-portal");
312        add_dpaa_bqman_portals(&context, fdt, "fsl,qman-portal");
313        add_dpaa_bpool(&context, fdt);
314        max_count = QORIQ_TLB1_ENTRY_COUNT - 1;
315#else
316        max_count = (3 * QORIQ_TLB1_ENTRY_COUNT) / 4;
317#endif
318
319        if (boot_processor) {
320                config_fdt_adjust(fdt);
321        }
322
323        for (i = 0; i < (int) (sizeof(config) / sizeof(config [0])); ++i) {
324                const entry *cur = &config [i];
325                if (cur->size > 0) {
326                        qoriq_mmu_add(
327                                &context,
328                                cur->begin,
329                                cur->begin + cur->size - 1,
330                                0,
331                                cur->mas2,
332                                cur->mas3,
333                                cur->mas7
334                        );
335                }
336        }
337
338        qoriq_mmu_partition(&context, max_count);
339        qoriq_mmu_write_to_tlb1(&context, first_tlb);
340}
341
342static Memory_Area _Memory_Areas[1];
343
344static const Memory_Information _Memory_Information =
345        MEMORY_INFORMATION_INITIALIZER(_Memory_Areas);
346
347static void bsp_memory_initialize(void)
348{
349        const entry *we = &config[WORKSPACE_ENTRY_INDEX];
350
351        _Memory_Initialize_by_size(
352                &_Memory_Areas[0],
353                (void *) we->begin,
354                we->size
355        );
356}
357
358RTEMS_SYSINIT_ITEM(
359        bsp_memory_initialize,
360        RTEMS_SYSINIT_MEMORY,
361        RTEMS_SYSINIT_ORDER_MIDDLE
362);
363
364const Memory_Information *_Memory_Get(void)
365{
366        return &_Memory_Information;
367}
Note: See TracBrowser for help on using the repository browser.