RISC-V 异常和中断

RISC-V 异常和中断

[TOC]

RISC-V Exception & Interrupt

RISC-V 特权等级:

Level Encoding Name Abbreviation
0 00 User/Application U
1 01 Supervisor S
2 10 Reserved
3 11 Machine M

RISC-V 支持的特权模式组合:

组合序号 支持的模式 应用场景
1 M 简单的嵌入式系统
2 M, U 有安全支持的嵌入式系统
3 M, S, U 能跑操作系统如 Linux(支持虚拟内存)

CSR 指令

CSR 指令格式 31, 20 19, 15 14, 12 11, 7 6, 0
CSR rs1 funct3 rd opcode
CSRRW CSR Index source 001 rd 1110011
CSRRS CSR Index source 010 rd 1110011
CSRRC CSR Index source 011 rd 1110011
CSRRWI CSR Index unsigned imm 101 rd 1110011
CSRRSI CSR Index unsigned imm 110 rd 1110011
CSRRCI CSR Index unsigned imm 111 rd 1110011
指令 说明 数学表达
CSRRW(Write) 取出 csr 寄存器里的值,零拓展为 32 位后存到 rd 寄存器里;将 rs1 寄存器里的值存到 crs 寄存器里 \(x[rd]=zeroExt(crs[index]),\\ csr[index] = x[rs1]\)
CSRRS(Set) 取出 csr 寄存器里的值,零拓展为 32 位后存到 rd 寄存器里;若 rs1 寄存器里某一位是 1,则将 crs 寄存器对应位置 1,负责 csr 对应位不变 \(x[rd]=zeroExt(crs[index]),\\ csr[index] \| = x[rs1]\)
CSRRC(Clear) 取出 csr 寄存器里的值,零拓展为 32 位后存到 rd 寄存器里;若 rs1 寄存器里某一位是 1,则将 crs 寄存器对应位清零,负责 csr 对应位不变 \(x[rd]=zeroExt(crs[index]),\\ csr[index]\&= !x[rs1]\)
CSRRWI 将 rs1 寄存器替换成无符号立即数 \(x[rd]=zeroExt(crs[index]),\\ csr[index] = zeroExt(imm)\)
CSRRSI 将 rs1 寄存器替换成无符号立即数 \(x[rd]=zeroExt(crs[index]),\\ csr[index] \| = zeroExt(imm)\)
CSRRCI 将 rs1 寄存器替换成无符号立即数 \(x[rd]=zeroExt(crs[index]),\\ csr[index]\&= !zeroExt(imm)]\)

Trap 相关控制寄存器

Trap Setup:

寄存器 描述 长度
mstatus 跟踪和控制 hart 的当前运行状态 XLEN
mtvec (trap vector base address): 表明 trap 发生的时候,PC 需要跳转的地址 XLEN
mie (interrupt enable): 用于进一步控制(打开和关闭)software interrupt/timer interrupt/external interrupt XLEN

image-20230627132133032 mstatus寄存器中的:

  • xIE字段用于控制全局中断使能;高级模式的中断关闭之后,比它等级低的中断都会关闭、低级模式的中断打开之后,比它等级高的中断都会打开
  • xPIE(previous interrupt enable)字段用于存储 trap 发上之前 hart 的中断使能
  • xPP(previous privilege)字段存储进入 trap 之前 hart 所处的特权模式

image-20230627132143581 mtvec寄存器中的:

  • BASE字段必须是 4byte 对齐

  • MODE

    • 0 for direct: pc=BASE, 中断发生的时候会跳到这个固定的地址
    • 1 for vectored: pc=BASE+4*cause, 中断发生的时候,会根据中断类型,跳到不同的地址 例:当machine time interrupt发生的时候,已知其对应的 mcause=111,故pc=BASE+(111<<2)=BASE+0x1C
    • \(\ge 2\): Reserved

    PS: RISC-V 中的指令都是 little endian

image-20230627132155502 mie(ie for interrupt enable)寄存器中的每 bit 指定 mcause 中的各种类型的 trap 是否打开

Trap Handling:

在 RISC-V 架构中,并没有定义进入和退出中断处理时硬件自动保存和恢复现场的机制, 用户需要用软件主动保护和恢复程序现场。在发生中断时,拉低 mstatus 寄存器的 MIE 域屏蔽全局中断, 也是为了软件保存和恢复现场的过程不 会被更高级别的中断打断,导致数据的丢失。

寄存器 描述 长度
mcause (trap cause): 记录导致 trap 的原因 XLEN
mtval (trap value): 补充 trap 发生 的额外信息 XLEN
mepc (exception pc): 保存 trap 发生时的 PC 到该寄存器里, 32 处理器下其 lsm[1:0]=00 XLEN
mip (interrupt pending): 它列出目前已发生等待处理的中断 XLEN
mscratch (scratch): 一般用于指向某 M 模式的上下文空间 XLEN

image-20230627132214997 mip(ip for interrupt pending)寄存器中的每 bit 判断 mcause 中的各种类型的 trap 是否 pending

image-20230627132224817 mcause最高位=1,表明 trap 是 interrupt,否则 trap 是 exception

Time/Counter

寄存器 描述 长度
mcycle (machine cycle counter): 记录该 hard 运行的 cycle 数 64
minstret (machine instruction retired counter): 记录执行完毕的指令数 64
mtime M 模式按时自增的计时器 64
mtimecmp 比较计时器,当 mtime\(/ge\)mtimecmp 时会触发 timer interrupt 64

Trap 类型

Trap 类型有mcause寄存器指出,其中最高位为 1 表明是 interrupt,为 0 表示是 exception

Interrupt Exception Code Description
1
1
1
1
0
1
2
3
Reserved
Supervisor software interrupt
Reserved
Machine software interrupt
1
1
1
1
4
5
6
7
Reserved
Supervisor timer interrupt
Reserved
Machine timer interrupt
1
1
1
1
8
9
10
11
Reserved
Supervisor external interrupt
Reserved
Machine external interrupt
1
1
12–15
≥16
Reserved
Designated for platform use
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16–23
24–31
32–47
48–63
≥64
Instruction address misaligned
Instruction access fault
Illegal instruction
Breakpoint <- EBREAK
Load address misaligned
Load access fault
Store/AMO address misaligned
Store/AMO access fault
Environment call from U-mode <- ECALL
Environment call from S-mode <- ECALL
Reserved
Environment call from M-mode <- ECALL
Instruction page fault
Load page fault
Reserved
Store/AMO page fault
Reserved
Designated for custom use
Reserved
Designated for custom use
Reserved
  1. Illegal Instruction Exception:
    • 访问不存在的 CSR
    • Write to read only CSR
    • 低特权级别尝试访问高级别的 CSR

通过上表可以看出:

  • interrupt 主要有三种,分别是:software interrupt, timer interruptexternal interrupt,在三种模式M, S, U下都有对应的 interrupt.
  • exception 主要有五种,分别是:instruction, load/store, environment call, page faultbreakpoint
    exception 的优先级从上到下依次递减,如果同时发生了多个 exception,则优先级高的被处理
Priority Exc. Code Description
Highest 3 Instruction address breakpoint
12, 1 During instruction address translation:First encountered page fault or access fault
1 With physical address for instruction:Instruction access fault
2
0
8, 9, 11
3
3
Illegal instruction
Instruction address misaligned
Environment call
Environment break
Load/store/AMO address breakpoint
4, 6 Optionally:Load/store/AMO address misaligned
13, 15, 5, 7 During address translation for an explicit memory access:First encountered page fault or access fault
5, 7 With physical address for an explicit memory access:Load/store/AMO access fault
Lowest 4, 6 If not higher priority:Load/store/AMO address misaligned

Trap 处理流程

image-20230627132243657 1. 初始化: 将trap_vector的地址存储到mtvec,这样当trap发生的时候,pc可以自动跳转到该地址去执行trap处理程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
trap_vector:
# save context(registers).
csrrw t6, mscratch, t6 # swap t6 and mscratch
reg_save t6

# Save the actual t6 register, which we swapped into
# mscratch
mv t5, t6 # t5 points to the context of current task
csrr t6, mscratch # read t6 back from mscratch
sw t6, 120(t5) # save t6 with t5 as base

# Restore the context pointer into mscratch
csrw mscratch, t5

# call the C trap handler in trap.c
csrr a0, mepc
csrr a1, mcause
call trap_handler # call C functions to solve trap

# trap_handler will return the return address via a0.
csrw mepc, a0

# restore context(registers).
csrr t6, mscratch
reg_restore t6

# return to whatever we were doing before trap.
MRET

  1. TOP Half, 一些硬件自动做的工作,更新 csr 的信息

    • 针对mstatus: \(MPIE=MIE, MIE=0\)
    • 如果 trap 是 interrupt 则mepc=pc+1; 如果 trap 是 exception 则mepc=pc
    • pc=mtvec
    • 根据 trap 发生之前所处的特权等级去设置mstatus的 MPP 字段,进入到 M 模式
  2. Botton Half: 执行 trap_handler

    • 保存(save)当前控制流的上下文信息(利用 mscratch)
    • 调用 C 语言的 trap_handler
    • 从 trap_handler 函数返回, mepc 的值有可能需要调整
    • 恢复(restore)上下文的信息
    • 执行 MRET 指令返回到 trap 之前的状态。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    reg_t trap_handler(reg_t epc, reg_t cause)
    {
    reg_t return_pc = epc;
    reg_t cause_code = cause & 0xfff;

    if (cause & 0x80000000) {
    /* Asynchronous trap - interrupt */
    switch (cause_code) {
    case 3:
    uart_puts("software interruption!\n");
    break;
    case 7:
    uart_puts("timer interruption!\n");
    break;
    case 11:
    uart_puts("external interruption!\n");
    break;
    default:
    uart_puts("unknown async exception!\n");
    break;
    }
    } else {
    /* Synchronous trap - exception */
    printf("Sync exceptions!, code = %d\n", cause_code);
    panic("OOPS! What can I do!");
    //return_pc += 4;
    }
    return return_pc;
    }
  3. 返回:执行 xRET 指令

    • 在不同特权模式下退出有对应的 ret 指令,如: mret, sret, uret
    • mret 硬件将会执行如下操作:
      • 更改当前 hart 的特权模式为 mstatus.MPP
      • mstatus.MIE=mstatus.MPIE, mstatus.MPIE=1
      • pc=mepc
image-20230627132301742

Trap处理加速

中断响应是嵌入式微控制器的关键特性之一。 中断响应时间指的是从中断设备产生中断信号到处理器开始执行中断服务程序(Interrupt Service Routine, ISR) 中的第一条指令所花费的时间。 拥有快速的中断响应对于嵌入式处理器而言至关重要。

  1. 加速中断的方法

    • 扩展了硬件自动保存和恢复现场和全局中断硬件屏蔽设计
    • 支持自动的中断嵌套缩短了中断响应时间,减少了软件的开销
    • 除此之外,还增加了中断尾链设计,进一步提升了处理器响应中断的性能
  2. RISC-V 中断为什么慢?

    • RISC-V 硬件不会自动保存现场,需要使用软件去手动保存现场,增加了很多的 cycle
    • RISC-V 默认不支持中断嵌套,如果需要支持中断嵌套,需要使用软件对 CSR 寄存器进行操作,增加了 cycle

    将软件的工作用硬件来实现,可以降低中断整体的时间近 1/3

References

  1. The RISC-V Instruction Set Manual Volume I: Unprivileged ISA, Chapter 9 “Zicsr”, Control and Status Register (CSR)
  2. The RISC-V Instruction Set Manual Volume II: Privileged Architecture, Chapter 3 Machine-Level ISA
  3. Writing a RISC-V Emulator in Rust: Control and Status Register
  4. RISC-V Bytes: Privilege Levels
  5. 用于计量的嵌入式 RISC-V 处理器设计及 MCU 实现