kernel/init.c: allow for memset/memcpy alternatives during early boot

Zeroing the BSS and copying data to RAM with regular memset/memcpy may
cause problems when those functions are assuming a fully initialized
system for their optimizations to work e.g. some instructions require
an active MMU, but turning the MMU on needs the .bss section to be
cleared first, etc.

Commit c5b898743a ("aarch64: Fix alignment fault on z_bss_zero()")
provides a detailed explanation of such a case.

Replacing z_bss_zero() with an architecture specific one is problematic
as the former may see new sections added to it that would be missed by
the later. The same reasoning goes for z_data_copy().

Let's make maintenance much easier by providing weak versions of
memset/memcpy that can be overridden by architecture-specific safe
versions when needed.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
This commit is contained in:
Nicolas Pitre 2022-02-10 13:54:49 -05:00 committed by Anas Nashif
commit 678b76e4b0
6 changed files with 66 additions and 31 deletions

View file

@ -224,5 +224,7 @@ macro(toolchain_ld_relocation)
)
add_library(code_relocation_source_lib STATIC ${MEM_RELOCATION_CODE})
target_include_directories(code_relocation_source_lib PRIVATE
${ZEPHYR_BASE}/kernel/include ${ARCH_DIR}/${ARCH}/include)
target_link_libraries(code_relocation_source_lib zephyr_interface)
endmacro()

View file

@ -26,5 +26,7 @@ macro(toolchain_ld_relocation)
)
add_library(code_relocation_source_lib STATIC ${MEM_RELOCATION_CODE})
target_include_directories(code_relocation_source_lib PRIVATE
${ZEPHYR_BASE}/kernel/include ${ARCH_DIR}/${ARCH}/include)
target_link_libraries(code_relocation_source_lib zephyr_interface)
endmacro()

View file

@ -26,6 +26,9 @@ extern "C" {
/* Early boot functions */
void z_early_memset(void *dst, int c, size_t n);
void z_early_memcpy(void *dst, const void *src, size_t n);
void z_bss_zero(void);
#ifdef CONFIG_XIP
void z_data_copy(void);

View file

@ -75,6 +75,32 @@ extern void idle(void *unused1, void *unused2, void *unused3);
* some like x86 do this with optimized assembly
*/
/**
* @brief equivalent of memset() for early boot usage
*
* Architectures that can't safely use the regular (optimized) memset very
* early during boot because e.g. hardware isn't yet sufficiently initialized
* may override this with their own safe implementation.
*/
__boot_func
void __weak z_early_memset(void *dst, int c, size_t n)
{
(void) memset(dst, c, n);
}
/**
* @brief equivalent of memcpy() for early boot usage
*
* Architectures that can't safely use the regular (optimized) memcpy very
* early during boot because e.g. hardware isn't yet sufficiently initialized
* may override this with their own safe implementation.
*/
__boot_func
void __weak z_early_memcpy(void *dst, const void *src, size_t n)
{
(void) memcpy(dst, src, n);
}
/**
* @brief Clear BSS
*
@ -83,14 +109,16 @@ extern void idle(void *unused1, void *unused2, void *unused3);
__boot_func
void z_bss_zero(void)
{
(void)memset(__bss_start, 0, __bss_end - __bss_start);
z_early_memset(__bss_start, 0, __bss_end - __bss_start);
#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_ccm), okay)
(void)memset(&__ccm_bss_start, 0,
((uint32_t) &__ccm_bss_end - (uint32_t) &__ccm_bss_start));
z_early_memset(&__ccm_bss_start, 0,
(uintptr_t) &__ccm_bss_end
- (uintptr_t) &__ccm_bss_start);
#endif
#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_dtcm), okay)
(void)memset(&__dtcm_bss_start, 0,
((uint32_t) &__dtcm_bss_end - (uint32_t) &__dtcm_bss_start));
z_early_memset(&__dtcm_bss_start, 0,
(uintptr_t) &__dtcm_bss_end
- (uintptr_t) &__dtcm_bss_start);
#endif
#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_ocm), okay)
(void)memset(&__ocm_bss_start, 0,
@ -102,8 +130,8 @@ void z_bss_zero(void)
bss_zeroing_relocation();
#endif /* CONFIG_CODE_DATA_RELOCATION */
#ifdef CONFIG_COVERAGE_GCOV
(void)memset(&__gcov_bss_start, 0,
((uintptr_t) &__gcov_bss_end - (uintptr_t) &__gcov_bss_start));
z_early_memset(&__gcov_bss_start, 0,
((uintptr_t) &__gcov_bss_end - (uintptr_t) &__gcov_bss_start));
#endif
}
@ -119,9 +147,9 @@ void z_bss_zero(void)
__boot_func
void z_bss_zero_boot(void)
{
(void)memset(&lnkr_boot_bss_start, 0,
(uintptr_t)&lnkr_boot_bss_end
- (uintptr_t)&lnkr_boot_bss_start);
z_early_memset(&lnkr_boot_bss_start, 0,
(uintptr_t)&lnkr_boot_bss_end
- (uintptr_t)&lnkr_boot_bss_start);
}
#endif /* CONFIG_LINKER_USE_BOOT_SECTION */
@ -141,9 +169,9 @@ __pinned_func
#endif
void z_bss_zero_pinned(void)
{
(void)memset(&lnkr_pinned_bss_start, 0,
(uintptr_t)&lnkr_pinned_bss_end
- (uintptr_t)&lnkr_pinned_bss_start);
z_early_memset(&lnkr_pinned_bss_start, 0,
(uintptr_t)&lnkr_pinned_bss_end
- (uintptr_t)&lnkr_pinned_bss_start);
}
#endif /* CONFIG_LINKER_USE_PINNED_SECTION */

View file

@ -8,7 +8,7 @@
#include <zephyr.h>
#include <kernel.h>
#include <string.h>
#include <kernel_internal.h>
#include <linker/linker-defs.h>
#ifdef CONFIG_STACK_CANARIES
@ -22,23 +22,23 @@ extern volatile uintptr_t __stack_chk_guard;
*/
void z_data_copy(void)
{
(void)memcpy(&__data_region_start, &__data_region_load_start,
__data_region_end - __data_region_start);
z_early_memcpy(&__data_region_start, &__data_region_load_start,
__data_region_end - __data_region_start);
#ifdef CONFIG_ARCH_HAS_RAMFUNC_SUPPORT
(void)memcpy(&__ramfunc_start, &__ramfunc_load_start,
(uintptr_t) &__ramfunc_size);
z_early_memcpy(&__ramfunc_start, &__ramfunc_load_start,
(uintptr_t) &__ramfunc_size);
#endif /* CONFIG_ARCH_HAS_RAMFUNC_SUPPORT */
#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_ccm), okay)
(void)memcpy(&__ccm_data_start, &__ccm_data_rom_start,
__ccm_data_end - __ccm_data_start);
z_early_memcpy(&__ccm_data_start, &__ccm_data_rom_start,
__ccm_data_end - __ccm_data_start);
#endif
#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_itcm), okay)
(void)memcpy(&__itcm_start, &__itcm_load_start,
(uintptr_t) &__itcm_size);
z_early_memcpy(&__itcm_start, &__itcm_load_start,
(uintptr_t) &__itcm_size);
#endif
#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_dtcm), okay)
(void)memcpy(&__dtcm_data_start, &__dtcm_data_load_start,
__dtcm_data_end - __dtcm_data_start);
z_early_memcpy(&__dtcm_data_start, &__dtcm_data_load_start,
__dtcm_data_end - __dtcm_data_start);
#endif
#ifdef CONFIG_CODE_DATA_RELOCATION
extern void data_copy_xip_relocation(void);
@ -65,8 +65,8 @@ void z_data_copy(void)
}
__stack_chk_guard = guard_copy;
#else
(void)memcpy(&_app_smem_start, &_app_smem_rom_start,
_app_smem_end - _app_smem_start);
z_early_memcpy(&_app_smem_start, &_app_smem_rom_start,
_app_smem_end - _app_smem_start);
#endif /* CONFIG_STACK_CANARIES */
#endif /* CONFIG_USERSPACE */
}

View file

@ -109,7 +109,7 @@ SOURCE_CODE_INCLUDES = """
#include <zephyr.h>
#include <linker/linker-defs.h>
#include <kernel_structs.h>
#include <string.h>
#include <kernel_internal.h>
"""
EXTERN_LINKER_VAR_DECLARATION = """
@ -134,14 +134,14 @@ void bss_zeroing_relocation(void)
"""
MEMCPY_TEMPLATE = """
(void)memcpy(&__{0}_{1}_start, &__{0}_{1}_rom_start,
(uint32_t) &__{0}_{1}_size);
z_early_memcpy(&__{0}_{1}_start, &__{0}_{1}_rom_start,
(size_t) &__{0}_{1}_size);
"""
MEMSET_TEMPLATE = """
(void)memset(&__{0}_bss_start, 0,
(uint32_t) &__{0}_bss_size);
z_early_memset(&__{0}_bss_start, 0,
(size_t) &__{0}_bss_size);
"""