From bfff7a842b43935ed6b733c6b5305e120ce850a2 Mon Sep 17 00:00:00 2001 From: tfx2001 Date: Thu, 25 Jul 2024 02:09:25 +0800 Subject: [PATCH] fix: illegal instruction delegate context switch error Fix context switch error when delegate illegal instruction to S-Mode. 1. Sepc should be assigned the value of mepc, 2. Assign mstatus::MPP to sstatus::SPP to make sure kernel can know the correct privilege level before trap. 3. mstatus::MPP update to S-Mode to make sure back to S-Mode when mret to let kernel handle the exception. Signed-off-by: tfx2001 --- src/trap.rs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/trap.rs b/src/trap.rs index 183e8ac..637380c 100644 --- a/src/trap.rs +++ b/src/trap.rs @@ -23,12 +23,21 @@ fn boot(mut ctx: FastContext, start_addr: usize, opaque: usize) -> FastResult { } #[inline] -fn delegate(ctx: &mut FastContext) { +fn delegate() { unsafe { - sepc::write(ctx.regs().pc); + sepc::write(mepc::read()); scause::write(mcause::read().bits()); stval::write(mtval::read()); sstatus::clear_sie(); + if mstatus::read() & mstatus::MPP == mstatus::MPP_SUPERVISOR { + sstatus::set_spp(sstatus::SPP::Supervisor); + } else { + sstatus::set_spp(sstatus::SPP::User); + } + mstatus::update(|bits| { + *bits &= !mstatus::MPP; + *bits |= mstatus::MPP_SUPERVISOR; + }); mepc::write(stvec::read().address()); } } @@ -132,13 +141,12 @@ pub extern "C" fn fast_handler( break ctx.restore(); } T::Exception(E::IllegalInstruction) => { - if mstatus::read() & mstatus::MPP != mstatus::MPP_SUPERVISOR { - panic!("only can handle illegal instruction exception from S-MODE"); + if mstatus::read() & mstatus::MPP == mstatus::MPP_MACHINE { + panic!("Illegal instruction exception from M-MODE"); } - ctx.regs().a = [ctx.a0(), a1, a2, a3, a4, a5, a6, a7]; if !illegal_instruction_handler(&mut ctx) { - delegate(&mut ctx); + delegate(); } break ctx.restore(); }