V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
amiwrong123
V2EX  ›  程序员

opensbi 里,_trap_handler 的实现,真的考虑了 异常里面进异常吗?

  •  
  •   amiwrong123 · 2 天前 · 497 次点击

    看了一下 opensbi 里,_trap_handler 的实现,里面的主体就是:

    _trap_handler:
    	TRAP_SAVE_AND_SETUP_SP_T0
    
    	TRAP_SAVE_MEPC_MSTATUS 0
    
    	TRAP_SAVE_GENERAL_REGS_EXCEPT_SP_T0
    
    	TRAP_SAVE_INFO 0 0
    
    	TRAP_CALL_C_ROUTINE
    
    	TRAP_RESTORE_GENERAL_REGS_EXCEPT_A0_T0
    
    	TRAP_RESTORE_MEPC_MSTATUS 0
    
    	TRAP_RESTORE_A0_T0
    
    	mret
    

    仔细看了这些汇编的实现,尤其是 TRAP_SAVE_AND_SETUP_SP_T0 的实现,

    .macro	TRAP_SAVE_AND_SETUP_SP_T0
    	/* Swap TP and MSCRATCH */
    	csrrw	tp, CSR_MSCRATCH, tp
    
    	/* Save T0 in scratch space */
    	REG_S	t0, SBI_SCRATCH_TMP0_OFFSET(tp)
    
    	/*
    	 * Set T0 to appropriate exception stack
    	 *
    	 * Came_From_M_Mode = ((MSTATUS.MPP < PRV_M) ? 1 : 0) - 1;
    	 * Exception_Stack = TP ^ (Came_From_M_Mode & (SP ^ TP))
    	 *
    	 * Came_From_M_Mode = 0    ==>    Exception_Stack = TP
    	 * Came_From_M_Mode = -1   ==>    Exception_Stack = SP
    	 */
    	csrr	t0, CSR_MSTATUS
    	srl	t0, t0, MSTATUS_MPP_SHIFT
    	and	t0, t0, PRV_M
    	slti	t0, t0, PRV_M
    	add	t0, t0, -1
    	xor	sp, sp, tp
    	and	t0, t0, sp
    	xor	sp, sp, tp
    	xor	t0, tp, t0
    
    	/* Save original SP on exception stack */
    	REG_S	sp, (SBI_TRAP_REGS_OFFSET(sp) - SBI_TRAP_CONTEXT_SIZE)(t0)
    
    	/* Set SP to exception stack and make room for trap context */
    	add	sp, t0, -(SBI_TRAP_CONTEXT_SIZE)
    
    	/* Restore T0 from scratch space */
    	REG_L	t0, SBI_SCRATCH_TMP0_OFFSET(tp)
    
    	/* Save T0 on stack */
    	REG_S	t0, SBI_TRAP_REGS_OFFSET(t0)(sp)
    
    	/* Swap TP and MSCRATCH */
    	csrrw	tp, CSR_MSCRATCH, tp
    .endm
    

    说白了,这段就是一个逻辑: 如果异常从 M 模式过来,那么栈就使用 tp ,也就是 scratch 空间; 如果异常从 S 模式过来,那么栈就使用 sp ,也就是 s 模式的栈空间。

    但我看了这个实现,如果进入异常后(此时处于 M ),再进入异常的话,这个栈空间就没有沿着 tp 继续增长,而是覆盖了 上一次的 tp 栈空间了。 PS:其实这里不只是异常,因为源码是使用的是 direct 模式,不是 vector 模式,所以任何 trap 包括中断和异常 都是有这个问题的。

    所以现在有这几个问题:

    1. TRAP_SAVE_AND_SETUP_SP_T0的实现,是不是就是没有考虑到异常里面进异常时的,栈空间的不停增长?
    2. 我这么考虑 异常里面进异常,是不是 没有什么实际意义?但考虑 中断嵌套的话,应该就有意义了吧?
    3. 为什么这个TRAP_SAVE_AND_SETUP_SP_T0的实现逻辑是,如果异常从 S 过来,就直接用 S 模式的栈,这是什么惯用做法吗?
    3 条回复    2025-03-17 15:36:20 +08:00
    NealLason
        1
    NealLason  
       2 天前
    先不纠结栈,先考虑什么场景下会出现异常里面进异常呢?
    我的理解,只有 OpenSBI 自身造成的异常才会导致重复进入异常吧,OpenSBI 自身运行在最高特权级别 M 模式,如果自身没有 bug ,不应出现自身造成异常的情况
    amiwrong123
        2
    amiwrong123  
    OP
       2 天前
    @NealLason #1 #1
    是的,你说的么错。只是我现在参考 OpenSBI 实现一些我自己的东西,我自己的场景,是可能出现 异常里面进异常的。

    所以,我想搞清楚 它的实现,是否有这个限制
    NealLason
        3
    NealLason  
       2 天前
    @amiwrong123 只要是进 trap handler 的时候就重新设置 sp ,那就肯定不能支持中断嵌套哎,不然之前中断栈里的上下文就被破坏了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   983 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 19ms · UTC 21:04 · PVG 05:04 · LAX 14:04 · JFK 17:04
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.