Skip to content

Commit acef64e

Browse files
Tm-C-mTRbb666
authored andcommitted
[libcpu-riscv]: [surpport SMP]: Add SMP support for qemu-virt64-riscv
1.Add the necessary function declarations for SMP enablement and implement the corresponding functionalities, including rt_hw_secondary_cpu_up, secondary_cpu_entry, rt_hw_local_irq_disable, rt_hw_local_irq_enable, rt_hw_secondary_cpu_idle_exec, rt_hw_spin_lock_init, rt_hw_spin_lock, rt_hw_spin_unlock, rt_hw_ipi_send, rt_hw_interrupt_set_priority, rt_hw_interrupt_get_priority, rt_hw_ipi_init, rt_hw_ipi_handler_install, and rt_hw_ipi_handler. 2.In the two functions (rt_hw_context_switch_to and rt_hw_context_switch) in context_gcc.S, add a call to rt_cpus_lock_status_restore to update the scheduler information. 3.If the MMU is enabled, use the .percpu section and record different hartids by configuring special page tables; if the MMU is not enabled, record them directly in the satp register. Additionally, add dynamic startup based on core configuration.The .percpu section is only used when both ARCH_MM_MMU and RT_USING_SMP are enabled. However, there is a certain amount of space waste since no macro guard is added for it in the link script currently. 4.The physical memory of QEMU started in CI is 128MB, so RT_HW_PAGE_END is modified from the original +256MB to +128MB. Modify the SConscript file under the common64 directory to include common/atomic_riscv.c in the compilation process. Signed-off-by: Mengchen Teng <teng_mengchen@163.com>
1 parent dd19c0e commit acef64e

File tree

20 files changed

+946
-166
lines changed

20 files changed

+946
-166
lines changed

bsp/qemu-virt64-riscv/SConstruct

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,25 @@ if GetDepend('__STACKSIZE__'): stack_size = GetDepend('__STACKSIZE__')
3838
stack_lds.write('__STACKSIZE__ = %d;\n' % stack_size)
3939
stack_lds.close()
4040

41+
# Obtain the number of harts from rtconfig.h and write
42+
# it into link_cpus.lds for the linker script
43+
try:
44+
with open('rtconfig.h', 'r') as f:
45+
rtconfig_content = f.readlines()
46+
except FileNotFoundError:
47+
cpus_nr = 1
48+
else:
49+
cpus_nr = 1 # default value
50+
for line in rtconfig_content:
51+
line = line.strip()
52+
if line.startswith('#define') and 'RT_CPUS_NR' in line:
53+
parts = line.split()
54+
if len(parts) >= 3 and parts[2].isdigit():
55+
cpus_nr = int(parts[2])
56+
break
57+
58+
with open('link_cpus.lds', 'w') as cpus_lds:
59+
cpus_lds.write(f'RT_CPUS_NR = {cpus_nr};\n')
60+
4161
# make a building
4262
DoBuilding(TARGET, objs)

bsp/qemu-virt64-riscv/driver/board.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424
#include "plic.h"
2525
#include "stack.h"
2626

27+
#ifdef RT_USING_SMP
28+
#include "interrupt.h"
29+
#endif /* RT_USING_SMP */
30+
2731
#ifdef RT_USING_SMART
2832
#include "riscv_mmu.h"
2933
#include "mmu.h"
@@ -89,6 +93,11 @@ void rt_hw_board_init(void)
8993

9094
rt_hw_tick_init();
9195

96+
#ifdef RT_USING_SMP
97+
/* ipi init */
98+
rt_hw_ipi_init();
99+
#endif /* RT_USING_SMP */
100+
92101
#ifdef RT_USING_COMPONENTS_INIT
93102
rt_components_board_init();
94103
#endif

bsp/qemu-virt64-riscv/driver/board.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ extern unsigned int __bss_end;
2525
#define RT_HW_HEAP_BEGIN ((void *)&__bss_end)
2626
#define RT_HW_HEAP_END ((void *)(RT_HW_HEAP_BEGIN + 64 * 1024 * 1024))
2727
#define RT_HW_PAGE_START RT_HW_HEAP_END
28-
#define RT_HW_PAGE_END ((void *)(KERNEL_VADDR_START + (256 * 1024 * 1024 - VIRT64_SBI_MEMSZ)))
28+
#define RT_HW_PAGE_END ((void *)(KERNEL_VADDR_START + (128 * 1024 * 1024 - VIRT64_SBI_MEMSZ)))
2929

3030
void rt_hw_board_init(void);
3131
void rt_init_user_mem(struct rt_thread *thread, const char *name,

bsp/qemu-virt64-riscv/link.lds

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*/
1010

1111
INCLUDE "link_stacksize.lds"
12+
INCLUDE "link_cpus.lds"
1213

1314
OUTPUT_ARCH( "riscv" )
1415

@@ -121,12 +122,9 @@ SECTIONS
121122
{
122123
. = ALIGN(64);
123124
__stack_start__ = .;
124-
125-
. += __STACKSIZE__;
126-
__stack_cpu0 = .;
127-
128-
. += __STACKSIZE__;
129-
__stack_cpu1 = .;
125+
/* Dynamically allocate stack areas according to RT_CPUS_NR */
126+
. += (__STACKSIZE__ * RT_CPUS_NR);
127+
__stack_end__ = .;
130128
} > SRAM
131129

132130
.sbss :
@@ -138,6 +136,24 @@ SECTIONS
138136
*(.scommon)
139137
} > SRAM
140138

139+
.percpu (NOLOAD) :
140+
{
141+
/* 2MB Align for MMU early map */
142+
. = ALIGN(0x200000);
143+
PROVIDE(__percpu_start = .);
144+
145+
*(.percpu)
146+
147+
/* 2MB Align for MMU early map */
148+
. = ALIGN(0x200000);
149+
150+
PROVIDE(__percpu_end = .);
151+
152+
/* Clone the area */
153+
. = __percpu_end + (__percpu_end - __percpu_start) * (RT_CPUS_NR - 1);
154+
PROVIDE(__percpu_real_end = .);
155+
} > SRAM
156+
141157
.bss :
142158
{
143159
*(.bss)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
RT_CPUS_NR = 8;

bsp/qemu-virt64-riscv/link_smart.lds

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*/
1010

1111
INCLUDE "link_stacksize.lds"
12+
INCLUDE "link_cpus.lds"
1213

1314
OUTPUT_ARCH( "riscv" )
1415

@@ -122,12 +123,9 @@ SECTIONS
122123
{
123124
. = ALIGN(64);
124125
__stack_start__ = .;
125-
126-
. += __STACKSIZE__;
127-
__stack_cpu0 = .;
128-
129-
. += __STACKSIZE__;
130-
__stack_cpu1 = .;
126+
/* Dynamically allocate stack areas according to RT_CPUS_NR */
127+
. += (__STACKSIZE__ * RT_CPUS_NR);
128+
__stack_end__ = .;
131129
} > SRAM
132130

133131
.sbss :
@@ -139,6 +137,24 @@ SECTIONS
139137
*(.scommon)
140138
} > SRAM
141139

140+
.percpu (NOLOAD) :
141+
{
142+
/* 2MB Align for MMU early map */
143+
. = ALIGN(0x200000);
144+
PROVIDE(__percpu_start = .);
145+
146+
*(.percpu)
147+
148+
/* 2MB Align for MMU early map */
149+
. = ALIGN(0x200000);
150+
151+
PROVIDE(__percpu_end = .);
152+
153+
/* Clone the area */
154+
. = __percpu_end + (__percpu_end - __percpu_start) * (RT_CPUS_NR - 1);
155+
PROVIDE(__percpu_real_end = .);
156+
} > SRAM
157+
142158
.bss :
143159
{
144160
*(.bss)

bsp/qemu-virt64-riscv/qemu-dbg.sh

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,16 @@
1-
qemu-system-riscv64 -nographic -machine virt -m 256M -kernel rtthread.bin -s -S \
1+
QEMU_CMD="qemu-system-riscv64 -nographic -machine virt -m 256M -kernel rtthread.bin -s -S"
2+
3+
if grep -q "#define RT_USING_SMP" ./rtconfig.h 2>/dev/null; then
4+
hart_num=$(grep "RT_CPUS_NR = [0-9]*;" ./link_cpus.lds | awk -F'[=;]' '{gsub(/ /, "", $2); print $2}')
5+
if [ -z "$hart_num" ]; then
6+
hart_num=1
7+
fi
8+
QEMU_CMD="$QEMU_CMD -smp $hart_num"
9+
fi
10+
11+
QEMU_CMD="$QEMU_CMD \
212
-drive if=none,file=sd.bin,format=raw,id=blk0 -device virtio-blk-device,drive=blk0,bus=virtio-mmio-bus.0 \
313
-netdev user,id=tap0 -device virtio-net-device,netdev=tap0,bus=virtio-mmio-bus.1 \
4-
-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
14+
-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"
15+
16+
eval $QEMU_CMD

bsp/qemu-virt64-riscv/run.sh

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,20 @@ if [ ! -f $path_image ]; then
2424
exit
2525
fi
2626

27-
qemu-system-riscv64 -nographic -machine virt -m 256M -kernel rtthread.bin \
27+
QEMU_CMD="qemu-system-riscv64 -nographic -machine virt -m 256M -kernel rtthread.bin"
28+
29+
if grep -q "#define RT_USING_SMP" ./rtconfig.h 2>/dev/null; then
30+
hart_num=$(grep "RT_CPUS_NR = [0-9]*;" ./link_cpus.lds 2>/dev/null | awk -F'[=;]' '{gsub(/ /, "", $2); print $2}')
31+
if [ -z "$hart_num" ] || [ "$hart_num" -lt 1 ]; then
32+
echo "Warning: Invalid or missing RT_CPUS_NR, defaulting to 1"
33+
hart_num=1
34+
fi
35+
QEMU_CMD="$QEMU_CMD -smp $hart_num"
36+
fi
37+
38+
QEMU_CMD="$QEMU_CMD \
2839
-drive if=none,file=$path_image,format=raw,id=blk0 -device virtio-blk-device,drive=blk0,bus=virtio-mmio-bus.0 \
2940
-netdev user,id=tap0 -device virtio-net-device,netdev=tap0,bus=virtio-mmio-bus.1 \
30-
-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
41+
-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"
42+
43+
eval $QEMU_CMD

libcpu/risc-v/common64/SConscript

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ CPPPATH = [cwd]
77
if not GetDepend('ARCH_USING_ASID'):
88
SrcRemove(src, ['asid.c'])
99

10+
src.append('../common/atomic_riscv.c')
11+
1012
group = DefineGroup('CPU', src, depend = [''], CPPPATH = CPPPATH)
1113

1214
Return('group')

libcpu/risc-v/common64/context_gcc.S

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,29 +69,47 @@
6969
.endm
7070

7171
/*
72+
* #ifdef RT_USING_SMP
73+
* void rt_hw_context_switch_to(rt_ubase_t to, stuct rt_thread *to_thread);
74+
* #else
7275
* void rt_hw_context_switch_to(rt_ubase_t to);
73-
*
74-
* a0 --> to SP pointer
76+
* #endif
77+
* a0 --> to
78+
* a1 --> to_thread
7579
*/
7680
.globl rt_hw_context_switch_to
7781
rt_hw_context_switch_to:
7882
LOAD sp, (a0)
7983

84+
#ifdef RT_USING_SMP
85+
/* Pass the previous CPU lock status to rt_cpus_lock_status_restore for restoration */
86+
mv a0, a1
87+
call rt_cpus_lock_status_restore
88+
#endif
89+
8090
call rt_thread_self
8191
mv s1, a0
8292

93+
#ifndef RT_USING_SMP
94+
//if enable RT_USING_SMP, it will finished by rt_cpus_lock_status_restore.
8395
#ifdef RT_USING_SMART
84-
call lwp_aspace_switch
96+
call lwp_aspace_switch
8597
#endif
98+
#endif
8699

87100
RESTORE_CONTEXT
88101
sret
89102

90103
/*
104+
* #ifdef RT_USING_SMP
105+
* void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread);
106+
* #else
91107
* void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to);
108+
* #endif
92109
*
93110
* a0 --> from SP pointer
94111
* a1 --> to SP pointer
112+
* a2 --> to_thread
95113
*
96114
* It should only be used on local interrupt disable
97115
*/
@@ -103,13 +121,22 @@ rt_hw_context_switch:
103121
// restore to thread SP
104122
LOAD sp, (a1)
105123

124+
#ifdef RT_USING_SMP
125+
/* Pass the previous CPU lock status to rt_cpus_lock_status_restore for restoration */
126+
mv a0, a2
127+
call rt_cpus_lock_status_restore
128+
#endif /*RT_USING_SMP*/
129+
106130
// restore Address Space
107131
call rt_thread_self
108132
mv s1, a0
109133

134+
#ifndef RT_USING_SMP
135+
// if enable RT_USING_SMP, it will finished by rt_cpus_lock_status_restore.
110136
#ifdef RT_USING_SMART
111-
call lwp_aspace_switch
137+
call lwp_aspace_switch
112138
#endif
139+
#endif
113140

114141
RESTORE_CONTEXT
115142
sret

0 commit comments

Comments
 (0)