@@ -3,15 +3,11 @@ use crate::{
33 qemu_hsm:: { QemuHsm , SUSPEND_NON_RETENTIVE } ,
44 Supervisor ,
55} ;
6-
7- mod context;
8- mod transfer_trap;
9-
10- use context:: Context ;
6+ use riscv:: register:: { mstatus, mtval, scause, sepc, stval, stvec} ;
117
128pub ( crate ) fn execute_supervisor ( hsm : & QemuHsm , supervisor : Supervisor ) {
139 use core:: arch:: asm;
14- use riscv:: register:: { medeleg, mie, mstatus } ;
10+ use riscv:: register:: { medeleg, mie} ;
1511
1612 unsafe {
1713 mstatus:: set_mpp ( mstatus:: MPP :: Supervisor ) ;
@@ -73,15 +69,16 @@ pub(crate) fn execute_supervisor(hsm: &QemuHsm, supervisor: Supervisor) {
7369 ctx. mepc = ctx. mepc . wrapping_add ( 4 ) ;
7470 }
7571 T :: Exception ( E :: IllegalInstruction ) => {
76- use riscv:: register:: scause;
72+ use riscv:: register:: scause:: { Exception as E , Trap as T } ;
7773
74+ // let instruction = mtval::read();
75+ // 尝试修正或代理指令
76+ // TODO 需要排查 qemu 哪些版本需要代理哪些指令?
77+ // TODO 标准 20191213 的表 24.3 列出了一些特殊的 CSR,SBI 软件负责将它们模拟出来,但 Qemu6.0+ 似乎不需要模拟 time
7878 // const OPCODE_MASK: usize = (1 << 7) - 1;
7979 // const REG_MASK: usize = (1 << 5) - 1;
8080 // const OPCODE_CSR: usize = 0b1110011;
8181 // const CSR_TIME: usize = 0xc01;
82- // let instruction = mtval::read();
83- // 标准 20191213 的表 24.3 列出了一些特殊的 CSR,SBI 软件负责将它们模拟出来
84- // Qemu 似乎不需要模拟 time
8582 // if let OPCODE_CSR = instruction & OPCODE_MASK {
8683 // if instruction >> 20 == CSR_TIME {
8784 // match (instruction >> 7) & REG_MASK {
@@ -91,26 +88,90 @@ pub(crate) fn execute_supervisor(hsm: &QemuHsm, supervisor: Supervisor) {
9188 // continue;
9289 // }
9390 // }
94- // 如果不是可修正的指令,且不是 M 态本身发出的,转交给 S 态处理
95- // mpp != machine
96- if transfer_trap:: should_transfer_trap ( & ctx) {
97- transfer_trap:: do_transfer_trap (
98- & mut ctx,
99- scause:: Trap :: Exception ( scause:: Exception :: IllegalInstruction ) ,
100- ) ;
101- } else {
102- println ! ( "{:?}" , I :: MachineSoft ) ;
103- break ;
104- }
105- }
106- t => {
107- println ! ( "{t:?}" ) ;
108- break ;
91+
92+ ctx. do_transfer_trap ( T :: Exception ( E :: IllegalInstruction ) ) ;
10993 }
94+ // TODO 可以修复非原子的非对称访存
95+ t => panic ! ( "unsupported trap: {t:?}" ) ,
11096 }
11197 }
112- loop {
113- core:: hint:: spin_loop ( ) ;
98+ }
99+
100+ #[ repr( C ) ]
101+ #[ derive( Debug ) ]
102+ struct Context {
103+ msp : usize ,
104+ x : [ usize ; 31 ] ,
105+ mstatus : usize ,
106+ mepc : usize ,
107+ }
108+
109+ impl Context {
110+ fn new ( supervisor : Supervisor ) -> Self {
111+ let mut ctx = Self {
112+ msp : 0 ,
113+ x : [ 0 ; 31 ] ,
114+ mstatus : 0 ,
115+ mepc : supervisor. start_addr ,
116+ } ;
117+
118+ unsafe { core:: arch:: asm!( "csrr {}, mstatus" , out( reg) ctx. mstatus) } ;
119+ * ctx. a_mut ( 0 ) = hart_id ( ) ;
120+ * ctx. a_mut ( 1 ) = supervisor. opaque ;
121+
122+ ctx
123+ }
124+
125+ #[ inline]
126+ fn x ( & self , n : usize ) -> usize {
127+ self . x [ n - 1 ]
128+ }
129+
130+ #[ inline]
131+ fn x_mut ( & mut self , n : usize ) -> & mut usize {
132+ & mut self . x [ n - 1 ]
133+ }
134+
135+ #[ inline]
136+ fn a ( & self , n : usize ) -> usize {
137+ self . x ( n + 10 )
138+ }
139+
140+ #[ inline]
141+ fn a_mut ( & mut self , n : usize ) -> & mut usize {
142+ self . x_mut ( n + 10 )
143+ }
144+
145+ pub ( super ) fn do_transfer_trap ( & mut self , cause : scause:: Trap ) {
146+ unsafe {
147+ // 向 S 转发陷入
148+ mstatus:: set_mpp ( mstatus:: MPP :: Supervisor ) ;
149+ // 转发陷入源状态
150+ let spp = match ( self . mstatus >> 11 ) & 0b11 {
151+ // U
152+ 0b00 => mstatus:: SPP :: User ,
153+ // S
154+ 0b01 => mstatus:: SPP :: Supervisor ,
155+ // H/M
156+ mpp => unreachable ! ( "invalid mpp: {mpp:#x} to delegate" ) ,
157+ } ;
158+ mstatus:: set_spp ( spp) ;
159+ // 转发陷入原因
160+ scause:: set ( cause) ;
161+ // 转发陷入附加信息
162+ stval:: write ( mtval:: read ( ) ) ;
163+ // 转发陷入地址
164+ sepc:: write ( self . mepc ) ;
165+ // 设置 S 中断状态
166+ if mstatus:: read ( ) . sie ( ) {
167+ mstatus:: set_spie ( ) ;
168+ mstatus:: clear_sie ( ) ;
169+ }
170+ core:: arch:: asm!( "csrr {}, mstatus" , out( reg) self . mstatus) ;
171+ // 设置返回地址,返回到 S
172+ // TODO Vectored stvec?
173+ self . mepc = stvec:: read ( ) . address ( ) ;
174+ }
114175 }
115176}
116177
0 commit comments