bsps/arm: Add support for small pages MMU

The small page MMU support reduces the granularity for memory settings
through the MMU from 1MiB sections to 4KiB small pages.

Enable it by default on the realview_pbx_a9_qemu BSP.
This commit is contained in:
Sebastian Huber
2019-10-28 10:15:28 +01:00
parent 3fb72b0f1e
commit f9648baf65
4 changed files with 103 additions and 30 deletions

View File

@@ -9,7 +9,7 @@
/* /*
* Copyright (c) 2013 Hesham AL-Matary. * Copyright (c) 2013 Hesham AL-Matary.
* Copyright (c) 2009-2014 embedded brains GmbH. All rights reserved. * Copyright (c) 2009-2019 embedded brains GmbH. All rights reserved.
* *
* embedded brains GmbH * embedded brains GmbH
* Dornierstr. 4 * Dornierstr. 4
@@ -28,6 +28,7 @@
#include <libcpu/arm-cp15.h> #include <libcpu/arm-cp15.h>
#include <bsp/start.h> #include <bsp/start.h>
#include <bsp/linker-symbols.h> #include <bsp/linker-symbols.h>
#include <bspopts.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@@ -106,16 +107,35 @@ arm_cp15_start_set_translation_table_entries(
const arm_cp15_start_section_config *config const arm_cp15_start_section_config *config
) )
{ {
uint32_t i = ARM_MMU_SECT_GET_INDEX(config->begin);
uint32_t iend =
ARM_MMU_SECT_GET_INDEX(ARM_MMU_SECT_MVA_ALIGN_UP(config->end));
uint32_t index_mask = (1U << (32 - ARM_MMU_SECT_BASE_SHIFT)) - 1U;
if (config->begin != config->end) { if (config->begin != config->end) {
uint32_t i;
uint32_t iend;
uint32_t index_mask;
uint32_t flags;
#ifdef ARM_MMU_USE_SMALL_PAGES
uint32_t *pt;
pt = &ttb[ARM_MMU_TRANSLATION_TABLE_ENTRY_COUNT];
i = ARM_MMU_SMALL_PAGE_GET_INDEX(config->begin);
iend = ARM_MMU_SMALL_PAGE_GET_INDEX(ARM_MMU_SECT_MVA_ALIGN_UP(config->end));
index_mask = (1U << (32 - ARM_MMU_SMALL_PAGE_BASE_SHIFT)) - 1U;
flags = ARM_MMU_SECT_FLAGS_TO_SMALL_PAGE(config->flags);
while (i != iend) { while (i != iend) {
ttb [i] = (i << ARM_MMU_SECT_BASE_SHIFT) | config->flags; pt[i] = (i << ARM_MMU_SMALL_PAGE_BASE_SHIFT) | flags;
i = (i + 1U) & index_mask; i = (i + 1U) & index_mask;
} }
#else
i = ARM_MMU_SECT_GET_INDEX(config->begin);
iend = ARM_MMU_SECT_GET_INDEX(ARM_MMU_SECT_MVA_ALIGN_UP(config->end));
index_mask = (1U << (32 - ARM_MMU_SECT_BASE_SHIFT)) - 1U;
flags = config->flags;
while (i != iend) {
ttb[i] = (i << ARM_MMU_SECT_BASE_SHIFT) | flags;
i = (i + 1U) & index_mask;
}
#endif
} }
} }
@@ -127,17 +147,36 @@ arm_cp15_start_setup_translation_table(
size_t config_count size_t config_count
) )
{ {
uint32_t dac = ARM_CP15_DAC_DOMAIN(client_domain, ARM_CP15_DAC_CLIENT); #ifdef ARM_MMU_USE_SMALL_PAGES
uint32_t *pt;
#endif
uint32_t dac;
size_t i; size_t i;
dac = ARM_CP15_DAC_DOMAIN(client_domain, ARM_CP15_DAC_CLIENT);
arm_cp15_set_domain_access_control(dac); arm_cp15_set_domain_access_control(dac);
arm_cp15_set_translation_table_base(ttb); arm_cp15_set_translation_table_base(ttb);
/* Initialize translation table with invalid entries */ /* Initialize translation table with invalid entries */
#ifdef ARM_MMU_USE_SMALL_PAGES
pt = &ttb[ARM_MMU_TRANSLATION_TABLE_ENTRY_COUNT];
for (i = 0; i < ARM_MMU_TRANSLATION_TABLE_ENTRY_COUNT; ++i) { for (i = 0; i < ARM_MMU_TRANSLATION_TABLE_ENTRY_COUNT; ++i) {
ttb [i] = 0; size_t j;
for (j = 0; j < ARM_MMU_SMALL_PAGE_TABLE_ENTRY_COUNT; ++j) {
pt[j] = 0;
} }
ttb[i] = (uint32_t) pt | (client_domain << ARM_MMU_SECT_DOMAIN_SHIFT)
| ARM_MMU_PAGE_TABLE_DEFAULT;
pt += ARM_MMU_SMALL_PAGE_TABLE_ENTRY_COUNT;
}
#else
for (i = 0; i < ARM_MMU_TRANSLATION_TABLE_ENTRY_COUNT; ++i) {
ttb[i] = 0;
}
#endif
for (i = 0; i < config_count; ++i) { for (i = 0; i < config_count; ++i) {
arm_cp15_start_set_translation_table_entries(ttb, &config_table [i]); arm_cp15_start_set_translation_table_entries(ttb, &config_table [i]);
} }

View File

@@ -1,7 +1,7 @@
MEMORY { MEMORY {
/* Waste the first 1MiB for NULL pointer protection */ /* Waste the first 1MiB for NULL pointer protection */
RAM : ORIGIN = 0x00100000, LENGTH = 255M - 16k RAM : ORIGIN = 0x00100000, LENGTH = 0x0fafc000
RAM_MMU : ORIGIN = 0x0fffc000, LENGTH = 16k RAM_MMU : ORIGIN = 0x0fbfc000, LENGTH = 0x404000
} }
REGION_ALIAS ("REGION_START", RAM); REGION_ALIAS ("REGION_START", RAM);

View File

@@ -1,8 +1,8 @@
/* /*
* Copyright (c) 2010-2013 embedded brains GmbH. All rights reserved. * Copyright (c) 2010-2019 embedded brains GmbH. All rights reserved.
* *
* embedded brains GmbH * embedded brains GmbH
* Obere Lagerstr. 30 * Dornierstr. 4
* 82178 Puchheim * 82178 Puchheim
* Germany * Germany
* <rtems@embedded-brains.de> * <rtems@embedded-brains.de>
@@ -14,6 +14,7 @@
#include <rtems.h> #include <rtems.h>
#include <libcpu/arm-cp15.h> #include <libcpu/arm-cp15.h>
#include <bspopts.h>
/* /*
* Translation table modification requires to propagate * Translation table modification requires to propagate
@@ -35,36 +36,67 @@ static uint32_t set_translation_table_entries(
uint32_t section_flags uint32_t section_flags
) )
{ {
uint32_t *ttb = arm_cp15_get_translation_table_base(); uint32_t *ttb;
uint32_t istart = ARM_MMU_SECT_GET_INDEX(begin); #ifdef ARM_MMU_USE_SMALL_PAGES
uint32_t iend = ARM_MMU_SECT_GET_INDEX(ARM_MMU_SECT_MVA_ALIGN_UP(end)); uint32_t *pt;
uint32_t index_mask = (1U << (32 - ARM_MMU_SECT_BASE_SHIFT)) - 1U; uint32_t flags;
uint32_t ctrl; #endif
uint32_t istart;
uint32_t iend;
uint32_t index_mask;
uint32_t section_flags_of_first_entry; uint32_t section_flags_of_first_entry;
uint32_t i; uint32_t i;
void *first_ttb_addr; uint32_t *modified_begin;
void *last_ttb_end; size_t modified_size;
ctrl = arm_cp15_get_control(); ttb = arm_cp15_get_translation_table_base();
section_flags_of_first_entry = ttb [istart]; #ifdef ARM_MMU_USE_SMALL_PAGES
last_ttb_end = first_ttb_addr = ttb + istart; pt = &ttb[ARM_MMU_TRANSLATION_TABLE_ENTRY_COUNT];
istart = ARM_MMU_SMALL_PAGE_GET_INDEX(begin);
iend = ARM_MMU_SMALL_PAGE_GET_INDEX(ARM_MMU_SMALL_PAGE_MVA_ALIGN_UP(end));
index_mask = (1U << (32 - ARM_MMU_SMALL_PAGE_BASE_SHIFT)) - 1U;
section_flags_of_first_entry = ARM_MMU_SMALL_PAGE_FLAGS_TO_SECT(pt[istart])
| ARM_MMU_PAGE_TABLE_FLAGS_TO_SECT(ttb[ARM_MMU_SECT_GET_INDEX(begin)]);
modified_begin = &pt[istart];
flags = ARM_MMU_SECT_FLAGS_TO_SMALL_PAGE(section_flags);
#else
istart = ARM_MMU_SECT_GET_INDEX(begin);
iend = ARM_MMU_SECT_GET_INDEX(ARM_MMU_SECT_MVA_ALIGN_UP(end));
index_mask = (1U << (32 - ARM_MMU_SECT_BASE_SHIFT)) - 1U;
section_flags_of_first_entry = ttb[istart];
modified_begin = &ttb[istart];
#endif
modified_size = 0;
for ( i = istart; i != iend; i = (i + 1U) & index_mask ) { for ( i = istart; i != iend; i = (i + 1U) & index_mask ) {
uint32_t addr = i << ARM_MMU_SECT_BASE_SHIFT; uint32_t pa;
ttb [i] = addr | section_flags; #ifdef ARM_MMU_USE_SMALL_PAGES
last_ttb_end = ttb + i + 1; pa = i << ARM_MMU_SMALL_PAGE_BASE_SHIFT;
pt[i] = pa | flags;
modified_size += ARM_MMU_SMALL_PAGE_TABLE_ENTRY_SIZE;
#else
pa = i << ARM_MMU_SECT_BASE_SHIFT;
ttb[i] = pa | section_flags;
modified_size += ARM_MMU_TRANSLATION_TABLE_ENTRY_SIZE;
#endif
} }
if ( ctrl & (ARM_CP15_CTRL_C | ARM_CP15_CTRL_M ) ) { if ((arm_cp15_get_control() & (ARM_CP15_CTRL_C | ARM_CP15_CTRL_M)) != 0) {
rtems_cache_flush_multiple_data_lines(first_ttb_addr, rtems_cache_flush_multiple_data_lines(modified_begin, modified_size);
last_ttb_end - first_ttb_addr);
} }
_ARM_Data_synchronization_barrier(); _ARM_Data_synchronization_barrier();
for ( i = istart; i != iend; i = (i + 1U) & index_mask ) { for ( i = istart; i != iend; i = (i + 1U) & index_mask ) {
void *mva = (void *) (i << ARM_MMU_SECT_BASE_SHIFT); void *mva;
#ifdef ARM_MMU_USE_SMALL_PAGES
mva = (void *) (i << ARM_MMU_SMALL_PAGE_BASE_SHIFT);
#else
mva = (void *) (i << ARM_MMU_SECT_BASE_SHIFT);
#endif
#if defined(__ARM_ARCH_7A__) #if defined(__ARM_ARCH_7A__)
/* /*
* Bit 31 needs to be 1 to indicate the register implements the * Bit 31 needs to be 1 to indicate the register implements the

View File

@@ -43,6 +43,8 @@ RTEMS_BSPOPTS_HELP([CLOCK_DRIVER_USE_ONLY_BOOT_PROCESSOR],
[If defined, then do the clock tick processing on the boot processor on behalf [If defined, then do the clock tick processing on the boot processor on behalf
of all other processors.]) of all other processors.])
RTEMS_BSPOPTS_SET([ARM_MMU_USE_SMALL_PAGES],[*],[1])
RTEMS_BSPOPTS_HELP([ARM_MMU_USE_SMALL_PAGES],[use MMU with small pages (4KiB)])
RTEMS_BSP_CLEANUP_OPTIONS RTEMS_BSP_CLEANUP_OPTIONS