riscv笔记之:中断/异常与CSR寄存器

原文地址链接:https://www.cnblogs.com/dream397/p/15687184.html

1.riscv模式

共有三种模式:
M模式:机器模式,必须支持。通常运行boot loader或fireware
S模式:监督模式,可选,若支持,另外两种模式也须支持,该模式可运行Linux等os内核;
U模式:用户模式,实现对资源的保护,运行用户应用

*模式的切换:*上电后(reset),RISC-V架构规定,特权模式复位称为机器模式,机器模式可以通过指令mret转换称为用户模式。在RISCV中,通过“ecall”指令可以从低特权切换到高特权,在U模式下执行就切换到S模式,在S模式下调用就切换到M模式。
在RISCV中,默认产生中断和异常时,处理器自动切换到M模式处理,可以通过中断托管设置将一些中断和异常直接交给S模式处理。

2.中断与异常

在RISCV架构设计中,有一系列的控制和状态寄存器( Control and Status Registers)简称CSR。三种模式下都有对应的csr寄存器与之对应,比如M模式下命名mxxxxx,S模式下为sxxxxx。主要负责用于设置异常向量表、设置页表基址、获取异常信息等,这些寄存器大多需要通过”csr“这类指令来访问。也有一部分寄存器是通过mmio映射的,可以通过普通访存指令进行访问,比如timer寄存器。
这些寄存器中比较重要的就是中断与异常类的寄存器。

2.1 M模式下的重要csr

在这里插入图片描述
上图中的寄存器被分为四类,其中和Trap相关的寄存器比较重要,用于中断和异常处理:

信息类:主要用于获取当前芯片id和cpu核id等信息。
Trap设置:用于设置中断和异常相关寄存器。
Trap处理:用于处理中断和异常相关寄存器。
内存保护:作用类似于conterx-m中的mpu功能。

2.1.1Machine Information Registers

mvendorid、 marchid 和 mimpid 可以获取芯片制造商、架构和实现相关信息,最重要的还是 mhartid 这个寄存器,RISCV中每个cpu核都被称为一个hart,通过mhartid可以获取当前cpu核的id号。

2.1.2 Machine Trap Setup

在RISCV中,中断(interrupt)和异常(exception)被统称为trap。在arm中我们知道中断和异常是通过中断向量表中不同入口调用不同的处理函数处理的,但是在riscv中,所有中断和异常一般都是使用的同一个处理入口。在x86和arm下都存在中断向量表的概念,用于定义不同异常和中断的处理入口,但是在riscv下,一般是不存在中断向量表这个概念的,只存在trap处理入口这个概念。为了表述上的方便,后续的章节都将trap处理入口称为中断入口,但是要明白这个入口不仅仅是处理中断的,同时也是处理异常的入口。中断入口在m模式和s模式下都有专门的寄存器需要设置,在本小节我们只看m模式下的相关寄存器,在使用中断和异常处理之前需要进行一些设置,下面就来看看这些寄存器如何设置。
mtvec mstatus mie medeleg 和 mideleg

  • mtvec
    riscv支持向量中断和非向量中断两种编程模型, 非向量中断,也就是中断发生后,所有的入口只有一个,不固定偏移。
    mtvec寄存器全名为Machine Trap-Vector Base-Address Register,用于设置中断入口地址,其寄存器格式如下
    在这里插入图片描述

    可以看出mtvec需要中断入口地址是4字节对齐的,因为最低两个bit是用于设置中断模式的,其模式定义如下:

在这里插入图片描述
Direct模式:所有的中断和异常使用同一个中断入口地址,一般都会设置为这种模式。
Vectored模式:所有异常使用同一个入口地址,但是不同的中断使用不同的入口地址。

  • mstatus
    这个寄存器顾名思义是用来控制cpu核当前的一些状态信息的,比如全局中断使能等,寄存器的格式如下:
    在这里插入图片描述
    红框内的位域用来控制全局中断的使能,SIE控制S模式下全局中断,MIE控制M模式下全局中断。这个有点像arm里cpsr中的F位,只是在RISCV架构下还分为S模式和M模式来控制,像但是不完全像。
    绿框里的位域用来记录发生中断之前MIE和SIE的值。SPIE记录的是SIE的值,MPIE记录的是MIE的值。
    蓝色框内位域用来记录当特权级别由低到高发生变化时(比如执行ecall指令),之前的特权级别。当变化后的特权级别是S模式时,SPP表示变化之前的特权级别是S模式还是U模式,所以只需要1位就可以表示;当变化后的特权级别是M模式时,MPP表示变化之前是S模式还是U模式还是M模式,由于有三种情况,所以需要使用2位来表示。
    **注意:**当发生中断时,SIE和MIE被硬件自动设置为0,用来屏蔽中断,这个行为和大部分架构都一样,同时MPIE和SPIE被硬件自动设置为MIE和SIE的值,如果特权级别还发生改变的话,之前的特权级别是记录在SPP或者MPP中的。当从中断中返回时,SIE和MIE被自动设置为MPIE和SPIE的值,同时MPIE和SPIE被自动设置为1,特权级别恢复为MPP或者SPP记录的级别,然后MPP或者SPP被设置为U模式。
    (也就是说mstatus寄存器在中断前后的设置都是自动设置完成的)
  • mie
    riscv中断:在RISCV下,将中断(interrupt)又细分为三种类型:定时中断(timer)核间中断(soft)、中断控制器中断(external)。定时中断可以用于产生系统的tick,核间中断用于不同cpu核之间通信,中断控制器则负责所有外设中断。这个设计和arm下有点不一样,在arm多核下,架构中的定时器中断、核间中断和外设中断都是统一由中断控制器管理的,而在RISCV中定时器和核间中断是分离出来的,这两个中断被称为CLINT(Core Local Interrupt),而管理其他外设中断的中断控制器则被称为PLIC(Platform-Level Interrupt Controller)。每个核都有自己的定时器和产生核间中断的寄存器可以设置,这些寄存器的访问不同于其他的控制状态寄存器,采用的是MMIO映射方式访问,比如下图所示为SIFIVE FU540的CLINT寄存器表:
    在这里插入图片描述
    图中的msip用于产生m模式下的核间中断,mtime可以读取出当前计数器的值,mtimecmp用于设置比较值,当mtime的值增加到mtimecmp的值时就可以产生中断。
    之前说的mstatus寄存器控制的是cpu全局状态信息,包括控制M/S模式下全局的中断的使能,而mie寄存器控制的是具体M模式下三种类型中断的使能。也就是mstatus寄存器M模式中断使能的前提下,mie中断类型使能的设置才能生效。mie寄存器格式如下:
    在这里插入图片描述
    MSIE、MTIE、MEIE这三个位域分别控制m模式下核间中断、定时中断、中断控制器中断的使能状态。
    SSIE、STIE、SEIE这三个位域分别控制s模式下核间中断、定时中断、中断控制器中断的使能状态。
  • medeleg 和 mideleg
    RISCV下默认所有中断和异常都是在m模式下处理的,但是有些时候我们需要将中断和异常直接交给s模式处理,这就是RISCV中的中断托管机制。通过mideleg寄存器,可以将三种中断交给s模式处理,通过medeleg寄存器,可以将异常交给s模式处理。下面来具体看看这些寄存器格式。

bit[1]用于控制是否将核间中断交给s模式处理。
bit[5]用于控制是否将定时中断交给s模式处理。
bit[9]用于控制是否将中断控制器管理的中断交给s模式处理。
注意对于核间中断和定时中断而言,即使使能了mideleg中对应的bit位,当产生相应中断时,还是先进入m模式进行处理,然后可以通过设置mip寄存器(下一小节讲解),在退出m模式中断时就可以进入s模式的中断处理函数中处理。
在这里插入图片描述

当我们想把异常交给s模式处理时,我们可以设置medelrg寄存器,这个寄存器格式如下:
在这里插入图片描述
可以看出来有很多异常是可以设置到s模式下处理的,但是实际使用时并不是所有异常都要交给s模式处理的,比如bit[9]代表的异常还是要交给m模式处理,因为像获取芯片id、cpu核id、设置timer等操作只能在m模式下进行,所以s模式通过SBI接口(后面会讲)使用“ecall”切换到m模式调用不同的服务,所以bit[9]代表的异常必须被m模式处理而不能交给s模式处理。

2.1.3 Machine Trap Handling

当产生中断或者异常时,会有一些信息保存在相应的寄存器中,下面我们就一起来看看这些寄存器。

在arm架构中,当发生中断或异常时,硬件自动将要返回的地址保存在lr寄存器中。类似的,在RISCV下产生中断或异常时,硬件自动将返回地址保存在mepc寄存器中,当在中断处理中返回时,硬件自动将mepc中的地址赋值给pc运行。
要注意的时,在RISCV架构中,当产生异常时,mepc中保存的是产生异常那条指令的地址,而不是其下一条指令地址,这么设计的原因是希望产生异常时,软件开发人员对相应异常做出处理,当处理完之后再次给一个运行之前产生异常指令的机会,比如缺页异常就是通过这种机制来运行的。当不需要再次运行产生异常那条指令时,需要在中断处理时手动将mepc的值加4,这样中断返回时就是运行产生异常那条指令的下一条指令。当产生的是中断时,mepc直接保存的就是被中断指令的下一条指令的地址,所以需要做修正。
即:产生异常时:mepc保存产生异常那条指令
产生中断时:mepc保存产生中断下一条指令

mcause mtval

- mcause
当产生中断和异常时,mcause寄存器中会记录当前产生的中断或者异常类型
在这里插入图片描述
寄存器的最高位用来表示产生的是中断还是异常,1表示中断0表示异常。剩下的位域表示中断或者异常的具体类型,如下所示:
在这里插入图片描述

  • mip
    这个寄存器可以表明当前是否产生了某种中断,其实就是mie或sie的直接反应,其格式如下所示。
    在这里插入图片描述
    MSIP表示m模式核间中断,此位只读,其状态反应的是CLINT中对应的核间中断设置寄存器最低位的状态,设置CLINT核间中断设置寄存器最低位为1则产生核间中断,置0则清除核间中断。
    MTIP表示m模式定时中断,此位只读,其状态通过设置CLINT中对应的mtimecmp寄存器来清零。
    MEIP表示m模式中断控制器中断,此位只读,其状态通过具体的中断控制器寄存器设置来清零。
    SSIP表示s模式核间中断,此位在s模式只读(s模式下有sip寄存器,下面会讲),在m模式下可读写,通过设置此位,可以进入s模式核间中断处理。
    STIP表示s模式定时中断,此位在m模式下可读写,通过设置此位,可以进入s模式定时中断处理。
    SEIP表示s模式中断控制器中断,此位在m模式下可读写,通过设置此位,可以进入s模式中断控制器中断处理。

2.2 S模式下重要的CSR

S模式下的CSR寄存器大部分都和M模式下的类似,只不过是可以在s模式下进行访问而已。因为在m模式可以访问其他模式下的寄存器,在其他模式下只能访问他自己模式下的csr寄存器。S模式下的一些csr寄存器如下所示。
在这里插入图片描述
可以看出大部分的寄存器都和m模式下的类似,作用也是一样的,这里就不再赘述了。我们这里看一个m模式下没有的寄存器satp,这个寄存器是s模式下用来设置页表基址的,其格式如下。

在这里插入图片描述

PPN位域用于填写页表在内存中的物理基址。
ASID可以先不关心,当作都为0。
MODE位域用来选择是否开启页表,如果是64位还用来选择虚拟地址翻译的位数,如下:
在这里插入图片描述
果是0 表示禁用页表翻译功能,64位架构下一般虚拟地址选用sv39。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值