Skip to content

Commit d400b81

Browse files
taricarlescufi
authored andcommitted
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 <[email protected]>
1 parent c30833d commit d400b81

File tree

11 files changed

+151
-59
lines changed

11 files changed

+151
-59
lines changed

arch/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ config RISCV
107107
select ARCH_IS_SET
108108
select HAS_DTS
109109
select ARCH_SUPPORTS_COREDUMP
110+
select ARCH_HAS_CODE_DATA_RELOCATION
110111
select ARCH_HAS_THREAD_LOCAL_STORAGE
111112
select IRQ_OFFLOAD_NESTED if IRQ_OFFLOAD
112113
select USE_SWITCH_SUPPORTED

cmake/linker/ld/target_relocation.cmake

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ macro(toolchain_ld_relocation)
99
set(MEM_RELOCATION_SRAM_BSS_LD
1010
"${PROJECT_BINARY_DIR}/include/generated/linker_sram_bss_relocate.ld")
1111
set(MEM_RELOCATION_CODE "${PROJECT_BINARY_DIR}/code_relocation.c")
12+
if(CONFIG_ARM)
13+
set(MEM_REGION_DEFAULT_RAM SRAM)
14+
elseif(CONFIG_RISCV)
15+
set(MEM_REGION_DEFAULT_RAM RAM)
16+
else()
17+
# Name must be configured for newly-supported architectures
18+
message(SEND_ERROR "Default RAM region name is unknown for target architecture")
19+
endif()
1220

1321
add_custom_command(
1422
OUTPUT ${MEM_RELOCATION_CODE} ${MEM_RELOCATION_LD}
@@ -22,6 +30,7 @@ macro(toolchain_ld_relocation)
2230
-s ${MEM_RELOCATION_SRAM_DATA_LD}
2331
-b ${MEM_RELOCATION_SRAM_BSS_LD}
2432
-c ${MEM_RELOCATION_CODE}
33+
--default_ram_region ${MEM_REGION_DEFAULT_RAM}
2534
DEPENDS app kernel ${ZEPHYR_LIBS_PROPERTY}
2635
)
2736

include/zephyr/arch/riscv/common/linker.ld

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,10 @@ SECTIONS
125125
#include <snippets-rom-start.ld>
126126
} GROUP_LINK_IN(ROMABLE_REGION)
127127

128+
#ifdef CONFIG_CODE_DATA_RELOCATION
129+
#include <linker_relocate.ld>
130+
#endif
131+
128132
SECTION_PROLOGUE(_RESET_SECTION_NAME,,)
129133
{
130134
KEEP(*(.reset.*))
@@ -246,6 +250,11 @@ SECTIONS
246250
*(.bss)
247251
*(".bss.*")
248252
COMMON_SYMBOLS
253+
254+
#ifdef CONFIG_CODE_DATA_RELOCATION
255+
#include <linker_sram_bss_relocate.ld>
256+
#endif
257+
249258
/*
250259
* As memory is cleared in words only, it is simpler to ensure the BSS
251260
* section ends on a 4 byte boundary. This wastes a maximum of 3 bytes.
@@ -287,6 +296,11 @@ SECTIONS
287296
* zephyr_linker_sources() Cmake function.
288297
*/
289298
#include <snippets-rwdata.ld>
299+
300+
#ifdef CONFIG_CODE_DATA_RELOCATION
301+
#include <linker_sram_data_relocate.ld>
302+
#endif
303+
290304
__data_end = .;
291305

292306
} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)

scripts/build/gen_relocate_app.py

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@
4343
from elftools.elf.elffile import ELFFile
4444
from elftools.elf.sections import SymbolTableSection
4545

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

4847
PRINT_TEMPLATE = """
4948
KEEP(*({0}))
@@ -154,6 +153,19 @@
154153
"""
155154

156155

156+
def region_is_default_ram(region_name: str) -> bool:
157+
"""
158+
Test whether a memory region with the given name is the system's default
159+
RAM region or not.
160+
161+
This is used to determine whether some items need to be omitted from
162+
custom regions and instead be placed in the default. In particular, mutable
163+
data placed in the default RAM section is ignored and is allowed to be
164+
handled normally by the linker because it is placed in that region anyway.
165+
"""
166+
return region_name == args.default_ram_region
167+
168+
157169
def find_sections(filename, full_list_of_sections):
158170
with open(filename, 'rb') as obj_file_desc:
159171
full_lib = ELFFile(obj_file_desc)
@@ -258,18 +270,18 @@ def string_create_helper(region, memory_type,
258270
# Create a complete list of funcs/ variables that goes in for this
259271
# memory type
260272
tmp = print_linker_sections(full_list_of_sections[region])
261-
if memory_type == 'SRAM' and region in {'data', 'bss'}:
273+
if region_is_default_ram(memory_type) and region in {'data', 'bss'}:
262274
linker_string += tmp
263275
else:
264-
if memory_type != 'SRAM' and region == 'rodata':
276+
if not region_is_default_ram(memory_type) and region == 'rodata':
265277
align_size = 0
266278
if memory_type in mpu_align:
267279
align_size = mpu_align[memory_type]
268280

269281
linker_string += LINKER_SECTION_SEQ_MPU.format(memory_type.lower(), region, memory_type.upper(),
270282
region.upper(), tmp, load_address_string, align_size)
271283
else:
272-
if memory_type == 'SRAM' and region == 'text':
284+
if region_is_default_ram(memory_type) and region == 'text':
273285
align_size = 0
274286
linker_string += LINKER_SECTION_SEQ_MPU.format(memory_type.lower(), region, memory_type.upper(),
275287
region.upper(), tmp, load_address_string, align_size)
@@ -293,16 +305,16 @@ def generate_linker_script(linker_file, sram_data_linker_file, sram_bss_linker_f
293305
is_copy = bool("|COPY" in memory_type)
294306
memory_type = memory_type.split("|", 1)[0]
295307

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

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

302-
if memory_type != "SRAM" and is_copy:
314+
if region_is_default_ram(memory_type) and is_copy:
303315
gen_string += MPU_RO_REGION_END.format(memory_type.lower())
304316

305-
if memory_type == 'SRAM':
317+
if region_is_default_ram(memory_type):
306318
gen_string_sram_data += string_create_helper("data", memory_type, full_list_of_sections, 1, 1)
307319
gen_string_sram_bss += string_create_helper("bss", memory_type, full_list_of_sections, 0, 1)
308320
else:
@@ -337,7 +349,7 @@ def generate_memcpy_code(memory_type, full_list_of_sections, code_generation):
337349

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

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

348360
# add for all the bss data that needs to be zeroed on boot up
349-
if full_list_of_sections["bss"] and generate_section["bss"] and memory_type != "SRAM":
361+
if full_list_of_sections["bss"] and generate_section["bss"] and not region_is_default_ram(memory_type):
350362
code_generation["zero_code"] += MEMSET_TEMPLATE.format(memory_type.lower())
351363
code_generation["extern"] += EXTERN_LINKER_VAR_DECLARATION.format(
352364
memory_type.lower(), "bss")
@@ -391,6 +403,8 @@ def parse_args():
391403
help="Output sram bss ld file")
392404
parser.add_argument("-c", "--output_code", required=False,
393405
help="Output relocation code header file")
406+
parser.add_argument("-R", "--default_ram_region", default='SRAM',
407+
help="Name of default RAM memory region for system")
394408
parser.add_argument("-v", "--verbose", action="count", default=0,
395409
help="Verbose Output")
396410
args = parser.parse_args()

tests/application_development/code_relocation/CMakeLists.txt

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,22 @@ project(code_relocation)
88
FILE(GLOB app_sources src/*.c)
99
target_sources(app PRIVATE ${app_sources})
1010

11+
if (CONFIG_ARM)
12+
set(RAM_SECTION SRAM)
13+
else()
14+
set(RAM_SECTION RAM)
15+
endif()
16+
1117
# Code relocation feature
1218
zephyr_code_relocate(src/test_file1.c SRAM2)
1319

14-
zephyr_code_relocate(src/test_file2.c SRAM)
20+
zephyr_code_relocate(src/test_file2.c ${RAM_SECTION})
1521

1622
zephyr_code_relocate(src/test_file3.c SRAM2_TEXT)
17-
zephyr_code_relocate(src/test_file3.c SRAM_DATA)
23+
zephyr_code_relocate(src/test_file3.c ${RAM_SECTION}_DATA)
1824
zephyr_code_relocate(src/test_file3.c SRAM2_BSS)
1925

20-
zephyr_code_relocate(../../../kernel/sem.c SRAM)
26+
zephyr_code_relocate(../../../kernel/sem.c ${RAM_SECTION})
2127

2228
if (CONFIG_RELOCATE_TO_ITCM)
2329
zephyr_code_relocate(../../../lib/libc/minimal/source/string/string.c ITCM_TEXT)

tests/application_development/code_relocation/Kconfig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,5 @@
33

44
config RELOCATE_TO_ITCM
55
bool "test with code relocate to itcm"
6-
default y
76

87
source "Kconfig.zephyr"
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright 2022 The Chromium OS Authors
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/**
8+
* @file
9+
* @brief Linker command/script file
10+
*
11+
* Linker script for the Cortex-M platforms.
12+
*/
13+
14+
#include <zephyr/linker/sections.h>
15+
#include <zephyr/devicetree.h>
16+
17+
#include <zephyr/linker/linker-defs.h>
18+
#include <zephyr/linker/linker-tool.h>
19+
20+
/** enable CONFIG_SRAM2 or any other partition in soc Kconfig,
21+
* this is just an example to show relocation of code/data/bss script
22+
*/
23+
#define _SRAM2_DATA_SECTION_NAME .sram2_data
24+
#define _SRAM2_BSS_SECTION_NAME .sram2_bss
25+
#define _SRAM2_TEXT_SECTION_NAME .sram2_text
26+
#define SRAM2_ADDR (CONFIG_SRAM_BASE_ADDRESS + RAM_SIZE2)
27+
28+
#define RAM_SIZE2 (CONFIG_SRAM_SIZE * 512)
29+
MEMORY
30+
{
31+
SRAM2 (wx) : ORIGIN = (CONFIG_SRAM_BASE_ADDRESS + RAM_SIZE2), LENGTH = RAM_SIZE2
32+
}
33+
34+
#include <zephyr/arch/riscv/common/linker.ld>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
CONFIG_CODE_DATA_RELOCATION=y
2+
CONFIG_ZTEST=y
3+
CONFIG_ZTEST_NEW_API=y
4+
CONFIG_HAVE_CUSTOM_LINKER_SCRIPT=y
5+
CONFIG_CUSTOM_LINKER_SCRIPT="linker_riscv_qemu_sram2.ld"

tests/application_development/code_relocation/src/test_file1.c

Lines changed: 38 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -8,50 +8,57 @@
88
#include <zephyr/sys/printk.h>
99
#include <zephyr/ztest.h>
1010

11-
uint32_t var_sram2_data = 10U;
12-
uint32_t var_sram2_bss;
11+
/*
12+
* These values will typically be placed in the appropriate sections, but may be moved around
13+
* by the compiler; for instance var_sram2_data might end up in .rodata if the compiler can prove
14+
* that it's never modified. To prevent that, we explicitly specify sections.
15+
*/
16+
__in_section(data, sram2, var) uint32_t var_sram2_data = 10U;
17+
__in_section(bss, sram2, var) uint32_t var_sram2_bss;
1318
K_SEM_DEFINE(test, 0, 1);
14-
const uint32_t var_sram2_rodata = 100U;
19+
__in_section(rodata, sram2, var) const uint32_t var_sram2_rodata = 100U;
1520

1621
__in_section(custom_section, static, var) uint32_t var_custom_data = 1U;
1722

1823
extern void function_in_sram(int32_t value);
1924
void function_in_custom_section(void);
2025

26+
#define HAS_SRAM2_DATA_SECTION (CONFIG_ARM)
27+
2128
ZTEST(code_relocation, test_function_in_sram2)
2229
{
23-
extern uint32_t __sram2_text_start;
24-
extern uint32_t __sram2_text_end;
25-
extern uint32_t __sram2_data_start;
26-
extern uint32_t __sram2_data_end;
27-
extern uint32_t __sram2_bss_start;
28-
extern uint32_t __sram2_bss_end;
29-
extern uint32_t __sram2_rodata_start;
30-
extern uint32_t __sram2_rodata_end;
31-
extern uint32_t __custom_section_start;
32-
extern uint32_t __custom_section_end;
30+
extern uintptr_t __sram2_text_start;
31+
extern uintptr_t __sram2_text_end;
32+
extern uintptr_t __sram2_data_start;
33+
extern uintptr_t __sram2_data_end;
34+
extern uintptr_t __sram2_bss_start;
35+
extern uintptr_t __sram2_bss_end;
36+
extern uintptr_t __sram2_rodata_start;
37+
extern uintptr_t __sram2_rodata_end;
38+
extern uintptr_t __custom_section_start;
39+
extern uintptr_t __custom_section_end;
3340

3441
/* Print values from sram2 */
3542
printk("Address of var_sram2_data %p\n", &var_sram2_data);
3643
printk("Address of k_sem_give %p\n", &k_sem_give);
3744
printk("Address of var_sram2_rodata %p\n", &var_sram2_rodata);
3845
printk("Address of var_sram2_bss %p\n\n", &var_sram2_bss);
3946

40-
zassert_between_inclusive((uint32_t)&var_sram2_data,
41-
(uint32_t)&__sram2_data_start,
42-
(uint32_t)&__sram2_data_end,
47+
zassert_between_inclusive((uintptr_t)&var_sram2_data,
48+
(uintptr_t)&__sram2_data_start,
49+
(uintptr_t)&__sram2_data_end,
4350
"var_sram2_data not in sram2 region");
44-
zassert_between_inclusive((uint32_t)&k_sem_give,
45-
(uint32_t)&__sram2_text_start,
46-
(uint32_t)&__sram2_text_end,
51+
zassert_between_inclusive((uintptr_t)&k_sem_give,
52+
(uintptr_t)&__sram2_text_start,
53+
(uintptr_t)&__sram2_text_end,
4754
"k_sem_give not in sram_text region");
48-
zassert_between_inclusive((uint32_t)&var_sram2_rodata,
49-
(uint32_t)&__sram2_rodata_start,
50-
(uint32_t)&__sram2_rodata_end,
55+
zassert_between_inclusive((uintptr_t)&var_sram2_rodata,
56+
(uintptr_t)&__sram2_rodata_start,
57+
(uintptr_t)&__sram2_rodata_end,
5158
"var_sram2_rodata not in sram2_rodata region");
52-
zassert_between_inclusive((uint32_t)&var_sram2_bss,
53-
(uint32_t)&__sram2_bss_start,
54-
(uint32_t)&__sram2_bss_end,
59+
zassert_between_inclusive((uintptr_t)&var_sram2_bss,
60+
(uintptr_t)&__sram2_bss_start,
61+
(uintptr_t)&__sram2_bss_end,
5562
"var_sram2_bss not in sram2_bss region");
5663

5764
/* Print values from sram */
@@ -62,13 +69,13 @@ ZTEST(code_relocation, test_function_in_sram2)
6269
&function_in_custom_section);
6370
printk("Address of custom_section data placed using attributes %p\n\n",
6471
&var_custom_data);
65-
zassert_between_inclusive((uint32_t)&function_in_custom_section,
66-
(uint32_t)&__custom_section_start,
67-
(uint32_t)&__custom_section_end,
72+
zassert_between_inclusive((uintptr_t)&function_in_custom_section,
73+
(uintptr_t)&__custom_section_start,
74+
(uintptr_t)&__custom_section_end,
6875
"function_in_custom_section not in custom_section region");
69-
zassert_between_inclusive((uint32_t)&var_custom_data,
70-
(uint32_t)&__custom_section_start,
71-
(uint32_t)&__custom_section_end,
76+
zassert_between_inclusive((uintptr_t)&var_custom_data,
77+
(uintptr_t)&__custom_section_start,
78+
(uintptr_t)&__custom_section_end,
7279
"var_custom_data not in custom_section region");
7380

7481
k_sem_give(&test);

tests/application_development/code_relocation/src/test_file3.c

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,25 @@
88
#include <zephyr/sys/printk.h>
99
#include <zephyr/ztest.h>
1010

11-
uint32_t var_file3_sram_data = 10U;
12-
uint32_t var_file3_sram2_bss;
11+
__in_section(data, sram, var) uint32_t var_file3_sram_data = 10U;
12+
__in_section(bss, sram2, var) uint32_t var_file3_sram2_bss;
1313

1414
ZTEST(code_relocation, test_function_in_split_multiple)
1515
{
16-
extern uint32_t __data_start;
17-
extern uint32_t __data_end;
18-
extern uint32_t __sram2_bss_start;
19-
extern uint32_t __sram2_bss_end;
16+
extern uintptr_t __data_start;
17+
extern uintptr_t __data_end;
18+
extern uintptr_t __sram2_bss_start;
19+
extern uintptr_t __sram2_bss_end;
2020

2121
printk("Address of var_file3_sram_data %p\n", &var_file3_sram_data);
2222
printk("Address of var_file3_sram2_bss %p\n\n", &var_file3_sram2_bss);
2323

24-
zassert_between_inclusive((uint32_t)&var_file3_sram_data,
25-
(uint32_t)&__data_start,
26-
(uint32_t)&__data_end,
24+
zassert_between_inclusive((uintptr_t)&var_file3_sram_data,
25+
(uintptr_t)&__data_start,
26+
(uintptr_t)&__data_end,
2727
"var_file3_sram_data not in sram_data region");
28-
zassert_between_inclusive((uint32_t)&var_file3_sram2_bss,
29-
(uint32_t)&__sram2_bss_start,
30-
(uint32_t)&__sram2_bss_end,
28+
zassert_between_inclusive((uintptr_t)&var_file3_sram2_bss,
29+
(uintptr_t)&__sram2_bss_start,
30+
(uintptr_t)&__sram2_bss_end,
3131
"var_file3_sram2_bss not in sram2_bss region");
3232
}

0 commit comments

Comments
 (0)