@@ -78,31 +78,46 @@ pub(crate) fn trap_delegate(hartid: usize) {
78
78
) ;
79
79
}
80
80
81
- /// 操作一个静态的原子变量。
82
- /// 现在除启动核外,所有核都处于 STOPPED 状态,
83
- /// 主核在 [`sbi::hart_start`] 之前给原子变量 +1。
84
- /// 核启动后,会自动给原子变量 -1。
85
- /// 所有核成功启动则原子变量值归零。
86
- /// 所有核一起等待原子变量归零,然后副核调用 [`sbi::hart_stop`] 关闭。
87
- /// 主核等待所有副核关闭,然后退出。
81
+ /// 所有副核:启动 -> 不可恢复休眠 -> 唤醒 -> 可恢复休眠 -> 唤醒 -> 关闭。
88
82
pub ( crate ) fn start_stop_harts ( hartid : usize , smp : usize ) {
83
+ const SUSPENDED : sbi:: SbiRet = sbi:: SbiRet {
84
+ error : sbi:: RET_SUCCESS ,
85
+ value : sbi:: HART_STATE_SUSPENDED ,
86
+ } ;
87
+ const STOPPED : sbi:: SbiRet = sbi:: SbiRet {
88
+ error : sbi:: RET_SUCCESS ,
89
+ value : sbi:: HART_STATE_STOPPED ,
90
+ } ;
91
+
89
92
use spin:: { Barrier , Once } ;
90
- static BARRIER : Once < Barrier > = Once :: new ( ) ;
93
+ static STARTED : Once < Barrier > = Once :: new ( ) ;
94
+ static RESUMED : Once < Barrier > = Once :: new ( ) ;
91
95
92
96
#[ naked]
93
- unsafe extern "C" fn test_start_entry ( hartid : usize ) -> ! {
97
+ unsafe extern "C" fn test_entry ( hartid : usize , main : usize ) -> ! {
94
98
core:: arch:: asm!(
95
99
"csrw sie, zero" , // 关中断
96
100
"call {select_stack}" , // 设置启动栈
97
- "j {main}" , // 进入 rust
101
+ "jr a1" , // 进入 rust
98
102
select_stack = sym crate :: select_stack,
99
- main = sym secondary_rust_main,
100
103
options( noreturn)
101
104
)
102
105
}
103
106
104
- extern "C" fn secondary_rust_main ( hart_id : usize ) -> ! {
105
- BARRIER . wait ( ) . wait ( ) ;
107
+ extern "C" fn start_rust_main ( hart_id : usize ) -> ! {
108
+ STARTED . wait ( ) . wait ( ) ;
109
+ let ret = sbi:: hart_suspend (
110
+ sbi:: HART_SUSPEND_TYPE_NON_RETENTIVE ,
111
+ test_entry as _ ,
112
+ resume_rust_main as _ ,
113
+ ) ;
114
+ unreachable ! ( "suspend [{hart_id}] but {ret:?}" ) ;
115
+ }
116
+
117
+ extern "C" fn resume_rust_main ( hart_id : usize ) -> ! {
118
+ RESUMED . wait ( ) . wait ( ) ;
119
+ let ret = sbi:: hart_suspend ( sbi:: HART_SUSPEND_TYPE_RETENTIVE , 0 , 0 ) ;
120
+ assert_eq ! ( sbi:: RET_SUCCESS , ret. error) ;
106
121
let ret = sbi:: hart_stop ( ) ;
107
122
unreachable ! ( "stop [{hart_id}] but {ret:?}" ) ;
108
123
}
@@ -113,11 +128,12 @@ pub(crate) fn start_stop_harts(hartid: usize, smp: usize) {
113
128
) ;
114
129
115
130
// 启动副核
116
- let barrier = BARRIER . call_once ( || Barrier :: new ( smp) ) ;
131
+ let started = STARTED . call_once ( || Barrier :: new ( smp) ) ;
132
+ let resumed = RESUMED . call_once ( || Barrier :: new ( smp) ) ;
117
133
for id in 0 ..smp {
118
134
if id != hartid {
119
135
println ! ( "[test-kernel] Hart{id} is booting..." ) ;
120
- let ret = sbi:: hart_start ( id, test_start_entry as usize , 0 ) ;
136
+ let ret = sbi:: hart_start ( id, test_entry as _ , start_rust_main as _ ) ;
121
137
if ret. error != sbi:: RET_SUCCESS {
122
138
panic ! ( "[test-kernel] Start hart{id} failed: {ret:?}" ) ;
123
139
}
@@ -126,19 +142,38 @@ pub(crate) fn start_stop_harts(hartid: usize, smp: usize) {
126
142
}
127
143
}
128
144
// 等待副核启动完成
129
- barrier . wait ( ) ;
145
+ started . wait ( ) ;
130
146
print ! ( "[test-kernel] All harts boot successfully!\n " ) ;
131
- // 等待副核关闭
147
+ // 等待副核休眠(不可恢复)
148
+ for id in 0 ..smp {
149
+ if id != hartid {
150
+ while sbi:: hart_get_status ( id) != SUSPENDED {
151
+ core:: hint:: spin_loop ( ) ;
152
+ }
153
+ println ! ( "[test-kernel] Hart{id} suspended." ) ;
154
+ } else {
155
+ println ! ( "[test-kernel] Hart{id} is the primary hart." ) ;
156
+ }
157
+ }
158
+ // 全部唤醒
159
+ sbi:: send_ipi ( 0 , -1isize as usize ) ;
160
+ // 等待副核恢复完成
161
+ resumed. wait ( ) ;
162
+ print ! ( "[test-kernel] All harts resume successfully!\n " ) ;
132
163
for id in 0 ..smp {
133
- const STOPPED : sbi:: SbiRet = sbi:: SbiRet {
134
- error : sbi:: RET_SUCCESS ,
135
- value : sbi:: HART_STATE_STOPPED ,
136
- } ;
137
164
if id != hartid {
165
+ // 等待副核休眠
166
+ while sbi:: hart_get_status ( id) != SUSPENDED {
167
+ core:: hint:: spin_loop ( ) ;
168
+ }
169
+ print ! ( "[test-kernel] Hart{id} suspended, " ) ;
170
+ // 单独唤醒
171
+ sbi:: send_ipi ( 1usize << id, 0 ) ;
172
+ // 等待副核关闭
138
173
while sbi:: hart_get_status ( id) != STOPPED {
139
174
core:: hint:: spin_loop ( ) ;
140
175
}
141
- println ! ( "[test-kernel] Hart{id} stopped." ) ;
176
+ println ! ( "then stopped." ) ;
142
177
} else {
143
178
println ! ( "[test-kernel] Hart{id} is the primary hart." ) ;
144
179
}
0 commit comments