@@ -33,19 +33,19 @@ enum HsmState {
33
33
ResumePending = 6 ,
34
34
}
35
35
36
- // RustSBI-QEMU hart state monitor structure. It stores hart states for all harts,
37
- // and last command (see HsmCommand) when hart is requested to procceed HSM functions.
36
+ // RustSBI-QEMU hart state monitor structure. It stores hart states for all harts,
37
+ // and last command (see HsmCommand) when hart is requested to procceed HSM functions.
38
38
//
39
39
// RustSBI-QEMU makes use of machine software interrupt. Functions should modify `state` to
40
40
// XxxPending before the actual procedure began. Then, caller should store next command structure
41
41
// to `last_command`, and use IPI to invoke software interrupt on machine level.
42
- //
42
+ //
43
43
// When target hart received machine software interrupt, it should read and procceed command
44
44
// from `last_command`. Then, after command execution makes progress, it should modify
45
45
// `state` to Xxxed to mark that the HSM function has taken effect.
46
46
//
47
47
// These functions above are defined as asynchronous procedures. That means it returns before
48
- // acutal procedure has finished. There are functions to read its current state when the target hart
48
+ // acutal procedure has finished. There are functions to read its current state when the target hart
49
49
// is still in transition or after the transition is done. These functions may read from `last_command`
50
50
// variable at any time.
51
51
#[ derive( Clone ) ]
@@ -54,8 +54,8 @@ pub struct QemuHsm {
54
54
last_command : Arc < spin:: Mutex < HashMap < usize , HsmCommand > > > ,
55
55
}
56
56
57
- // RustSBI-QEMU HSM command, these commands apply to a remote given hart.
58
- //
57
+ // RustSBI-QEMU HSM command, these commands apply to a remote given hart.
58
+ //
59
59
// Should be stored with hart id before software interrupt is invoked.
60
60
// After software interrupt is received, the target hart should handle with HSM command structure
61
61
// and run corresponding HSM procedures.
@@ -87,7 +87,7 @@ impl QemuHsm {
87
87
}
88
88
// Record that current hart id is marked as `Stopped` state.
89
89
// It is used in interrupt handler, when hart stop command is received. Before this function,
90
- // the target hart is making preparations to stop; it records state and must stop immediately after
90
+ // the target hart is making preparations to stop; it records state and must stop immediately after
91
91
// this function is called.
92
92
pub ( crate ) fn record_current_stop_finished ( & self ) {
93
93
let hart_id = riscv:: register:: mhartid:: read ( ) ;
@@ -98,7 +98,7 @@ impl QemuHsm {
98
98
}
99
99
// Record that current hart id is marked as `Started` state.
100
100
// It is used when hart stop command is received in interrupt handler.
101
- // The target hart (when in interrupt handler) is prepared to start, it marks itself into 'started',
101
+ // The target hart (when in interrupt handler) is prepared to start, it marks itself into 'started',
102
102
// and should jump to target address right away.
103
103
pub ( crate ) fn record_current_start_finished ( & self ) {
104
104
let hart_id = riscv:: register:: mhartid:: read ( ) ;
@@ -111,7 +111,7 @@ impl QemuHsm {
111
111
112
112
// Adapt RustSBI interface to RustSBI-QEMU's QemuHsm.
113
113
impl rustsbi:: Hsm for QemuHsm {
114
- // The supervisor software above RustSBI has called SBI environment to start a given `hart_id`
114
+ // The supervisor software above RustSBI has called SBI environment to start a given `hart_id`
115
115
// to address `start_addr` with parameter `opaque`.
116
116
fn hart_start ( & self , hart_id : usize , start_addr : usize , opaque : usize ) -> SbiRet {
117
117
// previous privileged mode should be user or supervisor; start from machine mode is not supported
@@ -129,21 +129,21 @@ impl rustsbi::Hsm for QemuHsm {
129
129
HsmState :: StartPending as u8 ,
130
130
Ordering :: AcqRel ,
131
131
Ordering :: Acquire ,
132
- ) ;
132
+ ) ;
133
133
// procceed with invalid hart states.
134
134
// - the given hartid is already started, the compare exchange should fail and suggests current state as `Started`,
135
135
// function should return error as already available.
136
136
if current_state == Err ( HsmState :: Started as u8 ) {
137
- return SbiRet :: already_available ( )
138
- }
137
+ return SbiRet :: already_available ( ) ;
138
+ }
139
139
// - otherwise return invalid parameter, this may be caused for hart is already transitioning from started state
140
140
if current_state != Ok ( HsmState :: Stopped as u8 ) {
141
141
return SbiRet :: invalid_param ( ) ;
142
142
}
143
143
// todo: check start address
144
144
/* SBI_ERR_INVALID_ADDRESS: start_addr is not valid possibly due to following reasons:
145
- * It is not a valid physical address.
146
- * The address is prohibited by PMP to run in supervisor mode. */
145
+ * It is not a valid physical address.
146
+ * The address is prohibited by PMP to run in supervisor mode. */
147
147
// fill in the parameter
148
148
let mut config_lock = self . last_command . lock ( ) ;
149
149
config_lock
@@ -154,8 +154,8 @@ impl rustsbi::Hsm for QemuHsm {
154
154
// now, start the target hart
155
155
let clint = crate :: clint:: Clint :: new ( 0x2000000 as * mut u8 ) ;
156
156
clint. send_soft ( hart_id) ; // this does not block the current function
157
- // The following process is going to be handled in software interrupt handler, and
158
- // the function returns immediately as starting a hart is defined as an asynchronous procedure.
157
+ // The following process is going to be handled in software interrupt handler, and
158
+ // the function returns immediately as starting a hart is defined as an asynchronous procedure.
159
159
SbiRet :: ok ( 0 )
160
160
}
161
161
fn hart_stop ( & self , hart_id : usize ) -> SbiRet {
@@ -172,7 +172,7 @@ impl rustsbi::Hsm for QemuHsm {
172
172
) ;
173
173
// check current hart state
174
174
if current_state. is_err ( ) {
175
- return SbiRet :: failed ( ) // illegal state
175
+ return SbiRet :: failed ( ) ; // illegal state
176
176
}
177
177
// fill in the parameter
178
178
let mut config_lock = self . last_command . lock ( ) ;
@@ -187,12 +187,12 @@ impl rustsbi::Hsm for QemuHsm {
187
187
fn hart_get_status ( & self , hart_id : usize ) -> SbiRet {
188
188
self . state . lock ( ) . get ( & hart_id) . map_or (
189
189
SbiRet :: invalid_param ( ) , // not in `state` map structure, the given hart id is invalid
190
- |a| SbiRet :: ok ( a. load ( Ordering :: Relaxed ) as usize )
190
+ |a| SbiRet :: ok ( a. load ( Ordering :: Relaxed ) as usize ) ,
191
191
)
192
192
}
193
193
// Supervisor requested current hart to suspend.
194
194
//
195
- // In RustSBI-QEMU, if `suspend_type` is retentive, it pauses the current hart; `resume_addr`
195
+ // In RustSBI-QEMU, if `suspend_type` is retentive, it pauses the current hart; `resume_addr`
196
196
// and `opaque` is not used.
197
197
// Otherwise, the current hart discards current supervisor context, and returns to another
198
198
// `resume_addr` with parameter `opaque`.
@@ -204,24 +204,27 @@ impl rustsbi::Hsm for QemuHsm {
204
204
// try to set current target hart state to stop pending
205
205
let hart_id = riscv:: register:: mhartid:: read ( ) ;
206
206
let mut state_lock = self . state . lock ( ) ;
207
- let current_state = state_lock. entry ( hart_id)
207
+ let current_state = state_lock
208
+ . entry ( hart_id)
208
209
. or_insert ( AtomicU8 :: new ( HsmState :: Stopped as u8 ) )
209
210
. compare_exchange (
210
211
HsmState :: Started as u8 ,
211
212
HsmState :: SuspendPending as u8 ,
212
213
Ordering :: AcqRel ,
213
214
Ordering :: Acquire ,
214
- ) ;
215
+ ) ;
215
216
// check current hart state
216
217
if current_state. is_err ( ) {
217
- return SbiRet :: failed ( ) // illegal state
218
+ return SbiRet :: failed ( ) ; // illegal state
218
219
}
219
220
drop ( state_lock) ;
220
221
// actual suspend begin
221
222
suspend_current_hart ( & self ) ; // pause and wait for machine level ipi
222
- // mark current hart as started
223
+ // mark current hart as started
223
224
let mut state_lock = self . state . lock ( ) ;
224
- state_lock. entry ( hart_id) . insert ( AtomicU8 :: new ( HsmState :: Started as u8 ) ) ;
225
+ state_lock
226
+ . entry ( hart_id)
227
+ . insert ( AtomicU8 :: new ( HsmState :: Started as u8 ) ) ;
225
228
drop ( state_lock) ;
226
229
SbiRet :: ok ( 0 )
227
230
}
@@ -240,31 +243,37 @@ impl rustsbi::Hsm for QemuHsm {
240
243
// try to set current target hart state to stop pending
241
244
let hart_id = riscv:: register:: mhartid:: read ( ) ;
242
245
let mut state_lock = self . state . lock ( ) ;
243
- let current_state = state_lock. entry ( hart_id)
246
+ let current_state = state_lock
247
+ . entry ( hart_id)
244
248
. or_insert ( AtomicU8 :: new ( HsmState :: Stopped as u8 ) )
245
249
. compare_exchange (
246
250
HsmState :: Started as u8 ,
247
251
HsmState :: SuspendPending as u8 ,
248
252
Ordering :: AcqRel ,
249
253
Ordering :: Acquire ,
250
- ) ;
254
+ ) ;
251
255
// check current hart state
252
256
if current_state. is_err ( ) {
253
- return SbiRet :: failed ( ) // illegal state
257
+ return SbiRet :: failed ( ) ; // illegal state
254
258
}
255
259
drop ( state_lock) ;
256
260
// retentive suspend
257
261
suspend_current_hart ( & self ) ;
258
262
// begin wake process
259
263
// send start command to runtime of current hart
260
264
let mut config_lock = self . last_command . lock ( ) ;
261
- config_lock. entry ( hart_id) . insert ( HsmCommand :: Start ( resume_addr, opaque) ) ;
265
+ config_lock
266
+ . entry ( hart_id)
267
+ . insert ( HsmCommand :: Start ( resume_addr, opaque) ) ;
262
268
drop ( config_lock) ;
263
- SbiRet { error : 0x233 , value : 0x0 } // unreachable, the runtime identifies start command and perform the hart resume
264
- } ,
269
+ SbiRet {
270
+ error : 0x233 ,
271
+ value : 0x0 ,
272
+ } // unreachable, the runtime identifies start command and perform the hart resume
273
+ }
265
274
// There could be other platform specific suspend types; RustSBI-QEMU does not define any
266
275
// platform suspend types. It gives SBI return value as not supported.
267
- _ => SbiRet :: not_supported ( )
276
+ _ => SbiRet :: not_supported ( ) ,
268
277
}
269
278
}
270
279
}
@@ -274,18 +283,20 @@ const SUSPEND_NON_RETENTIVE: u32 = 0x80000000;
274
283
275
284
// Suspend current hart and record resume state when wake
276
285
pub fn suspend_current_hart ( hsm : & QemuHsm ) {
277
- use riscv:: asm:: wfi;
278
- use riscv:: register:: { mie, mip, mhartid} ;
279
286
use crate :: clint:: Clint ;
287
+ use riscv:: asm:: wfi;
288
+ use riscv:: register:: { mhartid, mie, mip} ;
280
289
let hart_id = mhartid:: read ( ) ;
281
290
let clint = Clint :: new ( 0x2000000 as * mut u8 ) ;
282
291
clint. clear_soft ( hart_id) ; // Clear IPI
283
292
unsafe { mip:: clear_msoft ( ) } ; // clear machine software interrupt flag
284
293
let prev_msoft = mie:: read ( ) . msoft ( ) ;
285
294
unsafe { mie:: set_msoft ( ) } ; // Start listening for software interrupts
286
- // mark current state as suspended
295
+ // mark current state as suspended
287
296
let mut state_lock = hsm. state . lock ( ) ;
288
- state_lock. entry ( hart_id) . insert ( AtomicU8 :: new ( HsmState :: Suspended as u8 ) ) ;
297
+ state_lock
298
+ . entry ( hart_id)
299
+ . insert ( AtomicU8 :: new ( HsmState :: Suspended as u8 ) ) ;
289
300
drop ( state_lock) ;
290
301
// actual suspended process
291
302
loop {
@@ -296,7 +307,9 @@ pub fn suspend_current_hart(hsm: &QemuHsm) {
296
307
}
297
308
// mark current state as resume pending
298
309
let mut state_lock = hsm. state . lock ( ) ;
299
- state_lock. entry ( hart_id) . insert ( AtomicU8 :: new ( HsmState :: ResumePending as u8 ) ) ;
310
+ state_lock
311
+ . entry ( hart_id)
312
+ . insert ( AtomicU8 :: new ( HsmState :: ResumePending as u8 ) ) ;
300
313
drop ( state_lock) ;
301
314
// resume
302
315
if !prev_msoft {
0 commit comments