我们正在集成一个新的核心(从pullino到cv32(。我在目标上编译和运行代码没有问题,除了调用time()
、srand()
或rand()
(例如,不调用div()
(时,默认异常处理程序被回调,并且我有以下CSR值:
mcause : 0x0000000b
mstatus : 0x00001880 (mstatus.MPP : 03, mstatus.MIE : 01)
mepc : 0x00003476
mtval : 0x00000000
mip : 0x00000000
mie : 0xffff0000
misa : 0x40101104
我编译并运行了一个非常简单的测试(它只是/仅是对触发异常的rand()
的调用(然后我在带有printfs的默认异常处理程序中显示CSR。
正如你所看到的,mcause=0xB;来自M模式的环境调用";(见第29页(
ECALL指令用于向更高的特权级别发出请求。二进制接口到执行环境将定义如何传递请求的参数,但通常这些将在整数寄存器文件中定义的位置。执行ECALL指令会导致环境调用异常。
我所理解的ecall
用于调用例如linux。通过分解二进制文件,我发现time
和rand
函数中调用了ecall
,但div
函数中没有调用。这证明ecall
正在触发异常。
1/什么可以解释ecall触发异常?
执行ECALL指令会导致环境调用异常。
好的,所以我想我应该处理ecall异常,但如何处理?
这是我的crt0
.section .vectors, "ax"
.option norvc;
.global intvec
intvec:
.org 0x00
jal x0, default_exception_handler_c
[...]
.org 0x88
jal x0, ecall_insn_handler
2/为什么ecall触发default_exception_handler_c
而不是ecall_insn_handler
?硬件布线不好?
详细信息:
我正在使用riscv COREV工具链,该工具链配置有:
riscv32-corev-elf-gcc -v
[...]
Target: riscv32-corev-elf
Configured with: ../../gcc/configure --target=riscv32-corev-elf --prefix=/build/workspace/corev-gcc-centos7/install --with-sysroot=/build/workspace/corev-gcc-centos7/install/riscv32-corev-elf --with-native-system-header-dir=/include --with-newlib --disable-shared --enable-languages=c,c++ --enable-tls --disable-werror --disable-libmudflap --disable-libssp --disable-quadmath --disable-libgomp --disable-nls --enable-multilib --with-arch=rv32imac --with-abi=ilp32 --with-bugurl=''''https://www.embecosm.com'''' --with-pkgversion=''''corev-openhw-gcc-centos7-20200913''''
Thread model: single
Supported LTO compression algorithms: zlib
gcc version 11.0.0 20200813 (experimental) ('corev-openhw-gcc-centos7-20200913')
编译标志包括:
-Os -Wa,-march=rv32ic -Wall -Wdouble-promotion -Wextra -Wformat=2 -fdata-sections -ffunction-sections -fno-builtin -fno-builtin-printf -fno-merge-all-constants -g0 -march=rv32ic -s -std=gnu11
ecall触发异常的原因是什么?
这个问题让我有点困惑。ECALL被记录为触发异常,这确实是该操作的目的,类似于x86/x64上的SYSENTER/SYSCALL。
这里的想法是促进上下文切换。像div()
这样的函数可以在非特权模式下解析,而像time()
这样的函数则不能(例如,因为非特权模式不允许访问系统时钟(。因此,他们的实现以某种方式设置某些寄存器("请给我时钟的状态"(,然后触发异常(ECALL(。异常处理程序以更高的特权级别运行,它检查这些寄存器的值,这些寄存器告诉它调用方需要哪些功能。执行该功能,将结果存储在寄存器中,并将控制权返回给(非特权(调用方。
为什么ecall触发default_exception_handler.c而不是ecall_insn_handler?硬件布线不好?
我对此非常怀疑,因为这是基本功能。您的异常处理更有可能是错误实现的。