Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

【提问】RT-Thread编译后出现supervisor特权级的CSR #19

Open
shili2017 opened this issue Aug 24, 2021 · 2 comments
Open

【提问】RT-Thread编译后出现supervisor特权级的CSR #19

shili2017 opened this issue Aug 24, 2021 · 2 comments

Comments

@shili2017
Copy link

按照教程编译OSCPU/rt-thread之后,把elf文件dump了一下,发现有如下指令。

    80008f74:	9e850513          	addi	a0,a0,-1560 # 80016958 <rt_data_queue_deinit+0x12e8>
    80008f78:	e3dfd0ef          	jal	ra,80006db4 <rt_kprintf>
    80008f7c:	180027f3          	csrr	a5,satp
    80008f80:	fef43023          	sd	a5,-32(s0)
    80008f84:	fe043783          	ld	a5,-32(s0)

查阅指令集文档得知satp是supervisor特权级的CSR,是否意味着需要对rt-thread代码做进一步修改?

@shili2017
Copy link
Author

shili2017 commented Aug 24, 2021

相关源代码在rt-thread/libcpu/risc-v/virt64/interrupt.c:158
个人认为可以直接删去satp有关代码,不会影响rt-thread运行。

@5265325
Copy link
Collaborator

5265325 commented Aug 30, 2021

该指令在函数dump_regs中,可在rt-thread/libcpu/risc-v/virt64/interrupt.c中找到该函数。
当异常发生时,首先陷入mtvec寄存器存放的异常回调函数trap_entry中,该函数首先保存上下文。

/* save thread context to thread stack */
addi sp, sp, -32 * REGBYTES

STORE x1,   1 * REGBYTES(sp)

csrr  x1, SRC_XSTATUS
STORE x1,   2 * REGBYTES(sp)

csrr  x1, SRC_XEPC
STORE x1, 0 * REGBYTES(sp)

STORE x4,   4 * REGBYTES(sp)
STORE x5,   5 * REGBYTES(sp)
STORE x6,   6 * REGBYTES(sp)
........

然后调用rt_interrupt_enter告知内核进入中断。

/* handle interrupt */
call  rt_interrupt_enter
csrr  a0, SRC_XCAUSE
csrr  a1, SRC_XEPC
mv    a2, s0
call  handle_trap
call  rt_interrupt_leave

如果之前调用过rt_interrupt_enter_sethook设置了中断钩子函数,那么此时中断钩子函数将被调用。之后调用handle_trap函数由内核进行一系列异常处理,其中就包括检测异常陷入原因。如果异常导致的陷入(mcause最高位为0),并且陷入原因不在预期之内。

switch (cause)
{
    case CAUSE_MISALIGNED_FETCH:
        rt_kprintf("Instruction address misaligned");
        break;
    case CAUSE_FAULT_FETCH:
        rt_kprintf("Instruction access fault");
        break;
    case CAUSE_ILLEGAL_INSTRUCTION:
        rt_kprintf("Illegal instruction");
        break;
    ........

那么此时dump_regs将被调用。

dump_regs(sp);
rt_kprintf("exception pc => 0x%08x\n", xepc);
rt_kprintf("current thread: %.*s\n", RT_NAME_MAX, tid->name);

此时将打印出所有内核寄存器,其中就包括satp寄存器。

rt_size_t satp_v = read_csr(satp);
rt_kprintf("satp = 0x%p\n",satp_v);

那么问题来了,如果CPU没有实现该寄存器,能不能跑rt-thread呢?需不需要修改rt-thread的源码呢?
答案是可以的。因为上面提到的,不在预期之内的异常陷入才会调用dump_regs一生一芯基础任务所要求实现的异常,都包含在该预期之中,所以dump_regs不会被调用。事实上,能跑起来rt-thread只需要实现定时器中断即可,甚至连ecall指令都用不到。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants