[SOLVED]An unexpected behavior of stvec on my os
Posted: Tue Nov 18, 2025 11:30 am
I'm writing an kernel in risc-v64. When I was writing my intterupt handling system and attempted to use the 'vectored' mode of 'stvec`, things went wrong somewhere. The intterupt handling system just doesn't work. I tries to use gdb and finds out that the pc was once set into the exact value of `stvec`, instead of `stvec & ~0x03`.

I've worked on this problem for hours and nothing has progressed. I even suspected that there was a problem with my qemu and compiled a new one, but nothing changed.
Here's my kernel sourcecode and the way I build and run it.
the related files are `kernel/arch/riscv64/int/exception.h` `kernel/arch/riscv64/int/exception.c` `kernel/arch/riscv64/int/trap.h` `kernel/main.c`
https://github.com/sustcore-team/sustcore
It's worth reminding that I've written my comments and printing messages in Chinese so it'll be a little confused if there are any garbled text.
Also, I'll paste some part of code in the below:
`kernel/arch/riscv64/int/exception.h`
`kernel/arch/riscv64/int/exception.c`

I've worked on this problem for hours and nothing has progressed. I even suspected that there was a problem with my qemu and compiled a new one, but nothing changed.
Here's my kernel sourcecode and the way I build and run it.
the related files are `kernel/arch/riscv64/int/exception.h` `kernel/arch/riscv64/int/exception.c` `kernel/arch/riscv64/int/trap.h` `kernel/main.c`
https://github.com/sustcore-team/sustcore
It's worth reminding that I've written my comments and printing messages in Chinese so it'll be a little confused if there are any garbled text.
Also, I'll paste some part of code in the below:
`kernel/arch/riscv64/int/exception.h`
Code: Select all
#pragma once
#include <sus/bits.h>
typedef void (*ISRService)(void);
#define DIRECT 0
#define VECTORED 1
#define IVT_MODE DIRECT
#if IVT_MODE == VECTORED
#define IVT_ENTRIES (16)
extern dword IVT[IVT_ENTRIES];
#endif
void init_ivt();
Code: Select all
...
#if IVT_MODE == VECTORED
__attribute__((aligned(4), section(".text")))
dword IVT[IVT_ENTRIES] = {};
static dword emit_j_ins(const dword offset) {
if (offset & 0x3) {
// 偏移量必须是4字节对齐的
return 0;
}
const dword j_opcode = 0x6F;
const dword imm20 = (offset >> 20) & 0x1;
const dword imm10_1 = (offset >> 1 ) & 0x3FF;
const dword imm11 = (offset >> 11) & 0x1;
const dword imm19_12 = (offset >> 12) & 0xFF;
const dword imm =
(imm20 << 31 )|
(imm10_1 << 21 )|
(imm11 << 20 )|
(imm19_12 << 12 );
return imm | j_opcode;
}
static dword emit_ivt_entry(ISRService isr_func, int idx) {
qword q_off = (qword)isr_func - (qword)IVT - (idx * sizeof(dword));
return emit_j_ins((dword)q_off);
}
#endif
void init_ivt() {
#if IVT_MODE == VECTORED
// 设置为vectored模式
umb_t ivt_addr = (umb_t)IVT;
if (ivt_addr & 0x3) {
log_info("错误: IVT地址未对齐!");
return;
}
umb_t stvec = (ivt_addr & ~0b11) | 0b01;
for (int i = 0 ; i < IVT_ENTRIES; i++) {
IVT[i] = emit_ivt_entry(general_isr, i);
}
log_info("general_isr 地址: 0x%lx", (umb_t)general_isr);
log_info("general_exception 地址: 0x%lx", (umb_t)general_exception);
log_info("IVT 地址: 0x%lx", (umb_t)IVT);
#elif IVT_MODE == DIRECT
// 采用direct模式
umb_t stvec = (umb_t)general_isr;
if (stvec & 0x3) {
log_info("错误: stvec地址未对齐!");
return;
}
log_info("general_isr 地址: 0x%lx", (umb_t)general_isr);
#endif
asm volatile("csrw stvec, %0" : : "r"(stvec));
}
#define RISCV_CPU_INTERRUPT_MASK (1ull << 63)
ISR_SERVICE_ATTRIBUTE
void general_isr(void) {
ISR_SERVICE_START(general_isr, 128);
if (scause & RISCV_CPU_INTERRUPT_MASK) {
log_info("这是一个中断");
} else {
general_exception(scause, sepc, stval, reglist_ptr);
}
ISR_SERVICE_END(general_isr);
}
enum {
EXCEPTION_INST_MISALIGNED = 0, // 指令地址不对齐
EXCEPTION_INST_ACCESS_FAULT = 1, // 指令访问错误
EXCEPTION_ILLEGAL_INST = 2, // 非法指令
EXCEPTION_BREAKPOINT = 3, // 断点
EXCEPTION_LOAD_MISALIGNED = 4, // 加载地址不对齐
EXCEPTION_LOAD_ACCESS_FAULT = 5, // 加载访问错误
EXCEPTION_STORE_MISALIGNED = 6, // 存储地址不对齐
EXCEPTION_STORE_ACCESS_FAULT = 7, // 存储访问错误
EXCEPTION_ECALL_U = 8, // 用户模式环境调用
EXCEPTION_ECALL_S = 9, // 监管模式环境调用
EXCEPTION_ECALL_M = 11, // 机器模式环境调用
EXCEPTION_INST_PAGE_FAULT = 12, // 指令页错误
EXCEPTION_LOAD_PAGE_FAULT = 13, // 加载页错误
EXCEPTION_STORE_PAGE_FAULT = 15 // 存储页错误
};
...
[\code]
`kernel/main.c`
[code]
...
// 触发非法指令异常
__attribute__((noinline))
int trigger_illegal_instruction(void) {
asm volatile (".word 0x00000000"); // 全零是非法指令
return -1;
}
//------------------ 调试异常处理程序 --------
/**
* @brief 内核主函数
*
* @return int
*/
int main(void) {
log_info("Hello RISCV World!");
log_info("Hart ID: %u", (unsigned int)hart_id);
log_info("DTB Ptr: 0x%016lx", (unsigned long)dtb_ptr);
log_info("开始验证设备树...");
void *fdt = (void *)dtb_ptr;
int ret = fdt_check_initial(fdt);
if (ret != 0) {
log_error("设备树校验失败: %d", ret);
return -1;
}
log_info("设备树校验成功!");
log_info("开始遍历设备树节点...");
traverse_nodes(fdt);
log_info("设备树节遍历完成!");
log_info("开始测试非法指令异常处理...");
init_ivt();
int a = trigger_illegal_instruction();
log_info("非法指令异常测试结果: %d", a);
return 0;
}
...
[\code]