Skip to content

Commit e3d4e9f

Browse files
committed
cleanup: address RISC-V32 QEMU demo review feedback
Rework PR #513 according to reviewer feedback while keeping the QEMU virt demo and GP relaxation pieces: - Restore the RISC-V32 GNU port src/inc baseline to upstream style, removing the tx_port.h-based assembly macro abstraction. - Revert the demo thread_2 priority back to (16, 16) and keep preemption verification in the Python runner instead of encoding it in demo priorities. - Document the QEMU entry stub, linker layout, x3/gp initialization, and __global_pointer$ placement used by GP relaxation. - Drop the tx_port.h dependency from the QEMU low-level init assembly. - Move kernel.elf and check-functional-riscv32 CMake wiring out of the root CMakeLists.txt and into the RISC-V32 GNU port example_build tree. - Document why -mrelax requires matching runtime gp setup and linker script support.
1 parent ae2aa03 commit e3d4e9f

16 files changed

Lines changed: 1031 additions & 1078 deletions

CMakeLists.txt

Lines changed: 1 addition & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -69,49 +69,4 @@ set(CPACK_SOURCE_IGNORE_FILES
6969
".*~$"
7070
)
7171
set(CPACK_VERBATIM_VARIABLES YES)
72-
include(CPack)
73-
74-
# Enable the QEMU Virt demo application (Target: kernel.elf)
75-
set(QEMU_DEMO_DIR ${CMAKE_CURRENT_LIST_DIR}/ports/risc-v32/gnu/example_build/qemu_virt)
76-
77-
add_executable(kernel.elf
78-
${QEMU_DEMO_DIR}/demo_threadx.c
79-
${QEMU_DEMO_DIR}/entry.s
80-
${QEMU_DEMO_DIR}/uart.c
81-
${QEMU_DEMO_DIR}/plic.c
82-
${QEMU_DEMO_DIR}/hwtimer.c
83-
${QEMU_DEMO_DIR}/trap.c
84-
${QEMU_DEMO_DIR}/board.c
85-
${QEMU_DEMO_DIR}/tx_initialize_low_level.S
86-
)
87-
88-
target_link_libraries(kernel.elf PRIVATE threadx)
89-
90-
target_include_directories(kernel.elf PRIVATE
91-
${CMAKE_CURRENT_LIST_DIR}/common/inc
92-
${CMAKE_CURRENT_LIST_DIR}/ports/${THREADX_ARCH}/${THREADX_TOOLCHAIN}/inc
93-
${QEMU_DEMO_DIR}
94-
)
95-
96-
# Linker options
97-
target_link_options(kernel.elf PRIVATE
98-
-T${QEMU_DEMO_DIR}/link.lds
99-
-nostartfiles
100-
-Wl,-Map=kernel.map
101-
)
102-
103-
# QEMU Test Runner Target
104-
find_package(Python3 COMPONENTS Interpreter)
105-
if(Python3_FOUND)
106-
add_custom_target(check-functional-riscv32
107-
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/test/ports/azrtos_test_tx_gnu_riscv32_qemu.py
108-
--elf $<TARGET_FILE:kernel.elf>
109-
--qemu qemu-system-riscv32
110-
--gdb gdb
111-
DEPENDS kernel.elf
112-
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
113-
COMMENT "Running QEMU/GDB Test Runner..."
114-
)
115-
else()
116-
message(WARNING "Python3 not found, run_qemu_test target will not be available.")
117-
endif()
72+
include(CPack)

cmake/riscv32_gnu.cmake

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ set(CMAKE_SYSTEM_PROCESSOR risc-v32)
44

55
set(THREADX_ARCH "risc-v32")
66
set(THREADX_TOOLCHAIN "gnu")
7+
# -mrelax enables linker relaxation, in particular GP-relative
8+
# addressing for symbols within +/- 2 KiB of __global_pointer$ (small
9+
# data window). This requires the runtime to load the global pointer
10+
# explicitly under .option norelax (see entry.s in the QEMU virt demo)
11+
# and the linker script to PROVIDE __global_pointer$ centred in the
12+
# small-data window (see link.lds). Without those two pieces in place
13+
# -mrelax produces broken GP-relative loads on bare-metal targets.
714
set(ARCH_FLAGS "-g -march=rv32gc -mabi=ilp32d -mcmodel=medany -mrelax")
815
set(CFLAGS "${ARCH_FLAGS}")
916
set(ASFLAGS "${ARCH_FLAGS}")

ports/risc-v32/gnu/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,11 @@ target_include_directories(${PROJECT_NAME}
1717
PUBLIC
1818
${CMAKE_CURRENT_LIST_DIR}/inc
1919
)
20+
21+
# Optional: pull in the QEMU virt demo if its CMakeLists is present.
22+
# kernel.elf is EXCLUDE_FROM_ALL inside, so the default build is
23+
# unaffected; consumers opt in via `--target kernel.elf` or
24+
# `--target check-functional-riscv32`.
25+
if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/example_build/qemu_virt/CMakeLists.txt)
26+
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/example_build/qemu_virt)
27+
endif()
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# ThreadX RISC-V32 GNU port: QEMU virt demo build.
2+
#
3+
# This subdirectory is opted-in by ports/risc-v32/gnu/CMakeLists.txt when
4+
# the consumer is building the threadx library for the risc-v32/gnu port.
5+
#
6+
# kernel.elf is marked EXCLUDE_FROM_ALL so that:
7+
# - The default `cmake --build .` (which builds the threadx library
8+
# and any tests the consumer wires up) is unaffected by the demo.
9+
# - Users who explicitly want the demo can `cmake --build .
10+
# --target kernel.elf` or `cmake --build . --target
11+
# check-functional-riscv32` to also drive the QEMU/GDB test runner.
12+
#
13+
# This avoids touching the root CMakeLists.txt while still keeping the
14+
# build-system entry point for the demo discoverable next to the demo
15+
# sources themselves.
16+
17+
set(QEMU_DEMO_DIR ${CMAKE_CURRENT_LIST_DIR})
18+
19+
add_executable(kernel.elf EXCLUDE_FROM_ALL
20+
${QEMU_DEMO_DIR}/demo_threadx.c
21+
${QEMU_DEMO_DIR}/entry.s
22+
${QEMU_DEMO_DIR}/uart.c
23+
${QEMU_DEMO_DIR}/plic.c
24+
${QEMU_DEMO_DIR}/hwtimer.c
25+
${QEMU_DEMO_DIR}/trap.c
26+
${QEMU_DEMO_DIR}/board.c
27+
${QEMU_DEMO_DIR}/tx_initialize_low_level.S
28+
)
29+
30+
target_link_libraries(kernel.elf PRIVATE threadx)
31+
32+
target_include_directories(kernel.elf PRIVATE
33+
${CMAKE_SOURCE_DIR}/common/inc
34+
${CMAKE_SOURCE_DIR}/ports/${THREADX_ARCH}/${THREADX_TOOLCHAIN}/inc
35+
${QEMU_DEMO_DIR}
36+
)
37+
38+
target_link_options(kernel.elf PRIVATE
39+
-T${QEMU_DEMO_DIR}/link.lds
40+
-nostartfiles
41+
-Wl,-Map=kernel.map
42+
)
43+
44+
# QEMU/GDB functional test runner. Optional: skipped silently if the
45+
# host has no Python 3 interpreter on PATH.
46+
find_package(Python3 COMPONENTS Interpreter)
47+
if(Python3_FOUND)
48+
add_custom_target(check-functional-riscv32
49+
COMMAND ${Python3_EXECUTABLE}
50+
${QEMU_DEMO_DIR}/test/azrtos_test_tx_gnu_riscv32_qemu.py
51+
--elf $<TARGET_FILE:kernel.elf>
52+
--qemu qemu-system-riscv32
53+
--gdb gdb
54+
DEPENDS kernel.elf
55+
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
56+
COMMENT "Running RISC-V32 QEMU/GDB functional test runner..."
57+
)
58+
else()
59+
message(STATUS
60+
"Python3 not found; check-functional-riscv32 target unavailable.")
61+
endif()

ports/risc-v32/gnu/example_build/qemu_virt/demo_threadx.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
#define DEMO_BLOCK_POOL_SIZE 100
1111
#define DEMO_QUEUE_SIZE 100
1212

13+
/* Shared FPU register exercised by thread_6/7 to validate FP context save/restore. */
14+
float fpu_test_val = 0.0f;
15+
1316
char *_to_str(ULONG val)
1417
{
1518
static char buf[11]; /* 10 digits max + '\0' */
@@ -112,7 +115,7 @@ void tx_application_define(void *first_unused_memory)
112115

113116
tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2,
114117
pointer, DEMO_STACK_SIZE,
115-
10, 10, 4, TX_AUTO_START);
118+
16, 16, 4, TX_AUTO_START);
116119

117120
/* Allocate the stack for thread 3. */
118121
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
@@ -337,8 +340,6 @@ ULONG actual_flags;
337340
}
338341
}
339342

340-
float fpu_test_val = 0.0f;
341-
342343
void thread_6_and_7_entry(ULONG thread_input)
343344
{
344345

ports/risc-v32/gnu/example_build/qemu_virt/entry.s

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,30 @@
1+
/**************************************************************************/
2+
/* */
3+
/* Copyright (c) Microsoft Corporation. All rights reserved. */
4+
/* */
5+
/* This software is licensed under the Microsoft Software License */
6+
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
7+
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8+
/* and in the root directory of this software. */
9+
/* */
10+
/**************************************************************************/
11+
12+
/*
13+
* ThreadX RISC-V32 GNU port: QEMU virt machine reset/entry stub.
14+
*
15+
* Linked at the load address of the QEMU `virt` machine (see link.lds).
16+
* Placed in the .init section so the linker keeps it at the very start
17+
* of the image regardless of file ordering during link, matching the
18+
* PC value QEMU uses on reset.
19+
*
20+
* Responsibilities:
21+
* 1. Park secondary harts on `wfi` (single-hart bring-up only; SMP TBD).
22+
* 2. Zero the integer register file on the boot hart, including x3
23+
* (the global pointer) which we load explicitly with the linker
24+
* symbol `__global_pointer$` below, with relaxation disabled so
25+
* the `la gp, ...` itself is not subject to GP-relative rewriting.
26+
* 3. Set up the system stack and clear .bss before calling main().
27+
*/
128

229
.section .init
330
.align 4
@@ -9,11 +36,13 @@
936
_start:
1037
csrr t0, mhartid
1138
bne t0, zero, 1f
39+
40+
/* Zero general purpose registers (x3/gp handled by the la below). */
1241
li x1, 0
1342
li x2, 0
1443
.option push
1544
.option norelax
16-
la gp, __global_pointer$
45+
la gp, __global_pointer$ /* x3 = gp; norelax keeps this load absolute */
1746
.option pop
1847
li x4, 0
1948
li x5, 0
@@ -43,19 +72,24 @@ _start:
4372
li x29, 0
4473
li x30, 0
4574
li x31, 0
46-
la t0, _sysstack_start
47-
li t1, 0x1000
75+
76+
/* Set up the system stack: top-of-stack = _sysstack_start + 0x1000. */
77+
la t0, _sysstack_start
78+
li t1, 0x1000
4879
add sp, t0, t1
80+
81+
/* Clear .bss [_bss_start, _bss_end). */
4982
la t0, _bss_start
5083
la t1, _bss_end
5184
_bss_clean_start:
5285
bgeu t0, t1, _bss_clean_end
53-
sb zero, 0(t0)
86+
sb zero, 0(t0)
5487
addi t0, t0, 1
55-
j _bss_clean_start
88+
j _bss_clean_start
5689
_bss_clean_end:
5790
call main
91+
5892
1:
59-
/* todo smp */
93+
/* Secondary harts: park here. SMP bring-up is not yet supported. */
6094
wfi
6195
j 1b

ports/risc-v32/gnu/example_build/qemu_virt/link.lds

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,31 @@
1+
/*
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the Microsoft Software License Terms for Microsoft
4+
* Azure RTOS. Full text of the license can be found in the LICENSE
5+
* file at https://aka.ms/AzureRTOS_EULA.
6+
*
7+
* ThreadX RISC-V32 GNU port: linker script for the QEMU `virt` machine.
8+
*
9+
* - Image base 0x80000000 matches the PC QEMU sets when launched with
10+
* `-machine virt -kernel kernel.elf` (DRAM start on this machine).
11+
* - .init is placed first so entry.s / _start is the very first
12+
* instruction the CPU executes after reset.
13+
* - __global_pointer$ is provided at the start of .data + 0x800 so
14+
* that GP-relative loads/stores reach symbols in [GP-0x800, GP+0x7FF],
15+
* the standard small-data window that `-mrelax` uses (see entry.s
16+
* for the matching `la gp, __global_pointer$` initialization).
17+
* - A 4 KiB system stack is reserved after .bss, with _sysstack_start
18+
* consumed by entry.s as the boot stack base.
19+
*/
20+
121
OUTPUT_ARCH( "riscv" )
222
ENTRY( _start )
323

424
SECTIONS
525
{
6-
/*
7-
* ensure that entry.S / _entry is at 0x80000000,
8-
* where qemu's -kernel jumps.
9-
*/
26+
/* QEMU virt: -kernel jumps to 0x80000000 (DRAM start). */
1027
. = 0x80000000;
11-
28+
1229
.init : {
1330
KEEP (*(.init))
1431
}
@@ -28,6 +45,8 @@ SECTIONS
2845

2946
.data : {
3047
. = ALIGN(16);
48+
/* Centre __global_pointer$ in the small-data window so the +/-2 KiB
49+
reach of GP-relative addressing covers the .sdata/.sbss area. */
3150
PROVIDE( __global_pointer$ = . + 0x800 );
3251
*(.sdata .sdata.*) /* do not need to distinguish this from .data */
3352
. = ALIGN(16);
@@ -36,7 +55,7 @@ SECTIONS
3655

3756
.bss : {
3857
. = ALIGN(16);
39-
_bss_start = .;
58+
_bss_start = .; /* consumed by entry.s for .bss zero-init */
4059
*(.sbss .sbss.*) /* do not need to distinguish this from .bss */
4160
. = ALIGN(16);
4261
*(.bss .bss.*)
@@ -45,8 +64,8 @@ SECTIONS
4564

4665
.stack : {
4766
. = ALIGN(4096);
48-
_sysstack_start = .;
49-
. += 0x1000;
67+
_sysstack_start = .; /* boot stack base used by entry.s */
68+
. += 0x1000; /* 4 KiB system stack */
5069
_sysstack_end = .;
5170
}
5271

0 commit comments

Comments
 (0)