Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
20 changes: 20 additions & 0 deletions bsp/qemu-virt64-riscv/SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,25 @@ if GetDepend('__STACKSIZE__'): stack_size = GetDepend('__STACKSIZE__')
stack_lds.write('__STACKSIZE__ = %d;\n' % stack_size)
stack_lds.close()

# Obtain the number of harts from rtconfig.h and write
# it into link_cpus.lds for the linker script
try:
with open('rtconfig.h', 'r') as f:
rtconfig_content = f.readlines()
except FileNotFoundError:
cpus_nr = 1
else:
cpus_nr = 1 # default value
for line in rtconfig_content:
line = line.strip()
if line.startswith('#define') and 'RT_CPUS_NR' in line:
parts = line.split()
if len(parts) >= 3 and parts[2].isdigit():
cpus_nr = int(parts[2])
break

with open('link_cpus.lds', 'w') as cpus_lds:
cpus_lds.write(f'RT_CPUS_NR = {cpus_nr};\n')

# make a building
DoBuilding(TARGET, objs)
9 changes: 9 additions & 0 deletions bsp/qemu-virt64-riscv/driver/board.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
#include "plic.h"
#include "stack.h"

#ifdef RT_USING_SMP
#include "interrupt.h"
#endif /* RT_USING_SMP */

#ifdef RT_USING_SMART
#include "riscv_mmu.h"
#include "mmu.h"
Expand Down Expand Up @@ -89,6 +93,11 @@ void rt_hw_board_init(void)

rt_hw_tick_init();

#ifdef RT_USING_SMP
/* ipi init */
rt_hw_ipi_init();
#endif /* RT_USING_SMP */

#ifdef RT_USING_COMPONENTS_INIT
rt_components_board_init();
#endif
Expand Down
2 changes: 1 addition & 1 deletion bsp/qemu-virt64-riscv/driver/board.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ extern unsigned int __bss_end;
#define RT_HW_HEAP_BEGIN ((void *)&__bss_end)
#define RT_HW_HEAP_END ((void *)(RT_HW_HEAP_BEGIN + 64 * 1024 * 1024))
#define RT_HW_PAGE_START RT_HW_HEAP_END
#define RT_HW_PAGE_END ((void *)(KERNEL_VADDR_START + (256 * 1024 * 1024 - VIRT64_SBI_MEMSZ)))
#define RT_HW_PAGE_END ((void *)(KERNEL_VADDR_START + (128 * 1024 * 1024 - VIRT64_SBI_MEMSZ)))

void rt_hw_board_init(void);
void rt_init_user_mem(struct rt_thread *thread, const char *name,
Expand Down
28 changes: 22 additions & 6 deletions bsp/qemu-virt64-riscv/link.lds
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
*/

INCLUDE "link_stacksize.lds"
INCLUDE "link_cpus.lds"

OUTPUT_ARCH( "riscv" )

Expand Down Expand Up @@ -121,12 +122,9 @@ SECTIONS
{
. = ALIGN(64);
__stack_start__ = .;

. += __STACKSIZE__;
__stack_cpu0 = .;

. += __STACKSIZE__;
__stack_cpu1 = .;
/* Dynamically allocate stack areas according to RT_CPUS_NR */
. += (__STACKSIZE__ * RT_CPUS_NR);
__stack_end__ = .;
} > SRAM

.sbss :
Expand All @@ -138,6 +136,24 @@ SECTIONS
*(.scommon)
} > SRAM

.percpu (NOLOAD) :
{
/* 2MB Align for MMU early map */
. = ALIGN(0x200000);
PROVIDE(__percpu_start = .);

*(.percpu)

/* 2MB Align for MMU early map */
. = ALIGN(0x200000);

PROVIDE(__percpu_end = .);

/* Clone the area */
. = __percpu_end + (__percpu_end - __percpu_start) * (RT_CPUS_NR - 1);
PROVIDE(__percpu_real_end = .);
} > SRAM

.bss :
{
*(.bss)
Expand Down
1 change: 1 addition & 0 deletions bsp/qemu-virt64-riscv/link_cpus.lds
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
RT_CPUS_NR = 8;
Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

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

[nitpick] [Best Practices/最佳实践]: Hardcoded maximum CPUs value in linker script.

English: The value RT_CPUS_NR = 8 is hardcoded in the linker script but may not match the actual RT_CPUS_NR configured in rtconfig.h. While the SConstruct script generates this file, having a default of 8 could be misleading.

中文:值 RT_CPUS_NR = 8 在链接器脚本中硬编码,但可能与 rtconfig.h 中配置的实际 RT_CPUS_NR 不匹配。虽然 SConstruct 脚本生成此文件,但默认值为 8 可能会产生误导。

Suggestion/建议: Add a comment explaining that this file is auto-generated:

/* Auto-generated by SConstruct - do not edit manually */
RT_CPUS_NR = 8;

Or add this to a .gitignore to avoid committing the generated file.

Copilot uses AI. Check for mistakes.
28 changes: 22 additions & 6 deletions bsp/qemu-virt64-riscv/link_smart.lds
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
*/

INCLUDE "link_stacksize.lds"
INCLUDE "link_cpus.lds"

OUTPUT_ARCH( "riscv" )

Expand Down Expand Up @@ -122,12 +123,9 @@ SECTIONS
{
. = ALIGN(64);
__stack_start__ = .;

. += __STACKSIZE__;
__stack_cpu0 = .;

. += __STACKSIZE__;
__stack_cpu1 = .;
/* Dynamically allocate stack areas according to RT_CPUS_NR */
. += (__STACKSIZE__ * RT_CPUS_NR);
__stack_end__ = .;
} > SRAM

.sbss :
Expand All @@ -139,6 +137,24 @@ SECTIONS
*(.scommon)
} > SRAM

.percpu (NOLOAD) :
{
/* 2MB Align for MMU early map */
. = ALIGN(0x200000);
PROVIDE(__percpu_start = .);

*(.percpu)

/* 2MB Align for MMU early map */
. = ALIGN(0x200000);

PROVIDE(__percpu_end = .);

/* Clone the area */
. = __percpu_end + (__percpu_end - __percpu_start) * (RT_CPUS_NR - 1);
PROVIDE(__percpu_real_end = .);
} > SRAM

.bss :
{
*(.bss)
Expand Down
16 changes: 14 additions & 2 deletions bsp/qemu-virt64-riscv/qemu-dbg.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
qemu-system-riscv64 -nographic -machine virt -m 256M -kernel rtthread.bin -s -S \
QEMU_CMD="qemu-system-riscv64 -nographic -machine virt -m 256M -kernel rtthread.bin -s -S"

if grep -q "#define RT_USING_SMP" ./rtconfig.h 2>/dev/null; then
hart_num=$(grep "RT_CPUS_NR = [0-9]*;" ./link_cpus.lds | awk -F'[=;]' '{gsub(/ /, "", $2); print $2}')
if [ -z "$hart_num" ]; then
hart_num=1
fi
QEMU_CMD="$QEMU_CMD -smp $hart_num"
fi

QEMU_CMD="$QEMU_CMD \
-drive if=none,file=sd.bin,format=raw,id=blk0 -device virtio-blk-device,drive=blk0,bus=virtio-mmio-bus.0 \
-netdev user,id=tap0 -device virtio-net-device,netdev=tap0,bus=virtio-mmio-bus.1 \
-device virtio-serial-device -chardev socket,host=127.0.0.1,port=4321,server=on,wait=off,telnet=on,id=console0 -device virtserialport,chardev=console0
-device virtio-serial-device -chardev socket,host=127.0.0.1,port=4321,server=on,wait=off,telnet=on,id=console0 -device virtserialport,chardev=console0"

eval $QEMU_CMD
17 changes: 15 additions & 2 deletions bsp/qemu-virt64-riscv/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,20 @@ if [ ! -f $path_image ]; then
exit
fi

qemu-system-riscv64 -nographic -machine virt -m 256M -kernel rtthread.bin \
QEMU_CMD="qemu-system-riscv64 -nographic -machine virt -m 256M -kernel rtthread.bin"

if grep -q "#define RT_USING_SMP" ./rtconfig.h 2>/dev/null; then
hart_num=$(grep "RT_CPUS_NR = [0-9]*;" ./link_cpus.lds 2>/dev/null | awk -F'[=;]' '{gsub(/ /, "", $2); print $2}')
if [ -z "$hart_num" ] || [ "$hart_num" -lt 1 ]; then
echo "Warning: Invalid or missing RT_CPUS_NR, defaulting to 1"
hart_num=1
fi
QEMU_CMD="$QEMU_CMD -smp $hart_num"
fi

QEMU_CMD="$QEMU_CMD \
-drive if=none,file=$path_image,format=raw,id=blk0 -device virtio-blk-device,drive=blk0,bus=virtio-mmio-bus.0 \
-netdev user,id=tap0 -device virtio-net-device,netdev=tap0,bus=virtio-mmio-bus.1 \
-device virtio-serial-device -chardev socket,host=127.0.0.1,port=4321,server=on,wait=off,telnet=on,id=console0 -device virtserialport,chardev=console0
-device virtio-serial-device -chardev socket,host=127.0.0.1,port=4321,server=on,wait=off,telnet=on,id=console0 -device virtserialport,chardev=console0"

eval $QEMU_CMD
2 changes: 2 additions & 0 deletions libcpu/risc-v/common64/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ CPPPATH = [cwd]
if not GetDepend('ARCH_USING_ASID'):
SrcRemove(src, ['asid.c'])

src.append('../common/atomic_riscv.c')

group = DefineGroup('CPU', src, depend = [''], CPPPATH = CPPPATH)

Return('group')
35 changes: 31 additions & 4 deletions libcpu/risc-v/common64/context_gcc.S
Original file line number Diff line number Diff line change
Expand Up @@ -69,29 +69,47 @@
.endm

/*
* #ifdef RT_USING_SMP
* void rt_hw_context_switch_to(rt_ubase_t to, stuct rt_thread *to_thread);
* #else
* void rt_hw_context_switch_to(rt_ubase_t to);
*
* a0 --> to SP pointer
* #endif
* a0 --> to
* a1 --> to_thread
*/
.globl rt_hw_context_switch_to
rt_hw_context_switch_to:
LOAD sp, (a0)

#ifdef RT_USING_SMP
/* Pass the previous CPU lock status to rt_cpus_lock_status_restore for restoration */
mv a0, a1
call rt_cpus_lock_status_restore
#endif

call rt_thread_self
mv s1, a0

#ifndef RT_USING_SMP
//if enable RT_USING_SMP, it will finished by rt_cpus_lock_status_restore.
#ifdef RT_USING_SMART
Copy link
Member

Choose a reason for hiding this comment

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

这块代码要格式化下,#ifdef前不需要有缩进

call lwp_aspace_switch
call lwp_aspace_switch
#endif
#endif

RESTORE_CONTEXT
sret

/*
* #ifdef RT_USING_SMP
* void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread);
* #else
* void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to);
* #endif
*
* a0 --> from SP pointer
* a1 --> to SP pointer
* a2 --> to_thread
*
* It should only be used on local interrupt disable
*/
Expand All @@ -103,13 +121,22 @@ rt_hw_context_switch:
// restore to thread SP
LOAD sp, (a1)

#ifdef RT_USING_SMP
/* Pass the previous CPU lock status to rt_cpus_lock_status_restore for restoration */
mv a0, a2
call rt_cpus_lock_status_restore
#endif /*RT_USING_SMP*/

// restore Address Space
call rt_thread_self
mv s1, a0

#ifndef RT_USING_SMP
// if enable RT_USING_SMP, it will finished by rt_cpus_lock_status_restore.
#ifdef RT_USING_SMART
call lwp_aspace_switch
call lwp_aspace_switch
#endif
#endif

RESTORE_CONTEXT
sret
Loading