arch/riscv: support CONFIG_CODE_DATA_RELOCATION

This implements support for relocating code to chosen memory regions via
the `zephyr_code_relocate` CMake function for RISC-V SoCs. ARM-specific
assumptions that were made by gen_relocate_app.py need to be corrected,
in particular not assuming any particular name for the default RAM
section (which is 'SRAM' for most ARM pltaforms) and not assuming 32-bit
pointers (so the test works on RV64).

Signed-off-by: Peter Marheine <pmarheine@chromium.org>
This commit is contained in:
Peter Marheine 2022-08-19 15:29:10 +10:00 committed by Carles Cufí
commit d400b8135c
11 changed files with 151 additions and 59 deletions

View file

@ -8,16 +8,22 @@ project(code_relocation)
FILE(GLOB app_sources src/*.c)
target_sources(app PRIVATE ${app_sources})
if (CONFIG_ARM)
set(RAM_SECTION SRAM)
else()
set(RAM_SECTION RAM)
endif()
# Code relocation feature
zephyr_code_relocate(src/test_file1.c SRAM2)
zephyr_code_relocate(src/test_file2.c SRAM)
zephyr_code_relocate(src/test_file2.c ${RAM_SECTION})
zephyr_code_relocate(src/test_file3.c SRAM2_TEXT)
zephyr_code_relocate(src/test_file3.c SRAM_DATA)
zephyr_code_relocate(src/test_file3.c ${RAM_SECTION}_DATA)
zephyr_code_relocate(src/test_file3.c SRAM2_BSS)
zephyr_code_relocate(../../../kernel/sem.c SRAM)
zephyr_code_relocate(../../../kernel/sem.c ${RAM_SECTION})
if (CONFIG_RELOCATE_TO_ITCM)
zephyr_code_relocate(../../../lib/libc/minimal/source/string/string.c ITCM_TEXT)

View file

@ -3,6 +3,5 @@
config RELOCATE_TO_ITCM
bool "test with code relocate to itcm"
default y
source "Kconfig.zephyr"

View file

@ -0,0 +1,34 @@
/*
* Copyright 2022 The Chromium OS Authors
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief Linker command/script file
*
* Linker script for the Cortex-M platforms.
*/
#include <zephyr/linker/sections.h>
#include <zephyr/devicetree.h>
#include <zephyr/linker/linker-defs.h>
#include <zephyr/linker/linker-tool.h>
/** enable CONFIG_SRAM2 or any other partition in soc Kconfig,
* this is just an example to show relocation of code/data/bss script
*/
#define _SRAM2_DATA_SECTION_NAME .sram2_data
#define _SRAM2_BSS_SECTION_NAME .sram2_bss
#define _SRAM2_TEXT_SECTION_NAME .sram2_text
#define SRAM2_ADDR (CONFIG_SRAM_BASE_ADDRESS + RAM_SIZE2)
#define RAM_SIZE2 (CONFIG_SRAM_SIZE * 512)
MEMORY
{
SRAM2 (wx) : ORIGIN = (CONFIG_SRAM_BASE_ADDRESS + RAM_SIZE2), LENGTH = RAM_SIZE2
}
#include <zephyr/arch/riscv/common/linker.ld>

View file

@ -0,0 +1,5 @@
CONFIG_CODE_DATA_RELOCATION=y
CONFIG_ZTEST=y
CONFIG_ZTEST_NEW_API=y
CONFIG_HAVE_CUSTOM_LINKER_SCRIPT=y
CONFIG_CUSTOM_LINKER_SCRIPT="linker_riscv_qemu_sram2.ld"

View file

@ -8,28 +8,35 @@
#include <zephyr/sys/printk.h>
#include <zephyr/ztest.h>
uint32_t var_sram2_data = 10U;
uint32_t var_sram2_bss;
/*
* These values will typically be placed in the appropriate sections, but may be moved around
* by the compiler; for instance var_sram2_data might end up in .rodata if the compiler can prove
* that it's never modified. To prevent that, we explicitly specify sections.
*/
__in_section(data, sram2, var) uint32_t var_sram2_data = 10U;
__in_section(bss, sram2, var) uint32_t var_sram2_bss;
K_SEM_DEFINE(test, 0, 1);
const uint32_t var_sram2_rodata = 100U;
__in_section(rodata, sram2, var) const uint32_t var_sram2_rodata = 100U;
__in_section(custom_section, static, var) uint32_t var_custom_data = 1U;
extern void function_in_sram(int32_t value);
void function_in_custom_section(void);
#define HAS_SRAM2_DATA_SECTION (CONFIG_ARM)
ZTEST(code_relocation, test_function_in_sram2)
{
extern uint32_t __sram2_text_start;
extern uint32_t __sram2_text_end;
extern uint32_t __sram2_data_start;
extern uint32_t __sram2_data_end;
extern uint32_t __sram2_bss_start;
extern uint32_t __sram2_bss_end;
extern uint32_t __sram2_rodata_start;
extern uint32_t __sram2_rodata_end;
extern uint32_t __custom_section_start;
extern uint32_t __custom_section_end;
extern uintptr_t __sram2_text_start;
extern uintptr_t __sram2_text_end;
extern uintptr_t __sram2_data_start;
extern uintptr_t __sram2_data_end;
extern uintptr_t __sram2_bss_start;
extern uintptr_t __sram2_bss_end;
extern uintptr_t __sram2_rodata_start;
extern uintptr_t __sram2_rodata_end;
extern uintptr_t __custom_section_start;
extern uintptr_t __custom_section_end;
/* Print values from sram2 */
printk("Address of var_sram2_data %p\n", &var_sram2_data);
@ -37,21 +44,21 @@ ZTEST(code_relocation, test_function_in_sram2)
printk("Address of var_sram2_rodata %p\n", &var_sram2_rodata);
printk("Address of var_sram2_bss %p\n\n", &var_sram2_bss);
zassert_between_inclusive((uint32_t)&var_sram2_data,
(uint32_t)&__sram2_data_start,
(uint32_t)&__sram2_data_end,
zassert_between_inclusive((uintptr_t)&var_sram2_data,
(uintptr_t)&__sram2_data_start,
(uintptr_t)&__sram2_data_end,
"var_sram2_data not in sram2 region");
zassert_between_inclusive((uint32_t)&k_sem_give,
(uint32_t)&__sram2_text_start,
(uint32_t)&__sram2_text_end,
zassert_between_inclusive((uintptr_t)&k_sem_give,
(uintptr_t)&__sram2_text_start,
(uintptr_t)&__sram2_text_end,
"k_sem_give not in sram_text region");
zassert_between_inclusive((uint32_t)&var_sram2_rodata,
(uint32_t)&__sram2_rodata_start,
(uint32_t)&__sram2_rodata_end,
zassert_between_inclusive((uintptr_t)&var_sram2_rodata,
(uintptr_t)&__sram2_rodata_start,
(uintptr_t)&__sram2_rodata_end,
"var_sram2_rodata not in sram2_rodata region");
zassert_between_inclusive((uint32_t)&var_sram2_bss,
(uint32_t)&__sram2_bss_start,
(uint32_t)&__sram2_bss_end,
zassert_between_inclusive((uintptr_t)&var_sram2_bss,
(uintptr_t)&__sram2_bss_start,
(uintptr_t)&__sram2_bss_end,
"var_sram2_bss not in sram2_bss region");
/* Print values from sram */
@ -62,13 +69,13 @@ ZTEST(code_relocation, test_function_in_sram2)
&function_in_custom_section);
printk("Address of custom_section data placed using attributes %p\n\n",
&var_custom_data);
zassert_between_inclusive((uint32_t)&function_in_custom_section,
(uint32_t)&__custom_section_start,
(uint32_t)&__custom_section_end,
zassert_between_inclusive((uintptr_t)&function_in_custom_section,
(uintptr_t)&__custom_section_start,
(uintptr_t)&__custom_section_end,
"function_in_custom_section not in custom_section region");
zassert_between_inclusive((uint32_t)&var_custom_data,
(uint32_t)&__custom_section_start,
(uint32_t)&__custom_section_end,
zassert_between_inclusive((uintptr_t)&var_custom_data,
(uintptr_t)&__custom_section_start,
(uintptr_t)&__custom_section_end,
"var_custom_data not in custom_section region");
k_sem_give(&test);

View file

@ -8,25 +8,25 @@
#include <zephyr/sys/printk.h>
#include <zephyr/ztest.h>
uint32_t var_file3_sram_data = 10U;
uint32_t var_file3_sram2_bss;
__in_section(data, sram, var) uint32_t var_file3_sram_data = 10U;
__in_section(bss, sram2, var) uint32_t var_file3_sram2_bss;
ZTEST(code_relocation, test_function_in_split_multiple)
{
extern uint32_t __data_start;
extern uint32_t __data_end;
extern uint32_t __sram2_bss_start;
extern uint32_t __sram2_bss_end;
extern uintptr_t __data_start;
extern uintptr_t __data_end;
extern uintptr_t __sram2_bss_start;
extern uintptr_t __sram2_bss_end;
printk("Address of var_file3_sram_data %p\n", &var_file3_sram_data);
printk("Address of var_file3_sram2_bss %p\n\n", &var_file3_sram2_bss);
zassert_between_inclusive((uint32_t)&var_file3_sram_data,
(uint32_t)&__data_start,
(uint32_t)&__data_end,
zassert_between_inclusive((uintptr_t)&var_file3_sram_data,
(uintptr_t)&__data_start,
(uintptr_t)&__data_end,
"var_file3_sram_data not in sram_data region");
zassert_between_inclusive((uint32_t)&var_file3_sram2_bss,
(uint32_t)&__sram2_bss_start,
(uint32_t)&__sram2_bss_end,
zassert_between_inclusive((uintptr_t)&var_file3_sram2_bss,
(uintptr_t)&__sram2_bss_start,
(uintptr_t)&__sram2_bss_end,
"var_file3_sram2_bss not in sram2_bss region");
}

View file

@ -1,19 +1,22 @@
common:
arch_allow: arm
tags: linker
tests:
tests.application_development.code_relocation:
filter: not CONFIG_CPU_HAS_NXP_MPU and CONFIG_MINIMAL_LIBC and dt_chosen_enabled("zephyr,itcm")
arch_allow: arm
extra_configs:
- CONFIG_RELOCATE_TO_ITCM=y
tests.application_development.code_relocation_kinetis:
filter: CONFIG_CPU_HAS_NXP_MPU and CONFIG_MINIMAL_LIBC and dt_chosen_enabled("zephyr,itcm")
arch_allow: arm
extra_configs:
- CONFIG_RELOCATE_TO_ITCM=y
- CONFIG_MPU_ALLOW_FLASH_WRITE=y
tests.application_development.code_relocation.no_itcm:
filter: not CONFIG_CPU_HAS_NXP_MPU and not dt_chosen_enabled("zephyr,itcm")
extra_configs:
- CONFIG_RELOCATE_TO_ITCM=n
arch_allow: arm
extra_sections: _SRAM2_RODATA_SECTION_NAME _SRAM_TEXT_SECTION_NAME _SRAM_RODATA_SECTION_NAME _SRAM_DATA_SECTION_NAME _CUSTOM_SECTION_NAME2
platform_allow: qemu_cortex_m3 mps2_an385 sam_e70_xplained
tests.application_development.code_relocation.riscv:
extra_args: CONF_FILE="prj_riscv.conf"
platform_allow: qemu_riscv32 qemu_riscv64