rCore Lab-1

rCore Lab-1

实验一: 中断

实验题:

1.原理:在rust_main函数中,执行ebreak命令后至函数结束前,sp寄存器的值是怎样变化的?

在rust_main函数中执行ebreak进入中断,首先需要在栈上开辟Context所需空间,即将栈顶(即sp寄存器)减去 34*8 bits。随后在__restore中恢复了sp寄存器中位置。

2.分析:如果去掉 rust_main 后的 panic 会发生什么,为什么?

去掉rust_main后的panic后程序将不会立刻返回。执行ebreak函数后进入到interrupt_handler函数中,判断为断点后进入breakpoint函数进行处理,在breakpoint函数中打印出断点位置并将sepc寄存器+2后返回,调用__restore函数恢复所有寄存器,并跳转至Contextsepc的位置上,即会回到entry.asm中,此时entry.asm函数后并未做任何处理。

3.实验:

I. 如果程序访问不存在的地址,会得到 Exception::LoadFault。模仿捕获 ebreak 和时钟中断的方法,捕获 LoadFault(之后 panic 即可)

pub fn handle_interrupt(context: &mut Context, scause: Scause, stval: usize) {
    // panic!("Interrupted: {:?}", scause.cause());
    match scause.cause() {
        // breakpoint interrupt(ebark)
        Trap::Exception(Exception::Breakpoint) => breakpoint(context),
        // clock interrupt
        Trap::Interrupt(Interrupt::SupervisorTimer) => supervisor_timer(context),
        // Visit a non-existent address
        Trap::Exception(Exception::LoadFault) => load_falut(context)
        // Other Situations: Stop current thread
        _ => fault(context, scause, stval),
    };
}

match中加入对Exception::LoadFault异常的处理。在load_falut函数中直接panic!

II. 在处理异常的过程中,如果程序想要非法访问的地址是 0x0,则打印 SUCCESS!

答:

// Handler Load Fault
fn load_falut(context: &mut Context, scause: Scause, stval: usize) {
    if (stval == 0x0){
        println!("Success!")
    }
    panic!(
        "Interrupt: {:?}\n{:x?}\nstval: {:x}",
        scause.cause(),
        context,
        stval
    )
}

III. 添加或修改少量代码,使得运行时触发这个异常,并且打印出 SUCCESS!

  • 要求:不允许添加或修改任何 unsafe 代码

handle_interript函数下加入context.sepc = 0;将触发中断指令地址设置为0,即可跳转到加载地址异常。

发布于 2021-02-14 10:20