@@ -26,37 +26,68 @@ use sbi::SbiMessage;
2626use loader:: load_vm_image;
2727use axhal:: mem:: PhysAddr ;
2828use crate :: regs:: GprIndex :: { A0 , A1 } ;
29+ use crate :: scause:: Interrupt ;
2930
3031const VM_ENTRY : usize = 0x8020_0000 ;
3132
3233#[ cfg_attr( feature = "axstd" , no_mangle) ]
3334fn main ( ) {
35+ //test
36+ ax_println ! ( "[DEBUG] Testing Hypervisor extension..." ) ;
37+
38+ unsafe { //直接使用汇编指令是不安全的操作,必须放在 unsafe 块中
39+ let result: usize ;
40+ core:: arch:: asm!( //这是 Rust 的内联汇编宏,允许在代码中直接嵌入汇编指令
41+ //csrr: "Control and Status Register Read" - 读取控制和状态寄存器
42+ // 如果 CPU 或 QEMU 没有启用 H 扩展,这条指令就会被识别为 非法指令,触发异常。
43+ "csrr {}, hstatus" , //读hstatus到一个通用寄存器
44+ // 然后汇编器/编译器确保:{} 被替换为一个合适的寄存器(比如 a0)
45+ out( reg) result//reg代表用通用寄存器存输出 再将输出传给result
46+ ) ;
47+ ax_println ! ( "hstatus = {:#x}" , result) ;
48+ }
49+ //
3450 ax_println ! ( "Hypervisor ..." ) ;
3551
3652 // A new address space for vm.
53+ ax_println ! ( "getting uspace" ) ;
54+ //从内存管理系统中划出一块物理内存作为虚拟机地址空间 即虚拟机的”物理“空间
3755 let mut uspace = axmm:: new_user_aspace ( ) . unwrap ( ) ;
3856
3957 // Load vm binary file into address space.
58+ //把映像加载到刚分配的地址空间(内部是将二进制文件读到物理内存 再建立Guest“物理”地址与真实物理页号的映射)
59+ ax_println ! ( "loading vm" ) ;
4060 if let Err ( e) = load_vm_image ( "/sbin/skernel2" , & mut uspace) {
4161 panic ! ( "Cannot load app! {:?}" , e) ;
4262 }
63+
4364
4465 // Setup context to prepare to enter guest mode.
66+ //准备Guest的上下文(寄存器)
67+ ax_println ! ( "setting ctx" ) ;
4568 let mut ctx = VmCpuRegisters :: default ( ) ;
4669 prepare_guest_context ( & mut ctx) ;
4770
4871 // Setup pagetable for 2nd address mapping.
72+ //建立hypervisor页表 用于二级地址映射
73+ //Guest 页表要等 Guest 内核启动后自己建立
74+ ax_println ! ( "setting pagetable" ) ;
4975 let ept_root = uspace. page_table_root ( ) ;
5076 prepare_vm_pgtable ( ept_root) ;
5177
5278 // Kick off vm and wait for it to exit.
79+ //run_guest封装了启动虚拟机的过程
80+ ax_println ! ( "kicking off vm" ) ;
5381 while !run_guest ( & mut ctx) {
5482 }
5583
5684 panic ! ( "Hypervisor ok!" ) ;
5785}
5886
5987fn prepare_vm_pgtable ( ept_root : PhysAddr ) {
88+ ax_println ! ( "prepare_vm_pgtable: ept_root = {:#x}" , ept_root) ;
89+
90+ //暂时注释
6091 let hgatp = 8usize << 60 | usize:: from ( ept_root) >> 12 ;
6192 unsafe {
6293 core:: arch:: asm!(
@@ -65,9 +96,13 @@ fn prepare_vm_pgtable(ept_root: PhysAddr) {
6596 ) ;
6697 core:: arch:: riscv64:: hfence_gvma_all ( ) ;
6798 }
99+
100+ // ax_println!("prepare_vm_pgtable: skipped for now");
101+
68102}
69103
70104fn run_guest ( ctx : & mut VmCpuRegisters ) -> bool {
105+ ax_println ! ( "[DEBUG] enter run_guest" ) ;
71106 unsafe {
72107 _run_guest ( ctx) ;
73108 }
@@ -77,6 +112,7 @@ fn run_guest(ctx: &mut VmCpuRegisters) -> bool {
77112
78113#[ allow( unreachable_code) ]
79114fn vmexit_handler ( ctx : & mut VmCpuRegisters ) -> bool {
115+ ax_println ! ( "[DEBUG] enter vmexit_hdler" ) ;
80116 use scause:: { Exception , Trap } ;
81117
82118 let scause = scause:: read ( ) ;
@@ -91,7 +127,7 @@ fn vmexit_handler(ctx: &mut VmCpuRegisters) -> bool {
91127 let a1 = ctx. guest_regs . gprs . reg ( A1 ) ;
92128 ax_println ! ( "a0 = {:#x}, a1 = {:#x}" , a0, a1) ;
93129 assert_eq ! ( a0, 0x6688 ) ;
94- assert_eq ! ( a1, 0x1234 ) ;
130+ assert_eq ! ( a1, 0x1234 ) ; //暗示a0 a1
95131 ax_println ! ( "Shutdown vm normally!" ) ;
96132 return true ;
97133 } ,
@@ -102,16 +138,61 @@ fn vmexit_handler(ctx: &mut VmCpuRegisters) -> bool {
102138 }
103139 } ,
104140 Trap :: Exception ( Exception :: IllegalInstruction ) => {
105- panic ! ( "Bad instruction: {:#x} sepc: {:#x}" ,
106- stval:: read( ) ,
107- ctx. guest_regs. sepc
108- ) ;
141+ // panic!("Bad instruction: {:#x} sepc: {:#x}",
142+ // stval::read(),
143+ // ctx.guest_regs.sepc
144+ // );
145+
146+ // Handle csrr a1, mhartid instruction
147+ let inst = stval:: read ( ) ;
148+ ax_println ! ( "VmExit Reason: IllegalInstruction: {:#x} at sepc: {:#x}" , inst, ctx. guest_regs. sepc) ;
149+
150+ // Set a1 to device tree address
151+ ctx. guest_regs . gprs . set_reg ( A1 , 0x1234 ) ;
152+ // Move sepc forward by 4 bytes to skip this instruction
153+ //sepc也代表着恢复到guest后的下条指令地址 所以要加”1“ 不然死循环
154+ ctx. guest_regs . sepc += 4 ;
155+ // if inst == 0xf14025f3 { // csrr a1, mhartid 的机器码
156+ // //模拟读取寄存器的操作 让guest以为读取成功了
157+ // let hartid: usize;
158+ // unsafe{
159+ // core::arch::asm!("csrr {}, mhartid", out(reg) hartid);
160+ // }
161+ // ax_println!("HS-mode mhartid = {}", hartid);
162+ // ctx.guest_regs.gprs.set_reg(A1, hartid);
163+ // // Move sepc forward by 4 bytes to skip this instruction
164+ // //sepc也代表着恢复到guest后的下条指令地址 所以要加”1“ 不然死循环
165+ // ctx.guest_regs.sepc += 4;
166+ // } else{
167+ // panic!("unimplement Bad instruction: {:#x} sepc: {:#x}",
168+ // stval::read(),
169+ // ctx.guest_regs.sepc
170+ // );
171+ // }
109172 } ,
110173 Trap :: Exception ( Exception :: LoadGuestPageFault ) => {
111- panic ! ( "LoadGuestPageFault: stval{:#x} sepc: {:#x}" ,
112- stval:: read( ) ,
113- ctx. guest_regs. sepc
114- ) ;
174+ // panic!("LoadGuestPageFault: stval{:#x} sepc: {:#x}",
175+ // stval::read(),
176+ // ctx.guest_regs.sepc
177+ // );
178+
179+ // Handle load from address 64 (ld a0, 64(zero))
180+ let addr = stval:: read ( ) ;
181+ ax_println ! ( "VmExit Reason: LoadGuestPageFault: stval {:#x} sepc: {:#x}" , addr, ctx. guest_regs. sepc) ;
182+
183+ if addr==0x40 {
184+ // Set a0 to the expected value
185+ ctx. guest_regs . gprs . set_reg ( A0 , 0x6688 ) ;
186+ // Move sepc forward by 4 bytes to skip this instruction
187+ ctx. guest_regs . sepc += 4 ;
188+ }
189+
190+ } ,
191+ Trap :: Interrupt ( Interrupt :: SupervisorTimer ) => {
192+ ax_println ! ( "VmExit Reason: SupervisorTimer interrupt at {:#x}" , ctx. guest_regs. sepc) ;
193+ // 向前推进定时器,避免立即再次触发
194+ // 然后返回 Guest
195+ return false ;
115196 } ,
116197 _ => {
117198 panic ! (
@@ -124,7 +205,6 @@ fn vmexit_handler(ctx: &mut VmCpuRegisters) -> bool {
124205 }
125206 false
126207}
127-
128208fn prepare_guest_context ( ctx : & mut VmCpuRegisters ) {
129209 // Set hstatus
130210 let mut hstatus = LocalRegisterCopy :: < usize , hstatus:: Register > :: new (
0 commit comments