Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenXiangShan
nexus-am
提交
8ed70b7f
N
nexus-am
项目概览
OpenXiangShan
/
nexus-am
大约 1 年 前同步成功
通知
2
Star
21
Fork
25
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
N
nexus-am
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
8ed70b7f
编写于
5月 04, 2022
作者:
W
William Wang
浏览文件
操作
浏览文件
下载
差异文件
Merge remote-tracking branch 'origin/driver-adding' into southlake
上级
4ab87094
f62a0a2d
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
85 addition
and
7 deletion
+85
-7
am/src/nemu/isa/riscv/cte.c
am/src/nemu/isa/riscv/cte.c
+50
-5
am/src/xs/isa/riscv/clint.c
am/src/xs/isa/riscv/clint.c
+1
-1
docs/interrupt_handle_reg.md
docs/interrupt_handle_reg.md
+33
-0
tests/amtest/src/tests/intr.c
tests/amtest/src/tests/intr.c
+1
-1
未找到文件。
am/src/nemu/isa/riscv/cte.c
浏览文件 @
8ed70b7f
...
...
@@ -14,7 +14,10 @@ void __am_switch(_Context *c);
_Context
*
(
*
interrupt_handler
[
INTERRUPT_CAUSE_SIZE
])(
_Event
*
ev
,
_Context
*
c
);
_Context
*
(
*
exception_handler
[
EXCEPTION_CAUSE_SIZE
])(
_Event
*
ev
,
_Context
*
c
);
/*
* default handler for all possible irqs
* just panic
*/
_Context
*
__am_irq_default_handler
(
_Event
*
ev
,
_Context
*
c
)
{
printf
(
"unregisted irq detected, scause=%d, sepc=%llx
\n
"
,
c
->
scause
,
c
->
sepc
);
ev
->
event
=
_EVENT_ERROR
;
...
...
@@ -22,14 +25,20 @@ _Context* __am_irq_default_handler(_Event *ev, _Context *c) {
// should never reach here
return
c
;
}
/*
* default handler for Supervisor Timer Interrupt
* set event to IRQ_TIMER
* may call custom timer handler if registered
*/
_Context
*
__am_irq_STIP_handler
(
_Event
*
ev
,
_Context
*
c
)
{
#if __riscv_xlen == 64
asm
volatile
(
"csrwi sip, 0"
);
#endif
printf
(
"inside irq STIP handler
\n
"
);
//
printf("inside irq STIP handler\n");
ev
->
event
=
_EVENT_IRQ_TIMER
;
if
(
custom_timer_handler
!=
NULL
)
{
printf
(
"dive into custom timer handler"
);
//
printf("dive into custom timer handler");
custom_timer_handler
(
*
ev
,
c
);
}
// machine mode will clear stip
...
...
@@ -37,6 +46,12 @@ _Context* __am_irq_STIP_handler(_Event *ev, _Context *c) {
// printf("STIP handler finished\n");
return
c
;
}
/*
* default handler for Supervisor External Interrupt
* set event to IEQ_IODEV
* may call custom external handler if registered
*/
_Context
*
__am_irq_SEIP_handler
(
_Event
*
ev
,
_Context
*
c
)
{
// WARNING: this has no effect since in S mode only SSIP can be cleared.
// It's not deleted because we want to test sip write mask.
...
...
@@ -48,12 +63,17 @@ _Context* __am_irq_SEIP_handler(_Event *ev, _Context *c) {
return
c
;
}
/*
* default handler for Supervisor Ecall Exception
* set event to YIELD or SYSCALL according to a7
* may call custom secall handler if registered
*/
_Context
*
__am_irq_SECALL_handler
(
_Event
*
ev
,
_Context
*
c
)
{
ev
->
event
=
(
c
->
GPR1
==
-
1
)
?
_EVENT_YIELD
:
_EVENT_SYSCALL
;
c
->
sepc
+=
4
;
//if (ev->event == _EVENT_YIELD)
// printf("SECALL: is YIELD\n");
printf
(
"Inside secall handler
\n
"
);
//
printf("Inside secall handler\n");
if
(
custom_secall_handler
!=
NULL
)
{
custom_secall_handler
(
*
ev
,
c
);
}
...
...
@@ -88,16 +108,35 @@ _Context* __am_irq_handle(_Context *c) {
extern
void
__am_asm_trap
(
void
);
/*
* Supervisor timer interrupt custom handler register function
* handler: the function to be registered
*/
void
stip_handler_reg
(
_Context
*
(
*
handler
)(
_Event
,
_Context
*
))
{
custom_timer_handler
=
handler
;
}
/*
* Supervisor external interrupt custom handler register function
* handler: the function to be registered
*/
void
seip_handler_reg
(
_Context
*
(
*
handler
)(
_Event
,
_Context
*
))
{
custom_external_handler
=
handler
;
}
/*
* Supervisor ecall exception custom handler register function
* handler: the function to be registered
*/
void
secall_handler_reg
(
_Context
*
(
*
handler
)(
_Event
,
_Context
*
))
{
custom_secall_handler
=
handler
;
}
/*
* Generic interrupt/exception CUSTOM handler register function
* code: scause code
* handler: the function to be registered
*/
void
custom_handler_reg
(
uintptr_t
code
,
_Context
*
(
*
handler
)(
_Event
,
_Context
*
))
{
switch
(
code
)
{
#if __riscv_xlen == 64
...
...
@@ -130,6 +169,11 @@ void register_handler(uintptr_t code, _Context*(*handler)(_Event*, _Context*)) {
}
}
/*
* Generic interrupt/exception handler register function
* code: scause code
* handler: the function to be registered
*/
void
irq_handler_reg
(
uintptr_t
code
,
_Context
*
(
*
handler
)(
_Event
*
,
_Context
*
))
{
uintptr_t
offset
=
(
code
<<
1
)
>>
1
;
if
(
INTR_BIT
&
code
)
{
...
...
@@ -155,7 +199,8 @@ int _cte_init(_Context *(*handler)(_Event ev, _Context *ctx)) {
__am_init_cte64
();
#endif
for
(
int
i
=
0
;
i
<
INTERRUPT_CAUSE_SIZE
;
i
++
)
{
interrupt_handler
[
i
]
=
__am_irq_default_handler
;
irq_handler_reg
(
INTR_BIT
|
i
,
__am_irq_default_handler
);
// interrupt_handler[i] = __am_irq_default_handler;
}
for
(
int
i
=
0
;
i
<
EXCEPTION_CAUSE_SIZE
;
i
++
)
{
exception_handler
[
i
]
=
__am_irq_default_handler
;
...
...
am/src/xs/isa/riscv/clint.c
浏览文件 @
8ed70b7f
...
...
@@ -11,7 +11,7 @@ ClintInfo timer_handle;
#if defined(__ARCH_RISCV64_NOOP) || defined(__ARCH_RISCV64_XS) || defined(__ARCH_RISCV64_XS_SOUTHLAKE) || defined(__ARCH_RISCV64_XS_SOUTHLAKE_FLASH)
#define CLINT_MMIO (RTC_ADDR - 0xbff8)
#define TIME_INC 0x800
00
#define TIME_INC 0x800
#else
#define CLINT_MMIO 0xa2000000
#define TIME_INC 0x800
...
...
docs/interrupt_handle_reg.md
0 → 100644
浏览文件 @
8ed70b7f
# 异常处理与Handler注册
## 异常处理流程
### RISC-V异常处理模型概述
RISC-V处理器的异常在默认情况下一律陷入到machine态,machine态软件视情况决定直接处理或转交supervisor态处理。为减少整体trap次数以提升常见中断异常的处理速度,RISC-V还提供了中断和异常代理功能。符合代理条件的异常可不经machine态直接转交supervisor态处理。
### AM在该异常处理模型下的实现细节
AM在RISC-V处理器上运行时,复位在machine态,在完成machine态的异常handler设置及异常代理、CLINT、PMP等必须在machine态完成的初始化设置后,进入supervisor态并设置supervisor态的异常handler。
machine态的异常handler实际仅处理时钟中断和非法指令两种异常。时钟中断异常在machine态利用更新mtimecmp csr的方式清除后,machine态handler会主动设置supervisor态的外部中断异常以便supervisor态软件得知中断触发并处理。考虑到supervisor态无法主动清除machine态所设置的supervisor态外部中断异常信号,为其在machine态提供了一个利用非法指令清除外部中断信号的方法。machine态handler在检测到非法指令异常时,会将supervisor态外部异常信号清空并返回触发异常指令的下一条指令执行。
supervisor态是AM用户接触最多的状态。为兼顾通用性及各功能处理由自身产生的各项异常需求,AM在supervisor态提供了分两层的运行时动态注册异常handler功能。
具体地,supervisor态异常handler在保存现场后会进入C语言
`__am_irq_handle`
函数,该函数根据scause寄存器最高位判断异常是否为中断并分别进入异常和中断handler表中对应cause所注册的异常handler。用户可使用
`irq_handler_reg`
函数注册相应handler。该级handler是可由用户主动注册的第一级handler。在默认情况下,时钟中断handler被注册为
`__am_irq_STIP_handler`
,外部中断handler被注册为
`__am_irq_SEIP_handler`
,ecall异常handler被注册为
`__am_irq_SECALL_handler`
,其他类型异常handler被注册为
`__am_irq_default_handler`
。
考虑到amtest中大量测试需要主动触发外部中断、ecall异常并自行对异常做进一步的处理,SEIP、SECALL、STIP三个handler还进一步提供了自定义handler注册机制。用户可使用
`custom_handler_reg`
函数按照异常编号进行自定义handler注册或直接调用
`seip_handler_reg`
、
`secall_handler_reg`
及
`stip_handler_reg`
函数注册相应handler。这类handler一旦注册,将会在默认handler执行结束后被调用。这一级handler是可由用户主动注册的第二级handler。
## handler注册示例与说明
`test/amtest`
目录下的测试充分利用了上述机制,可用于参考。
main.c中在调用每个具体测试前,首先使用CTE宏完成中断机制初始化,而后利用REEH、RCEH、RTEH等宏分别调用外部中断、ecall异常和时钟中断的自定义handler注册,最终再调用测试本身。
此外,
`src/nemu/isa/riscv/cte.c`
中
`_cte_init`
函数对
`irq_handler_reg`
函数的调用可用作该函数用法参考。
### handler实现需求
第一级handler执行前,supervisor态软件并未对该异常做任何具体处理,一切与此异常处理具体相关的操作都要在该handler内实现完毕,通常包括清除中断信号(以避免重复进入该异常的处理)、设置相关event、设置特权态csr等。第二级handler执行前,supervisor态软件往往已对该异常进行了必要处理并生成了该异常具体原因(event),二级handler一般仅需要根据该event信息修改部分全局变量值、进行某些输出等操作。
第一级handler可参考
`src/nemu/isa/riscv/cte.c`
中
`__am_irq_SEIP_handler`
实现,第二级handler可参考
`tests/amtest/tests/intr.c`
中
`simple_trap`
实现。
\ No newline at end of file
tests/amtest/src/tests/intr.c
浏览文件 @
8ed70b7f
...
...
@@ -18,7 +18,7 @@ void hello_intr() {
_intr_write
(
1
);
// printf("hello intr written\n");
#if defined(__ARCH_RISCV64_XS_SOUTHLAKE) || defined(__ARCH_RISCV64_XS_SOUTHLAKE_FLASH)
for
(
volatile
int
i
=
0
;
i
<
10
;
i
++
)
;
for
(
volatile
int
i
=
0
;
i
<
512
;
i
++
)
;
_yield
();
#else
while
(
1
)
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录