Skip to content

Commit 201bfe2

Browse files
fix bug: 'cargo qemu --ch 2 --release' is hung
1 parent 2912caa commit 201bfe2

2 files changed

Lines changed: 18 additions & 9 deletions

File tree

ch2/src/main.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@ extern "C" fn rust_main() -> ! {
3333
log::info!("load app{i} to {app_base:#x}");
3434
// 初始化上下文
3535
let mut ctx = LocalContext::user(app_base);
36-
// 设置用户栈
37-
let mut user_stack = [0usize; 256];
38-
*ctx.sp_mut() = user_stack.as_mut_ptr() as usize + core::mem::size_of_val(&user_stack);
39-
// 执行应用程序
36+
// 设置用户栈(使用 MaybeUninit 避免 release 模式下零初始化的问题)
37+
let mut user_stack: core::mem::MaybeUninit<[usize; 256]> = core::mem::MaybeUninit::uninit();
38+
let user_stack_ptr = user_stack.as_mut_ptr() as *mut usize;
39+
*ctx.sp_mut() = unsafe { user_stack_ptr.add(256) } as usize;
4040
loop {
4141
unsafe { ctx.execute() };
4242

@@ -56,6 +56,8 @@ extern "C" fn rust_main() -> ! {
5656
unsafe { core::arch::asm!("fence.i") };
5757
break;
5858
}
59+
// 防止 user_stack 被优化
60+
let _ = core::hint::black_box(&user_stack);
5961
println!();
6062
}
6163

kernel-context/src/lib.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -129,27 +129,34 @@ impl LocalContext {
129129
/// # Safety
130130
///
131131
/// 将修改 `sscratch`、`sepc`、`sstatus` 和 `stvec`。
132-
#[inline]
132+
#[inline(never)]
133133
pub unsafe fn execute(&mut self) -> usize {
134134
let mut sstatus = build_sstatus(self.supervisor, self.interrupt);
135+
// 保存 self 指针和 sepc,避免 release 模式下 csrrw 破坏寄存器后的问题
136+
let ctx_ptr = self as *mut Self;
137+
let mut sepc = self.sepc;
138+
let old_sscratch: usize;
135139
core::arch::asm!(
136-
" csrrw {sscratch}, sscratch, {sscratch}
140+
" csrrw {old_ss}, sscratch, {ctx}
137141
csrw sepc , {sepc}
138142
csrw sstatus , {sstatus}
139143
addi sp, sp, -8
140144
sd ra, (sp)
141145
call {execute_naked}
142146
ld ra, (sp)
143147
addi sp, sp, 8
144-
csrw sscratch, {sscratch}
148+
csrw sscratch, {old_ss}
145149
csrr {sepc} , sepc
146150
csrr {sstatus}, sstatus
147151
",
148-
sscratch = in (reg) self,
149-
sepc = inlateout(reg) self.sepc,
152+
ctx = in (reg) ctx_ptr,
153+
old_ss = out (reg) old_sscratch,
154+
sepc = inlateout(reg) sepc,
150155
sstatus = inlateout(reg) sstatus,
151156
execute_naked = sym execute_naked,
152157
);
158+
let _ = old_sscratch; // suppress unused warning
159+
(*ctx_ptr).sepc = sepc;
153160
sstatus
154161
}
155162
}

0 commit comments

Comments
 (0)