zoukankan      html  css  js  c++  java
  • riscv 中断处理

    中断(中断返回)本质上也是一种跳转,只不过还需要附加一些读写CSR寄存器的操作。

    RISC-V中断分为两种类型,一种是同步中断,即ECALL、EBREAK等指令所产生的中断,另一种是异步中断,即GPIO、UART等外设产生的中断。

    1. 中断号保存在 mcause 寄存器中,最高位是 1 说明是同步异常,否则是中断
    2. mepc 储存中断前执行指令的地址,调用 mret 返回后会执行其中的地址
    3. 对于 RISCV 而言,当前运行的状态保存在mstatus 寄存器中
    • MPP 位记录当前机器模式的特权等级,0 是用户级,1 是内核级,2 保留,3 是机器级,权限最高
    • MPIE 记录触发中断前的MIE 位的值,MIE (Machine Interrupt Enable)位为 1 的时候,中断才会触发

    RISCV 不支持中断嵌套,即中断触发之后会将 mstatus 的 mie 位置 0

    中断处理的第一条指令地址存储在 mtvec 中,mie 寄存器(不是mstatus 寄存器中的mie位)控制哪些中断可以被触发,只有对应位置置一的中断号的中断会触发。

    中断处理完成之后需要返回,从机器模式的中断返回需要调用 mret 指令,它会 将 PC 设置为 mepc,通过将 mstatus 的 MPIE 域复制到MIE 来恢复之前的中断使能设置,并将权限模式设置为 mstatus 的 MPP 域中的值。

    对于中断模块设计,一种简单的方法就是当检测到中断(中断返回)信号时,先暂停整条流水线,设置跳转地址为中断入口地址,然后读、写必要的CSR寄存器(mstatus、mepc、mcause等),等读写完这些CSR寄存器后取消流水线暂停,这样处理器就可以从中断入口地址开始取指,进入中断服务程序。

    下面看tinyriscv的中断是如何设计的。中断模块所在文件:rtl/core/clint.v

    输入输出信号列表如下:

     先看中断模块是怎样判断有中断信号产生的,如下代码:

    第3~4行,复位后的状态,默认没有中断要处理。

    第6~7行,判断当前指令是否是ECALL或者EBREAK指令,如果是则设置中断状态为S_INT_SYNC_ASSERT,表示有同步中断要处理。

    第8~9行,判断是否有外设中断信号产生,如果是则设置中断状态为S_INT_ASYNC_ASSERT,表示有异步中断要处理。

    第10~11行,判断当前指令是否是MRET指令,MRET指令是中断返回指令。如果是,则设置中断状态为S_INT_MRET。

    下面就根据当前的中断状态做不同处理(读写不同的CSR寄存器),代码如下:

    第1023行,当CSR处于S_CSR_IDLE时,如果中断状态为S_INT_SYNC_ASSERT,则在第11行将CSR状态设置为S_CSR_MEPC,在第12行将当前指令地址保存下来。

    在第1323行,根据不同的指令类型,设置不同的中断码(Exception Code),这样在中断服务程序里就可以知道当前中断发生的原因了。

    第24~28行,目前tinyriscv只支持定时器这个外设中断。

    第30~31行,如果是中断返回指令,则设置CSR状态为S_CSR_MSTATUS_MRET。

    第34~48行,一个时钟切换一下CSR状态。

    接下来就是写CSR寄存器操作,需要根据上面的CSR状态来写。

    第11~15行,写mepc寄存器。

    第17~21行,写mcause寄存器。

    第23~27行,关闭全局异步中断。

    第29~33行,写mstatus寄存器。

    最后就是发出中断信号,中断信号会进入到执行阶段。

    有两种情况需要发出中断信号,一种是进入中断,另一种是退出中断。

    9~12行,写完mstatus寄存器后发出中断进入信号,中断入口地址就是mtvec寄存器的值。

    第13~15行,发出中断退出信号,中断退出地址就是mepc寄存器的值。

    编写一个 BOOT

     mret 指令

    为了使 hart 跑在监管者模式下,我们必须使用 mret 。

     参考 RISC-V 的相关资料,在处理 mret 指令时,PC 值会从 mepc 寄存器取得。因此,我们必须将 main 函数的地址存入 mepc 寄存器。

    mstatus 寄存器

    刚开始执行代码一定是机器模式,但是我们总不能一直让 hart 在机器模式下运行;此外,全局中断使能位也需要我们控制。这些都可以在 mstatus 寄存器上找到,关于 mstatus 寄存器,RISC-V 特权架构 和 RISC-V 中文手册上都有详细介绍。在此就略写几句。

    当进入 main 函数时,hart 最好要进入监管者模式。因为 main 函数事实上是我们操作系统内核最主要的函数之一,此外,我们也希望中断能被打开。对照 mstatus 寄存器的位图,我们可以在对应位域置 1 ,来打开中断或者记录信息等。

    比如,我们想先打开机器模式的中断使能,那么我们需要:

    将 mstatus.MIE 位置为 1 ,因为它代表机器模式全局下的中断使能
    将 mstatus.MPIE 位置为 1 ,它代表了在中断/异常发生前,机器模式全局下的中断使能(我们肯定不想在中断/异常发生一次后,使能就失效了吧)
    我们还要将 mstatus.MPP 位置为 01,它代表了中断/异常发生前,代码运行的模式。之所以置为 01(监管者模式),是为了在执行 mret 的时候进入监管者模式。结合之前所说的,写下如下代码:

        li   t0, (0b01 << 11) | (1 << 7) | (1 << 3)
        csrw mstatus, t0


     

        # 让其它(非0号)硬件线程挂起,跳转至 3
        csrr    t0, mhartid
        bnez    t0, 3f
        csrw    satp, zero   //关闭mmu

    这里是读取处理器的核心号码(mhartid),我们只需要使用 0 号核心进行初始化操作,非 0 的核心会跳转到后面挂起

        # 先初始化
        li      t0, (0b11 << 13) | (0b11 << 11) | (1 << 7)
        csrw    mstatus, t0
        la      t1, kernel_init
        csrw    mepc, t1
        la      t2, m_trap_vector
        csrw    mtvec, t2
        li      t3, 0xaaa
        csrw    mie, t3
        la      ra, 4f
        mret

    这里出现一个关键的指令 csrw 意思是写入状态控制寄存器。每个核心都有一系列状态控制寄存器,可以参考 RISCV 手册。下方列出的是 mstatus 状态寄存器的每个位的情况。

    • 使 FS 置位,可以开启浮点运算(不开启的话使用浮点数会报错)
    • 使 MPIE 置位,手册里的说法是,这个位储存中断前 MIE 的值,当我们从中断返回后 MPIE 会放到 MIE 中
    • 使 MPP 置 0b11, MMP 标志着当前的特权级别
    • mepc 放置 m_trap_vector 函数的地址,出发中断后会跳转到 m_trap_vector (放在 src/asm/trap.S 中)
    • 调用 mret 之后,会执行 mepc 中的地址,即 kernel_init 函数

    Rust 初始化函数

    #[no_mangle]
    extern "C" fn kernel_init(){
    ​
    }
    ​
    #[no_mangle]
    extern "C" fn kernel_start(){
    ​
    }

    RISC-V from scratch 6 

  • 相关阅读:
    java语言程序设计与数据结构(基础版)第三章**3.4
    贪心练习:阿里巴巴与十四大盗————背包问题
    贪心练习最优装载问题
    贪心训练均分纸牌Noip2002
    排队打水问题(信息学奥赛一本通贪心算法)
    PAT甲题题解-1040. Longest Symmetric String (25)-求最长回文子串
    PAT甲题题解-1039. Course List for Student (25)-建立映射+vector
    PAT甲题题解-1038. Recover the Smallest Number (30)-排序/贪心,自定义cmp函数的强大啊!!!
    PAT甲题题解-1037. Magic Coupon (25)-贪心,水
    PAT甲题题解-1036. Boys vs Girls (25)-找最大最小,大水题
  • 原文地址:https://www.cnblogs.com/dream397/p/15682726.html
Copyright © 2011-2022 走看看