ch10-Trap和Exception

376 阅读3分钟

控制流(Control Flow)和 Trap

image-20210815222458303

RISC-V Trap 处理中涉及的寄存器

image-20210815222516807

image-20210815222616171

1.mtvec(Machine Trap-Vector Base-Address)

  • 异常向量表的基址

image-20210815222742766

  • mtvec分为两个部分
    1. Base:trap入口函数的基地址 (由于是保证4字节对齐,所以后面两个bit可以用于别的功能)
    2. Mode:分为Direct和Vectored
      1. Direct:所有的异常,pc都是直接指向这个Base地址.
      2. Vectored:BASE只是这个数组的基地址,然后根据cause去决定数组的下标.

2.mepc(Machine Exception Program Counter)

  • 当trap发生时,pc会变成异常处理代码的地址,同时hart会设置mepc当前指令或者下一条指令的地址,当需要退出trap的时候,执行mret指令,可以将mepc赋值给pc,从而回到原本的执行流.

image-20210815223620993

3.mcause(Machine Cause)

  • trap的原因.

image-20210815224137719

  • trap时,hart会设置该寄存器来通知trap的原因(scause 不足以存下中断所有的必须信息。例如缺页异常,就会将 stval 设置成需要访问但是不在内存中的地址,以便于操作系统将这个地址所在的页面加载进来。)

image-20210815224310636

4.mtval(Machine Trap Value)

  • 指定这个mcause的时候,可能信息还不够,mtval传递补充的信息.

image-20210815224523143

5.mstatus(Machine Status)

  • 描述状态信息

image-20210815224619381

异常发生时,权限级别总是往高了跳,不会往下跳。 实际上,中断的时候,总是跳往M模式下.

这里我们要学的是,主要分成三组信息:

  • xIE(x=M/S/U) <IE:Interupt Enabled:中断使能位>

    中断使能位1:开中断

    中断使能位0:关中断

  • xPIE(x=M/S/U) <PIE:Previous Interupt Enabled:保存上一个的xIE的值>

    在陷入trap的时候,会先将当前的中断使能位保存到PIE中,trap执行结束后,将PIE恢复到IE.

  • xPP(x=M/S) <PP:Previous Privilege:保存trap发生前的权限级别值>

6.mscratch(当前控制流的context的指针)

RISC-V Trap 处理流程

image-20210815230153941

  • Trap初始化:比如设置trap入口基地址
  • Trap的上半部分:是在硬件内部发生的,是硬件的一套处理逻辑。硬件的控制处理完了,才会跳到软件部分——即Trap的下半部分
  • Trap的下半部分:是我们写的处理trap的一套软件逻辑。
  • 从Trap返回.

1.Trap初始化

image-20210815230454535

设置mtvec寄存器:

extern void trap_vector(void);

void trap_init()
{
	/*
	 * set the trap-vector base-address for machine-mode
	 */
	w_mtvec((reg_t)trap_vector);
}

trap_vector的代码:

trap_vector:
	# save context(registers).
	csrrw	t6, mscratch, t6	# swap t6 and mscratch
	reg_save t6
	csrw	mscratch, t6

	# call the C trap handler in trap.c
	csrr	a0, mepc
	csrr	a1, mcause
	call	trap_handler
	# trap_handler的返回值是正常控制流的PC值

	# 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

2.Top Half

image-20210815231433731

Trap时,Hart会自动执行如下:

  • MPIE = MIE ,MIE = 0 (即禁止中断)[这个非常重要!!!!]

  • 设置mepc为正常执行流的指令地址,同时PC被设置为mtvec

    注意:

    • 对于Exception,mepc指向异常的指令.
    • 对于Interrupt,mepc指向下一条指令.
  • 设置mcausemtval

  • 将trap发生之前的权限模式保存在mstatus的MPP中,再把hart权限模式更改为M.

3.Bottom Half

image-20210815232555936

4.退出trap

image-20210815232831013

Mret指令会做这些事情:

  1. 恢复Hart的权限级别为MPP
  2. 恢复Hart的MIE为MPIE,MPIE=1
  3. pc=mepc