score: Fix per-CPU data allocation

Allocate the per-CPU data for secondary processors directly from the
heap areas before heap initialization and not via
_Workspace_Allocate_aligned().  This avoids dependency on the workspace
allocator.  It fixes also a problem on some platforms (e.g. QorIQ) where
at this early point in the system initialization the top of the RAM is
used by low-level startup code on secondary processors (boot pages).

Update #3507.
This commit is contained in:
Sebastian Huber
2018-12-18 08:45:06 +01:00
parent e7b0a72566
commit 7c19e50bdd
10 changed files with 183 additions and 32 deletions

View File

@@ -193,7 +193,8 @@ typedef enum {
INTERNAL_ERROR_LIBIO_STDOUT_FD_OPEN_FAILED = 36,
INTERNAL_ERROR_LIBIO_STDERR_FD_OPEN_FAILED = 37,
INTERNAL_ERROR_ILLEGAL_USE_OF_FLOATING_POINT_UNIT = 38,
INTERNAL_ERROR_ARC4RANDOM_GETENTROPY_FAIL = 39
INTERNAL_ERROR_ARC4RANDOM_GETENTROPY_FAIL = 39,
INTERNAL_ERROR_NO_MEMORY_FOR_PER_CPU_DATA = 40
} Internal_errors_Core_list;
typedef CPU_Uint32ptr Internal_errors_t;

View File

@@ -7,7 +7,7 @@
*/
/*
* Copyright (c) 2012, 2017 embedded brains GmbH. All rights reserved.
* Copyright (c) 2012, 2018 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Dornierstr. 4
@@ -66,7 +66,8 @@ static const char *const internal_error_text[] = {
"INTERNAL_ERROR_LIBIO_STDOUT_FD_OPEN_FAILED",
"INTERNAL_ERROR_LIBIO_STDERR_FD_OPEN_FAILED",
"INTERNAL_ERROR_ILLEGAL_USE_OF_FLOATING_POINT_UNIT",
"INTERNAL_ERROR_ARC4RANDOM_GETENTROPY_FAIL"
"INTERNAL_ERROR_ARC4RANDOM_GETENTROPY_FAIL",
"INTERNAL_ERROR_NO_MEMORY_FOR_PER_CPU_DATA"
};
const char *rtems_internal_error_text( rtems_fatal_code error )

View File

@@ -77,37 +77,43 @@ static uintptr_t _Workspace_Space_for_TLS( uintptr_t page_size )
return space;
}
static uintptr_t _Workspace_Space_for_per_CPU_data( uintptr_t page_size )
{
uintptr_t space;
#ifdef RTEMS_SMP
uintptr_t size;
static void *_Workspace_Allocate_from_areas(
Heap_Area *areas,
size_t area_count,
uintptr_t size,
uintptr_t alignment
)
{
size_t i;
size = RTEMS_LINKER_SET_SIZE( _Per_CPU_Data );
_Assert( size % CPU_CACHE_LINE_BYTES == 0 );
for ( i = 0; i < area_count; ++i ) {
Heap_Area *area;
uintptr_t alloc_begin;
uintptr_t alloc_size;
if ( size > 0 ) {
/*
* Memory allocated with an alignment constraint is allocated from the end of
* a free block. The last allocation may need one free block of minimum
* size.
*/
space = _Heap_Min_block_size( page_size );
area = &areas[ i ];
alloc_begin = (uintptr_t) area->begin;
alloc_begin = ( alloc_begin + alignment - 1 ) & ~( alignment - 1 );
alloc_size = size;
alloc_size += alloc_begin - (uintptr_t) area->begin;
space += ( rtems_configuration_get_maximum_processors() - 1 )
* _Heap_Size_with_overhead( page_size, size, CPU_CACHE_LINE_BYTES );
} else {
space = 0;
if ( area->size >= alloc_size ) {
area->begin = (void *) ( alloc_begin + size );
area->size -= alloc_size;
return (void *) alloc_begin;
}
#else
space = 0;
}
return NULL;
}
#endif
return space;
}
static void _Workspace_Allocate_per_CPU_data( void )
static void _Workspace_Allocate_per_CPU_data(
Heap_Area *areas,
size_t area_count
)
{
#ifdef RTEMS_SMP
uintptr_t size;
@@ -126,11 +132,23 @@ static void _Workspace_Allocate_per_CPU_data( void )
for ( cpu_index = 1 ; cpu_index < cpu_max ; ++cpu_index ) {
cpu = _Per_CPU_Get_by_index( cpu_index );
cpu->data = _Workspace_Allocate_aligned( size, CPU_CACHE_LINE_BYTES );
_Assert( cpu->data != NULL );
cpu->data = _Workspace_Allocate_from_areas(
areas,
area_count,
size,
CPU_CACHE_LINE_BYTES
);
if( cpu->data == NULL ) {
_Internal_error( INTERNAL_ERROR_NO_MEMORY_FOR_PER_CPU_DATA );
}
memcpy( cpu->data, RTEMS_LINKER_SET_BEGIN( _Per_CPU_Data ), size);
}
}
#else
(void) areas;
(void) area_count;
#endif
}
@@ -148,11 +166,12 @@ void _Workspace_Handler_initialization(
uintptr_t overhead;
size_t i;
_Workspace_Allocate_per_CPU_data( areas, area_count );
page_size = CPU_HEAP_ALIGNMENT;
remaining = rtems_configuration_get_work_space_size();
remaining += _Workspace_Space_for_TLS( page_size );
remaining += _Workspace_Space_for_per_CPU_data( page_size );
init_or_extend = _Heap_Initialize;
do_zero = rtems_configuration_get_do_zero_of_workspace();
@@ -208,7 +227,6 @@ void _Workspace_Handler_initialization(
}
_Heap_Protection_set_delayed_free_fraction( &_Workspace_Area, 1 );
_Workspace_Allocate_per_CPU_data();
}
void *_Workspace_Allocate(

View File

@@ -237,6 +237,17 @@ smpfatal08_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_FLAGS_smpfatal08) \
endif
endif
if HAS_SMP
if TEST_smpfatal09
smp_tests += smpfatal09
smp_screens += smpfatal09/smpfatal09.scn
smp_docs += smpfatal09/smpfatal09.doc
smpfatal09_SOURCES = smpfatal09/init.c
smpfatal09_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_FLAGS_smpfatal09) \
$(support_includes)
endif
endif
if HAS_SMP
if TEST_smpipi01
smp_tests += smpipi01

View File

@@ -53,6 +53,7 @@ RTEMS_TEST_CHECK([smpfatal04])
RTEMS_TEST_CHECK([smpfatal05])
RTEMS_TEST_CHECK([smpfatal06])
RTEMS_TEST_CHECK([smpfatal08])
RTEMS_TEST_CHECK([smpfatal09])
RTEMS_TEST_CHECK([smpipi01])
RTEMS_TEST_CHECK([smpload01])
RTEMS_TEST_CHECK([smplock01])

View File

@@ -0,0 +1,87 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (C) 2018 embedded brains GmbH
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <rtems.h>
#include <rtems/score/percpudata.h>
#include <rtems/score/wkspace.h>
#include <tmacros.h>
static PER_CPU_DATA_ITEM(int, i) = 123;
const char rtems_test_name[] = "SMPFATAL 9";
static void Init( rtems_task_argument arg )
{
Heap_Area area = { .begin = NULL, .size = 0 };
int i;
TEST_BEGIN();
i = *PER_CPU_DATA_GET( _Per_CPU_Get_snapshot(), int, i );
RTEMS_OBFUSCATE_VARIABLE( i );
rtems_test_assert( i == 123 );
_Workspace_Handler_initialization( &area, 1, NULL );
rtems_test_assert( 0 );
}
static void fatal_extension(
rtems_fatal_source source,
bool always_set_to_false,
rtems_fatal_code code
)
{
if (
source == INTERNAL_ERROR_CORE
&& !always_set_to_false
&& code == INTERNAL_ERROR_NO_MEMORY_FOR_PER_CPU_DATA
) {
TEST_END();
}
}
#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER
#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
#define CONFIGURE_INITIAL_EXTENSIONS \
{ .fatal = fatal_extension }, \
RTEMS_TEST_INITIAL_EXTENSION
#define CONFIGURE_MAXIMUM_PROCESSORS 2
#define CONFIGURE_MAXIMUM_TASKS 1
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
#define CONFIGURE_INIT
#include <rtems/confdefs.h>

View File

@@ -0,0 +1,11 @@
This file describes the directives and concepts tested by this test set.
test set name: smpfatal09
directives:
- _Workspace_Handler_initialization()
concepts:
- Provoke the INTERNAL_ERROR_NO_MEMORY_FOR_PER_CPU_DATA fatal error.

View File

@@ -0,0 +1,7 @@
*** BEGIN OF TEST SMPFATAL 9 ***
*** TEST VERSION: 5.0.0.cfa82b34b0c53ab4e3d84dd8ab5225793d48fcd0
*** TEST STATE: EXPECTED-PASS
*** TEST BUILD: RTEMS_SMP
*** TEST TOOLS: 7.4.0 20181206 (RTEMS 5, RSB ddba5372522da341fa20b2c75dfe966231cb6790, Newlib df6915f029ac9acd2b479ea898388cbd7dda4974)
*** END OF TEST SMPFATAL 9 ***

View File

@@ -36,7 +36,7 @@ static void test_internal_error_text(void)
} while ( text != text_last );
rtems_test_assert(
error - 3 == INTERNAL_ERROR_ARC4RANDOM_GETENTROPY_FAIL
error - 3 == INTERNAL_ERROR_NO_MEMORY_FOR_PER_CPU_DATA
);
}

View File

@@ -1,4 +1,8 @@
*** BEGIN OF TEST SPINTERNALERROR 2 ***
*** TEST VERSION: 5.0.0.cfa82b34b0c53ab4e3d84dd8ab5225793d48fcd0
*** TEST STATE: EXPECTED-PASS
*** TEST BUILD:
*** TEST TOOLS: 7.4.0 20181206 (RTEMS 5, RSB ddba5372522da341fa20b2c75dfe966231cb6790, Newlib df6915f029ac9acd2b479ea898388cbd7dda4974)
INTERNAL_ERROR_NO_CONFIGURATION_TABLE
INTERNAL_ERROR_NO_CPU_TABLE
INTERNAL_ERROR_TOO_LITTLE_WORKSPACE
@@ -31,6 +35,15 @@ INTERNAL_ERROR_THREAD_QUEUE_DEADLOCK
INTERNAL_ERROR_THREAD_QUEUE_ENQUEUE_STICKY_FROM_BAD_STATE
INTERNAL_ERROR_BAD_THREAD_DISPATCH_DISABLE_LEVEL
INTERNAL_ERROR_BAD_THREAD_DISPATCH_ENVIRONMENT
INTERNAL_ERROR_RTEMS_INIT_TASK_CREATE_FAILED
INTERNAL_ERROR_POSIX_INIT_THREAD_CREATE_FAILED
INTERNAL_ERROR_LIBIO_USER_ENV_KEY_CREATE_FAILED
INTERNAL_ERROR_LIBIO_SEM_CREATE_FAILED
INTERNAL_ERROR_LIBIO_STDOUT_FD_OPEN_FAILED
INTERNAL_ERROR_LIBIO_STDERR_FD_OPEN_FAILED
INTERNAL_ERROR_ILLEGAL_USE_OF_FLOATING_POINT_UNIT
INTERNAL_ERROR_ARC4RANDOM_GETENTROPY_FAIL
INTERNAL_ERROR_NO_MEMORY_FOR_PER_CPU_DATA
?
?
INTERNAL_ERROR_CORE
@@ -79,4 +92,5 @@ RTEMS_IO_ERROR
RTEMS_PROXY_BLOCKING
?
?
*** END OF TEST SPINTERNALERROR 2 ***