1
- use crate :: { clint, hart_id, qemu_hsm:: QemuHsm , Supervisor } ;
1
+ use crate :: { clint, hart_id, qemu_hsm:: QemuHsm , FixedRustSBI , Supervisor } ;
2
2
use core:: arch:: asm;
3
3
use riscv:: register:: * ;
4
+ use rustsbi:: spec:: binary:: SbiRet ;
4
5
5
6
#[ repr( usize ) ]
6
7
pub ( crate ) enum Operation {
7
8
Stop = 0 ,
8
9
SystemReset = 1 ,
9
10
}
10
11
11
- pub ( crate ) fn execute_supervisor ( hsm : & QemuHsm , supervisor : Supervisor ) -> Operation {
12
- let mut ctx = SupervisorContext :: new ( supervisor) ;
13
- mscratch:: write ( & mut ctx as * mut _ as _ ) ;
14
-
12
+ pub ( crate ) fn execute_supervisor (
13
+ sbi : FixedRustSBI ,
14
+ hsm : & QemuHsm ,
15
+ supervisor : Supervisor ,
16
+ ) -> Operation {
15
17
clint:: msip:: clear ( ) ;
16
18
clint:: mtimecmp:: clear ( ) ;
17
19
unsafe {
@@ -26,6 +28,10 @@ pub(crate) fn execute_supervisor(hsm: &QemuHsm, supervisor: Supervisor) -> Opera
26
28
mie:: set_msoft ( ) ;
27
29
mie:: set_mtimer ( ) ;
28
30
}
31
+ let ctx = SupervisorContext :: new ( supervisor) ;
32
+
33
+ let mut env = Environment { ctx, sbi } ;
34
+ mscratch:: write ( & mut env. ctx as * mut _ as _ ) ;
29
35
30
36
hsm. record_current_start_finished ( ) ;
31
37
loop {
@@ -34,15 +40,87 @@ pub(crate) fn execute_supervisor(hsm: &QemuHsm, supervisor: Supervisor) -> Opera
34
40
use mcause:: { Exception , Trap } ;
35
41
match mcause:: read ( ) . cause ( ) {
36
42
Trap :: Exception ( Exception :: SupervisorEnvCall ) => {
37
- if let Some ( op) = ctx . handle_ecall ( ) {
43
+ if let Some ( op) = env . handle_ecall ( ) {
38
44
break op;
39
45
}
40
46
}
41
- t => ctx . trap_stop ( t) ,
47
+ t => env . trap_stop ( t) ,
42
48
}
43
49
}
44
50
}
45
51
52
+ struct Environment < ' a > {
53
+ ctx : SupervisorContext ,
54
+ sbi : FixedRustSBI < ' a > ,
55
+ }
56
+
57
+ impl < ' a > Environment < ' a > {
58
+ fn handle_ecall ( & mut self ) -> Option < Operation > {
59
+ use rustsbi:: spec:: { binary:: * , hsm:: * , srst:: * } ;
60
+ if self . ctx . sbi_extension ( ) == sbi_spec:: legacy:: LEGACY_CONSOLE_PUTCHAR {
61
+ let ch = self . ctx . a ( 0 ) ;
62
+ crate :: console:: STDOUT . wait ( ) . putchar ( ( ch & 0xFF ) as u8 ) ;
63
+ self . ctx . mepc = self . ctx . mepc . wrapping_add ( 4 ) ;
64
+ return None ;
65
+ } else if self . ctx . sbi_extension ( ) == sbi_spec:: legacy:: LEGACY_CONSOLE_GETCHAR {
66
+ let ch = crate :: console:: STDOUT . wait ( ) . getchar ( ) ;
67
+ * self . ctx . a_mut ( 0 ) = ch as usize ;
68
+ self . ctx . mepc = self . ctx . mepc . wrapping_add ( 4 ) ;
69
+ return None ;
70
+ }
71
+ let ans = self . sbi . handle_ecall (
72
+ self . ctx . sbi_extension ( ) ,
73
+ self . ctx . sbi_function ( ) ,
74
+ self . ctx . sbi_param ( ) ,
75
+ ) ;
76
+ // 判断导致退出执行流程的调用
77
+ if ans. error == RET_SUCCESS {
78
+ match ( self . ctx . sbi_extension ( ) , self . ctx . sbi_function ( ) ) {
79
+ // 核状态
80
+ ( EID_HSM , HART_STOP ) => return Some ( Operation :: Stop ) ,
81
+ ( EID_HSM , HART_SUSPEND )
82
+ if matches ! (
83
+ u32 :: try_from( self . ctx. a( 0 ) ) ,
84
+ Ok ( HART_SUSPEND_TYPE_NON_RETENTIVE )
85
+ ) =>
86
+ {
87
+ return Some ( Operation :: Stop )
88
+ }
89
+ // 系统重置
90
+ ( EID_SRST , SYSTEM_RESET )
91
+ if matches ! (
92
+ u32 :: try_from( self . ctx. a( 0 ) ) ,
93
+ Ok ( RESET_TYPE_COLD_REBOOT ) | Ok ( RESET_TYPE_WARM_REBOOT )
94
+ ) =>
95
+ {
96
+ return Some ( Operation :: SystemReset )
97
+ }
98
+ _ => { }
99
+ }
100
+ }
101
+ self . ctx . fill_in ( ans) ;
102
+ self . ctx . mepc = self . ctx . mepc . wrapping_add ( 4 ) ;
103
+ None
104
+ }
105
+
106
+ fn trap_stop ( & self , trap : mcause:: Trap ) -> ! {
107
+ println ! (
108
+ "
109
+ -----------------------------
110
+ > trap: {trap:?}
111
+ > mstatus: {:#018x}
112
+ > mepc: {:#018x}
113
+ > mtval: {:#018x}
114
+ -----------------------------
115
+ " ,
116
+ self . ctx. mstatus,
117
+ self . ctx. mepc,
118
+ mtval:: read( )
119
+ ) ;
120
+ panic ! ( "stopped with unsupported trap" )
121
+ }
122
+ }
123
+
46
124
#[ repr( C ) ]
47
125
#[ derive( Debug ) ]
48
126
struct SupervisorContext {
@@ -72,6 +150,34 @@ impl SupervisorContext {
72
150
ctx
73
151
}
74
152
153
+ #[ inline]
154
+ fn sbi_extension ( & self ) -> usize {
155
+ self . a ( 7 )
156
+ }
157
+
158
+ #[ inline]
159
+ fn sbi_function ( & self ) -> usize {
160
+ self . a ( 6 )
161
+ }
162
+
163
+ #[ inline]
164
+ fn sbi_param ( & self ) -> [ usize ; 6 ] {
165
+ [
166
+ self . a ( 0 ) ,
167
+ self . a ( 1 ) ,
168
+ self . a ( 2 ) ,
169
+ self . a ( 3 ) ,
170
+ self . a ( 4 ) ,
171
+ self . a ( 5 ) ,
172
+ ]
173
+ }
174
+
175
+ #[ inline]
176
+ fn fill_in ( & mut self , ans : SbiRet ) {
177
+ * self . a_mut ( 0 ) = ans. error ;
178
+ * self . a_mut ( 1 ) = ans. value ;
179
+ }
180
+
75
181
#[ inline]
76
182
fn x ( & self , n : usize ) -> usize {
77
183
self . x [ n - 1 ]
@@ -92,60 +198,6 @@ impl SupervisorContext {
92
198
self . x_mut ( n + 10 )
93
199
}
94
200
95
- fn handle_ecall ( & mut self ) -> Option < Operation > {
96
- use rustsbi:: spec:: { binary:: * , hsm:: * , srst:: * } ;
97
- let extension = self . a ( 7 ) ;
98
- let function = self . a ( 6 ) ;
99
- let ans = rustsbi:: ecall (
100
- extension,
101
- function,
102
- [
103
- self . a ( 0 ) ,
104
- self . a ( 1 ) ,
105
- self . a ( 2 ) ,
106
- self . a ( 3 ) ,
107
- self . a ( 4 ) ,
108
- self . a ( 5 ) ,
109
- ] ,
110
- ) ;
111
- // 判断导致退出执行流程的调用
112
- if ans. error == RET_SUCCESS {
113
- match extension {
114
- // 核状态
115
- EID_HSM => match function {
116
- HART_STOP => return Some ( Operation :: Stop ) ,
117
- HART_SUSPEND
118
- if matches ! (
119
- u32 :: try_from( self . a( 0 ) ) ,
120
- Ok ( HART_SUSPEND_TYPE_NON_RETENTIVE )
121
- ) =>
122
- {
123
- return Some ( Operation :: Stop ) ;
124
- }
125
- _ => { }
126
- } ,
127
- // 系统重置
128
- EID_SRST => match function {
129
- SYSTEM_RESET
130
- if matches ! (
131
- u32 :: try_from( self . a( 0 ) ) ,
132
- Ok ( RESET_TYPE_COLD_REBOOT ) | Ok ( RESET_TYPE_WARM_REBOOT )
133
- ) =>
134
- {
135
- return Some ( Operation :: SystemReset )
136
- }
137
- _ => { }
138
- } ,
139
-
140
- _ => { }
141
- }
142
- }
143
- * self . a_mut ( 0 ) = ans. error ;
144
- * self . a_mut ( 1 ) = ans. value ;
145
- self . mepc = self . mepc . wrapping_add ( 4 ) ;
146
- None
147
- }
148
-
149
201
#[ allow( unused) ]
150
202
fn do_transfer_trap ( & mut self , cause : scause:: Trap ) {
151
203
unsafe {
@@ -178,23 +230,6 @@ impl SupervisorContext {
178
230
self . mepc = stvec:: read ( ) . address ( ) ;
179
231
}
180
232
}
181
-
182
- fn trap_stop ( & self , trap : mcause:: Trap ) -> ! {
183
- println ! (
184
- "
185
- -----------------------------
186
- > trap: {trap:?}
187
- > mstatus: {:#018x}
188
- > mepc: {:#018x}
189
- > mtval: {:#018x}
190
- -----------------------------
191
- " ,
192
- self . mstatus,
193
- self . mepc,
194
- mtval:: read( )
195
- ) ;
196
- panic ! ( "stopped with unsupported trap" )
197
- }
198
233
}
199
234
200
235
/// M 态转到 S 态。
0 commit comments