Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions arch/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ config RISCV
select ARCH_IS_SET
select HAS_DTS
select ARCH_SUPPORTS_COREDUMP
select ARCH_HAS_CODE_DATA_RELOCATION
select ARCH_HAS_THREAD_LOCAL_STORAGE
select IRQ_OFFLOAD_NESTED if IRQ_OFFLOAD
select USE_SWITCH_SUPPORTED
Expand Down
9 changes: 9 additions & 0 deletions cmake/linker/ld/target_relocation.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ macro(toolchain_ld_relocation)
set(MEM_RELOCATION_SRAM_BSS_LD
"${PROJECT_BINARY_DIR}/include/generated/linker_sram_bss_relocate.ld")
set(MEM_RELOCATION_CODE "${PROJECT_BINARY_DIR}/code_relocation.c")
if(CONFIG_ARM)
set(MEM_REGION_DEFAULT_RAM SRAM)
elseif(CONFIG_RISCV)
set(MEM_REGION_DEFAULT_RAM RAM)
else()
# Name must be configured for newly-supported architectures
message(SEND_ERROR "Default RAM region name is unknown for target architecture")
endif()

add_custom_command(
OUTPUT ${MEM_RELOCATION_CODE} ${MEM_RELOCATION_LD}
Expand All @@ -22,6 +30,7 @@ macro(toolchain_ld_relocation)
-s ${MEM_RELOCATION_SRAM_DATA_LD}
-b ${MEM_RELOCATION_SRAM_BSS_LD}
-c ${MEM_RELOCATION_CODE}
--default_ram_region ${MEM_REGION_DEFAULT_RAM}
DEPENDS app kernel ${ZEPHYR_LIBS_PROPERTY}
)

Expand Down
14 changes: 14 additions & 0 deletions include/zephyr/arch/riscv/common/linker.ld
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@ SECTIONS
#include <snippets-rom-start.ld>
} GROUP_LINK_IN(ROMABLE_REGION)

#ifdef CONFIG_CODE_DATA_RELOCATION
#include <linker_relocate.ld>
#endif

SECTION_PROLOGUE(_RESET_SECTION_NAME,,)
{
KEEP(*(.reset.*))
Expand Down Expand Up @@ -246,6 +250,11 @@ SECTIONS
*(.bss)
*(".bss.*")
COMMON_SYMBOLS

#ifdef CONFIG_CODE_DATA_RELOCATION
#include <linker_sram_bss_relocate.ld>
#endif

/*
* As memory is cleared in words only, it is simpler to ensure the BSS
* section ends on a 4 byte boundary. This wastes a maximum of 3 bytes.
Expand Down Expand Up @@ -287,6 +296,11 @@ SECTIONS
* zephyr_linker_sources() Cmake function.
*/
#include <snippets-rwdata.ld>

#ifdef CONFIG_CODE_DATA_RELOCATION
#include <linker_sram_data_relocate.ld>
#endif

__data_end = .;

} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
Expand Down
32 changes: 23 additions & 9 deletions scripts/build/gen_relocate_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
from elftools.elf.elffile import ELFFile
from elftools.elf.sections import SymbolTableSection

# This script will create linker commands for text,rodata data, bss section relocation

PRINT_TEMPLATE = """
KEEP(*({0}))
Expand Down Expand Up @@ -154,6 +153,19 @@
"""


def region_is_default_ram(region_name: str) -> bool:
"""
Test whether a memory region with the given name is the system's default
RAM region or not.

This is used to determine whether some items need to be omitted from
custom regions and instead be placed in the default. In particular, mutable
data placed in the default RAM section is ignored and is allowed to be
handled normally by the linker because it is placed in that region anyway.
"""
return region_name == args.default_ram_region


def find_sections(filename, full_list_of_sections):
with open(filename, 'rb') as obj_file_desc:
full_lib = ELFFile(obj_file_desc)
Expand Down Expand Up @@ -258,18 +270,18 @@ def string_create_helper(region, memory_type,
# Create a complete list of funcs/ variables that goes in for this
# memory type
tmp = print_linker_sections(full_list_of_sections[region])
if memory_type == 'SRAM' and region in {'data', 'bss'}:
if region_is_default_ram(memory_type) and region in {'data', 'bss'}:
linker_string += tmp
else:
if memory_type != 'SRAM' and region == 'rodata':
if not region_is_default_ram(memory_type) and region == 'rodata':
align_size = 0
if memory_type in mpu_align:
align_size = mpu_align[memory_type]

linker_string += LINKER_SECTION_SEQ_MPU.format(memory_type.lower(), region, memory_type.upper(),
region.upper(), tmp, load_address_string, align_size)
else:
if memory_type == 'SRAM' and region == 'text':
if region_is_default_ram(memory_type) and region == 'text':
align_size = 0
linker_string += LINKER_SECTION_SEQ_MPU.format(memory_type.lower(), region, memory_type.upper(),
region.upper(), tmp, load_address_string, align_size)
Expand All @@ -293,16 +305,16 @@ def generate_linker_script(linker_file, sram_data_linker_file, sram_bss_linker_f
is_copy = bool("|COPY" in memory_type)
memory_type = memory_type.split("|", 1)[0]

if memory_type != "SRAM" and is_copy:
if region_is_default_ram(memory_type) and is_copy:
gen_string += MPU_RO_REGION_START.format(memory_type.lower(), memory_type.upper())

gen_string += string_create_helper("text", memory_type, full_list_of_sections, 1, is_copy)
gen_string += string_create_helper("rodata", memory_type, full_list_of_sections, 1, is_copy)

if memory_type != "SRAM" and is_copy:
if region_is_default_ram(memory_type) and is_copy:
gen_string += MPU_RO_REGION_END.format(memory_type.lower())

if memory_type == 'SRAM':
if region_is_default_ram(memory_type):
gen_string_sram_data += string_create_helper("data", memory_type, full_list_of_sections, 1, 1)
gen_string_sram_bss += string_create_helper("bss", memory_type, full_list_of_sections, 0, 1)
else:
Expand Down Expand Up @@ -337,7 +349,7 @@ def generate_memcpy_code(memory_type, full_list_of_sections, code_generation):

# add all the regions that needs to be copied on boot up
for mtype in ["text", "rodata", "data"]:
if memory_type == "SRAM" and mtype == "data":
if region_is_default_ram(memory_type) and mtype == "data":
continue

if full_list_of_sections[mtype] and generate_section[mtype]:
Expand All @@ -346,7 +358,7 @@ def generate_memcpy_code(memory_type, full_list_of_sections, code_generation):
memory_type.lower(), mtype)

# add for all the bss data that needs to be zeroed on boot up
if full_list_of_sections["bss"] and generate_section["bss"] and memory_type != "SRAM":
if full_list_of_sections["bss"] and generate_section["bss"] and not region_is_default_ram(memory_type):
code_generation["zero_code"] += MEMSET_TEMPLATE.format(memory_type.lower())
code_generation["extern"] += EXTERN_LINKER_VAR_DECLARATION.format(
memory_type.lower(), "bss")
Expand Down Expand Up @@ -391,6 +403,8 @@ def parse_args():
help="Output sram bss ld file")
parser.add_argument("-c", "--output_code", required=False,
help="Output relocation code header file")
parser.add_argument("-R", "--default_ram_region", default='SRAM',
help="Name of default RAM memory region for system")
parser.add_argument("-v", "--verbose", action="count", default=0,
help="Verbose Output")
args = parser.parse_args()
Expand Down
12 changes: 9 additions & 3 deletions tests/application_development/code_relocation/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 0 additions & 1 deletion tests/application_development/code_relocation/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,5 @@

config RELOCATE_TO_ITCM
bool "test with code relocate to itcm"
default y

source "Kconfig.zephyr"
Original file line number Diff line number Diff line change
@@ -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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cortex-M?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hah, oops. I've added a commit to #49438 that fixes this.

*/

#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>
5 changes: 5 additions & 0 deletions tests/application_development/code_relocation/prj_riscv.conf
Original file line number Diff line number Diff line change
@@ -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"
69 changes: 38 additions & 31 deletions tests/application_development/code_relocation/src/test_file1.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,50 +8,57 @@
#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);
printk("Address of k_sem_give %p\n", &k_sem_give);
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 */
Expand All @@ -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);
Expand Down
24 changes: 12 additions & 12 deletions tests/application_development/code_relocation/src/test_file3.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
Loading