第1章:RISC-V特权架构:机器模式、监督模式、用户模式、CSR寄存器介绍、异常与中断向量表

大家好,我是你们的老朋友。今天咱们来聊聊RISC-V的特权架构。说实话,这部分内容是我当年啃RISC-V手册时最头疼的章节之一。但搞懂它,你才能真正理解一个操作系统是怎么跑起来的。

为什么这么说?你想想看,CPU不能一直让用户程序为所欲为吧?总得有个机制来保护系统。RISC-V的特权架构,说白了就是给CPU分了几个「权限等级」。不同等级能做的事不一样,低等级想干高等级的事?门都没有。

1.1 三种特权模式

RISC-V定义了三种特权模式,从高到低分别是:

  • 机器模式(M模式):最高权限,啥都能干。复位后CPU默认就在这个模式。
  • 监督模式(S模式):操作系统内核运行的地方。能访问页表、处理中断。
  • 用户模式(U模式):应用程序待的地方。权限最低,想碰硬件?得求着内核帮忙。

我刚开始做RISC-V项目时,犯过一个低级错误:在U模式下直接去写一个CSR寄存器。结果呢?CPU直接抛异常给我看。嗯,从那以后我就记住了——权限不是闹着玩的。

核心要点:M模式是「上帝模式」,S模式是「内核模式」,U模式是「用户模式」。系统调用就是U模式请求S模式帮忙干活的过程。

1.2 模式切换与异常处理

模式之间怎么切换?主要有两种方式:

  1. 异常(Exception):程序自己搞出来的问题,比如除零、非法指令。
  2. 中断(Interrupt):外部设备发来的信号,比如网卡说「我有数据了」。

不管是异常还是中断,CPU都会干一件事:提升特权级。比如U模式下发生异常,CPU会跳到S模式或M模式去处理。处理完了再回来继续执行。

我记得有一次调试一个驱动,死活进不了中断处理函数。查了半天,发现是中断向量表配置错了。这种坑,我踩过不止一次。

1.3 CSR寄存器家族

CSR(Control and Status Register)是RISC-V里一类特殊的寄存器。它们控制着CPU的核心行为。我习惯把它们分成三类:

类别 典型寄存器 作用
机器模式 mstatus, mtvec, mepc, mcause M模式下的状态、异常向量、异常PC、异常原因
监督模式 sstatus, stvec, sepc, scause S模式下的对应功能
用户模式 (几乎没有) U模式基本碰不到CSR

这里我特别想强调一下mtvec和stvec。这两个寄存器存的是异常/中断向量表的基地址。CPU一旦发生异常,就会跳到这里去找处理函数。

我的小技巧:写启动代码时,第一件事就是设置好mtvec。否则一旦发生异常,CPU就不知道往哪跳了。我曾经因为这个原因,调试了一个下午。

1.4 异常与中断向量表

向量表,说白了就是一个跳转表。每个异常或中断都有一个编号(叫cause),CPU根据这个编号去查表,找到对应的处理函数。

RISC-V的向量表有两种模式:

  • 直接模式(Direct):所有异常都跳到同一个入口。你得自己在入口处判断是哪种异常。
  • 向量模式(Vectored):每个异常有独立的入口。CPU直接跳过去,省了判断的步骤。

我个人更推荐向量模式。为什么?省一个分支判断,性能好一点。在微内核这种对性能敏感的场景下,这点优化值得做。

来看一个简单的向量表示例:

.section .text.vector
.align 2
.globl _start_vector

_start_vector:
    j handle_supervisor_soft     // 软件中断
    j handle_supervisor_timer    // 定时器中断
    j handle_supervisor_external // 外部设备中断
    // ... 其他异常入口

你看,每个中断源都有自己的入口。CPU根据cause寄存器的值,自动选择跳转到哪个入口。

注意:向量表的地址必须对齐。RISC-V要求向量表基地址按4字节对齐。如果你用向量模式,对齐要求更严格。我见过有人因为对齐问题,导致中断跳转到了错误的地方。

1.5 从微内核角度看特权架构

好了,聊了这么多基础概念,咱们回到微内核上。微内核的核心思想是:把最少的代码放在S模式,把最多的代码放在U模式。

具体来说:

  • S模式只放一个微小的内核,负责进程调度、IPC、中断处理。
  • U模式放各种服务:文件系统、网络协议栈、设备驱动。

这样做的好处是啥?隔离性好。驱动崩了?不影响内核。文件系统挂了?重启服务就行,不用重启整个系统。

但代价也很明显:U模式的服务想访问硬件,必须通过系统调用切换到S模式。这个切换是有开销的。我当年做性能测试时,发现系统调用开销占了总时间的30%以上。嗯,优化空间很大。

所以,理解RISC-V的特权架构,是做好微内核的第一步。你只有知道CPU怎么切换模式、怎么处理异常,才能设计出高效的系统调用机制。

下一章,咱们就正式开始写代码,实现第一个系统调用。到时候你会看到,今天讲的这些概念,全都会用上。