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
159 changes: 159 additions & 0 deletions libcpu/risc-v/common64/atomic_riscv.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-03-14 WangShun first version
*/

#include <rtthread.h>

rt_atomic_t rt_hw_atomic_exchange(volatile rt_atomic_t *ptr, rt_atomic_t val)
{
rt_atomic_t result = 0;
#if __riscv_xlen == 32
asm volatile("amoswap.w %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory");
#elif __riscv_xlen == 64
asm volatile("amoswap.d %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory");
#endif
return result;
}

rt_atomic_t rt_hw_atomic_add(volatile rt_atomic_t *ptr, rt_atomic_t val)
{
rt_atomic_t result = 0;
#if __riscv_xlen == 32
asm volatile("amoadd.w %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory");
#elif __riscv_xlen == 64
asm volatile("amoadd.d %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory");
#endif
return result;
}

rt_atomic_t rt_hw_atomic_sub(volatile rt_atomic_t *ptr, rt_atomic_t val)
{
rt_atomic_t result = 0;
val = -val;
#if __riscv_xlen == 32
asm volatile("amoadd.w %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory");
#elif __riscv_xlen == 64
asm volatile("amoadd.d %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory");
#endif
return result;
}

rt_atomic_t rt_hw_atomic_xor(volatile rt_atomic_t *ptr, rt_atomic_t val)
{
rt_atomic_t result = 0;
#if __riscv_xlen == 32
asm volatile("amoxor.w %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory");
#elif __riscv_xlen == 64
asm volatile("amoxor.d %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory");
#endif
return result;
}

rt_atomic_t rt_hw_atomic_and(volatile rt_atomic_t *ptr, rt_atomic_t val)
{
rt_atomic_t result = 0;
#if __riscv_xlen == 32
asm volatile("amoand.w %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory");
#elif __riscv_xlen == 64
asm volatile("amoand.d %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory");
#endif
return result;
}

rt_atomic_t rt_hw_atomic_or(volatile rt_atomic_t *ptr, rt_atomic_t val)
{
rt_atomic_t result = 0;
#if __riscv_xlen == 32
asm volatile("amoor.w %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory");
#elif __riscv_xlen == 64
asm volatile("amoor.d %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory");
#endif
return result;
}

rt_atomic_t rt_hw_atomic_load(volatile rt_atomic_t *ptr)
{
rt_atomic_t result = 0;
#if __riscv_xlen == 32
asm volatile("amoxor.w %0, x0, (%1)" : "=r"(result) : "r"(ptr) : "memory");
#elif __riscv_xlen == 64
asm volatile("amoxor.d %0, x0, (%1)" : "=r"(result) : "r"(ptr) : "memory");
#endif
return result;
}

void rt_hw_atomic_store(volatile rt_atomic_t *ptr, rt_atomic_t val)
{
rt_atomic_t result = 0;
#if __riscv_xlen == 32
asm volatile("amoswap.w %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory");
#elif __riscv_xlen == 64
asm volatile("amoswap.d %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory");
#endif
}

rt_atomic_t rt_hw_atomic_flag_test_and_set(volatile rt_atomic_t *ptr)
{
rt_atomic_t result = 0;
rt_atomic_t temp = 1;
#if __riscv_xlen == 32
asm volatile("amoor.w %0, %1, (%2)" : "=r"(result) : "r"(temp), "r"(ptr) : "memory");
#elif __riscv_xlen == 64
asm volatile("amoor.d %0, %1, (%2)" : "=r"(result) : "r"(temp), "r"(ptr) : "memory");
#endif
return result;
}

void rt_hw_atomic_flag_clear(volatile rt_atomic_t *ptr)
{
rt_atomic_t result = 0;
#if __riscv_xlen == 32
asm volatile("amoand.w %0, x0, (%1)" : "=r"(result) : "r"(ptr) : "memory");
#elif __riscv_xlen == 64
asm volatile("amoand.d %0, x0, (%1)" : "=r"(result) : "r"(ptr) : "memory");
#endif
}

rt_atomic_t rt_hw_atomic_compare_exchange_strong(volatile rt_atomic_t *ptr, rt_atomic_t *old, rt_atomic_t desired)
{
rt_atomic_t tmp = *old;
rt_atomic_t result = 0;
#if __riscv_xlen == 32
asm volatile(
" fence iorw, ow\n"
"1: lr.w.aq %[result], (%[ptr])\n"
" bne %[result], %[tmp], 2f\n"
" sc.w.rl %[tmp], %[desired], (%[ptr])\n"
" bnez %[tmp], 1b\n"
" li %[result], 1\n"
" j 3f\n"
" 2:sw %[result], (%[old])\n"
" li %[result], 0\n"
" 3:\n"
: [result] "+r"(result), [tmp] "+r"(tmp), [ptr] "+r"(ptr)
: [desired] "r"(desired), [old] "r"(old)
: "memory");
#elif __riscv_xlen == 64
asm volatile(
" fence iorw, ow\n"
"1: lr.d.aq %[result], (%[ptr])\n"
" bne %[result], %[tmp], 2f\n"
" sc.d.rl %[tmp], %[desired], (%[ptr])\n"
" bnez %[tmp], 1b\n"
" li %[result], 1\n"
" j 3f\n"
" 2:sd %[result], (%[old])\n"
" li %[result], 0\n"
" 3:\n"
: [result] "+r"(result), [tmp] "+r"(tmp), [ptr] "+r"(ptr)
: [desired] "r"(desired), [old] "r"(old)
: "memory");
#endif
return result;
}
Loading