Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenXiangShan
NEMU
提交
3fd461b0
N
NEMU
项目概览
OpenXiangShan
/
NEMU
10 个月 前同步成功
通知
7
Star
171
Fork
67
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
N
NEMU
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
3fd461b0
编写于
3月 05, 2020
作者:
Z
Zihao Yu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
riscv64: use global flag instead of longjmp to implement exceptions
* calling setjmp() at the beginning of exec() will reduce performance
上级
5c74c556
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
84 addition
and
50 deletion
+84
-50
include/isa/riscv64.h
include/isa/riscv64.h
+1
-0
src/isa/riscv64/exec/amo.h
src/isa/riscv64/exec/amo.h
+17
-0
src/isa/riscv64/exec/exec.c
src/isa/riscv64/exec/exec.c
+11
-10
src/isa/riscv64/exec/ldst.h
src/isa/riscv64/exec/ldst.h
+5
-0
src/isa/riscv64/exec/system.h
src/isa/riscv64/exec/system.h
+15
-0
src/isa/riscv64/intr.c
src/isa/riscv64/intr.c
+0
-6
src/isa/riscv64/local-include/intr.h
src/isa/riscv64/local-include/intr.h
+6
-1
src/isa/riscv64/mmu.c
src/isa/riscv64/mmu.c
+29
-26
src/isa/riscv64/reg.c
src/isa/riscv64/reg.c
+0
-7
未找到文件。
include/isa/riscv64.h
浏览文件 @
3fd461b0
...
...
@@ -22,6 +22,7 @@ typedef struct {
bool
fetching
;
bool
amo
;
int
mem_exception
;
// for LR/SC
vaddr_t
lr_addr
;
...
...
src/isa/riscv64/exec/amo.h
浏览文件 @
3fd461b0
#include "../local-include/intr.h"
static
inline
make_EHelper
(
lr
)
{
rtl_lm
(
s
,
s0
,
dsrc1
,
s
->
width
);
check_mem_ex
();
rtl_sext
(
s
,
s0
,
s0
,
s
->
width
);
rtl_sr
(
s
,
id_dest
->
reg
,
s0
,
0
);
...
...
@@ -12,6 +15,7 @@ static inline make_EHelper(sc) {
// should check overlapping instead of equality
if
(
cpu
.
lr_addr
==
*
dsrc1
)
{
rtl_sm
(
s
,
dsrc1
,
dsrc2
,
s
->
width
);
check_mem_ex
();
rtl_li
(
s
,
s0
,
0
);
}
else
{
rtl_li
(
s
,
s0
,
1
);
...
...
@@ -28,47 +32,60 @@ static void inline amo_load(DecodeExecState *s) {
static
void
inline
amo_update
(
DecodeExecState
*
s
)
{
rtl_sm
(
s
,
dsrc1
,
s1
,
s
->
width
);
check_mem_ex
();
rtl_sr
(
s
,
id_dest
->
reg
,
s0
,
0
);
}
static
inline
make_EHelper
(
amoswap
)
{
amo_load
(
s
);
check_mem_ex
();
rtl_mv
(
s
,
s1
,
dsrc2
);
// swap
amo_update
(
s
);
check_mem_ex
();
print_asm_template3
(
amoswap
);
}
static
inline
make_EHelper
(
amoadd
)
{
amo_load
(
s
);
check_mem_ex
();
rtl_add
(
s
,
s1
,
s0
,
dsrc2
);
amo_update
(
s
);
check_mem_ex
();
print_asm_template3
(
amoor
);
}
static
inline
make_EHelper
(
amoor
)
{
amo_load
(
s
);
check_mem_ex
();
rtl_or
(
s
,
s1
,
s0
,
dsrc2
);
amo_update
(
s
);
check_mem_ex
();
print_asm_template3
(
amoor
);
}
static
inline
make_EHelper
(
amoand
)
{
amo_load
(
s
);
check_mem_ex
();
rtl_and
(
s
,
s1
,
s0
,
dsrc2
);
amo_update
(
s
);
check_mem_ex
();
print_asm_template3
(
amoand
);
}
static
inline
make_EHelper
(
amomaxu
)
{
amo_load
(
s
);
check_mem_ex
();
*
s1
=
(
*
s0
>
*
dsrc2
?
*
s0
:
*
dsrc2
);
amo_update
(
s
);
check_mem_ex
();
print_asm_template3
(
amomaxu
);
}
static
inline
make_EHelper
(
amoxor
)
{
amo_load
(
s
);
check_mem_ex
();
rtl_xor
(
s
,
s1
,
s0
,
dsrc2
);
amo_update
(
s
);
check_mem_ex
();
print_asm_template3
(
amoxor
);
}
src/isa/riscv64/exec/exec.c
浏览文件 @
3fd461b0
...
...
@@ -2,7 +2,6 @@
#include "../local-include/decode.h"
#include "../local-include/intr.h"
#include "all-instr.h"
#include <setjmp.h>
#define decode_empty(s)
...
...
@@ -109,7 +108,7 @@ static inline make_EHelper(atomic) {
}
static
inline
make_EHelper
(
fp
)
{
longjmp_raise_intr
(
EX_II
);
raise_intr
(
s
,
EX_II
,
cpu
.
pc
);
}
// RVC
...
...
@@ -158,18 +157,14 @@ static inline make_EHelper(misc_alu) {
}
static
inline
void
exec
(
DecodeExecState
*
s
)
{
extern
jmp_buf
intr_buf
;
int
setjmp_ret
;
if
((
setjmp_ret
=
setjmp
(
intr_buf
))
!=
0
)
{
int
exception
=
setjmp_ret
-
1
;
raise_intr
(
s
,
exception
,
cpu
.
pc
);
return
;
}
cpu
.
fetching
=
true
;
if
((
s
->
seq_pc
&
0xfff
)
==
0xffe
)
{
// instruction may accross page boundary
uint32_t
lo
=
instr_fetch
(
&
s
->
seq_pc
,
2
);
if
(
cpu
.
mem_exception
!=
MEM_OK
)
{
cpu
.
fetching
=
false
;
return
;
}
s
->
isa
.
instr
.
val
=
lo
&
0xffff
;
if
(
s
->
isa
.
instr
.
r
.
opcode1_0
!=
0x3
)
{
// this is an RVC instruction
...
...
@@ -189,6 +184,8 @@ static inline void exec(DecodeExecState *s) {
}
cpu
.
fetching
=
false
;
check_mem_ex
();
if
(
s
->
isa
.
instr
.
r
.
opcode1_0
==
0x3
)
{
switch
(
s
->
isa
.
instr
.
r
.
opcode6_2
)
{
IDEX
(
000
,
ld
,
load
)
EX
(
001
,
fp
)
EX
(
003
,
fence
)
...
...
@@ -225,6 +222,10 @@ vaddr_t isa_exec_once() {
s
.
seq_pc
=
cpu
.
pc
;
exec
(
&
s
);
if
(
cpu
.
mem_exception
!=
MEM_OK
)
{
raise_intr
(
&
s
,
cpu
.
mem_exception
,
cpu
.
pc
);
cpu
.
mem_exception
=
MEM_OK
;
}
update_pc
(
&
s
);
#if !defined(DIFF_TEST) && !_SHARE
...
...
src/isa/riscv64/exec/ldst.h
浏览文件 @
3fd461b0
#include "../local-include/intr.h"
static
inline
make_EHelper
(
ld
)
{
rtl_lm
(
s
,
s0
,
&
id_src1
->
addr
,
s
->
width
);
check_mem_ex
();
rtl_sr
(
s
,
id_dest
->
reg
,
s0
,
0
);
switch
(
s
->
width
)
{
...
...
@@ -14,6 +17,7 @@ static inline make_EHelper(ld) {
// load sign value
static
inline
make_EHelper
(
lds
)
{
rtl_lm
(
s
,
s0
,
&
id_src1
->
addr
,
s
->
width
);
check_mem_ex
();
rtl_sext
(
s
,
s0
,
s0
,
s
->
width
);
rtl_sr
(
s
,
id_dest
->
reg
,
s0
,
0
);
...
...
@@ -27,6 +31,7 @@ static inline make_EHelper(lds) {
static
inline
make_EHelper
(
st
)
{
rtl_sm
(
s
,
&
id_src1
->
addr
,
ddest
,
s
->
width
);
check_mem_ex
();
switch
(
s
->
width
)
{
case
8
:
print_asm_template2
(
sd
);
break
;
...
...
src/isa/riscv64/exec/system.h
浏览文件 @
3fd461b0
#include <monitor/difftest.h>
#include "../local-include/csr.h"
static
inline
bool
csr_check
(
DecodeExecState
*
s
,
uint32_t
addr
)
{
switch
(
addr
)
{
case
0xc01
:
// time
case
0x001
:
// fflags
case
0x002
:
// frm
case
0x003
:
// fcsr
raise_intr
(
s
,
EX_II
,
cpu
.
pc
);
return
false
;
}
return
true
;
}
static
inline
make_EHelper
(
csrrw
)
{
uint32_t
addr
=
*
dsrc2
;
if
(
!
csr_check
(
s
,
addr
))
return
;
csr_read
(
s0
,
addr
);
rtl_sr
(
s
,
id_dest
->
reg
,
s0
,
8
);
csr_write
(
addr
,
dsrc1
);
...
...
@@ -12,6 +25,7 @@ static inline make_EHelper(csrrw) {
static
inline
make_EHelper
(
csrrs
)
{
uint32_t
addr
=
*
dsrc2
;
if
(
!
csr_check
(
s
,
addr
))
return
;
csr_read
(
s0
,
addr
);
rtl_sr
(
s
,
id_dest
->
reg
,
s0
,
8
);
if
(
id_src1
->
reg
!=
0
)
{
...
...
@@ -24,6 +38,7 @@ static inline make_EHelper(csrrs) {
static
inline
make_EHelper
(
csrrc
)
{
uint32_t
addr
=
id_src2
->
val
;
if
(
!
csr_check
(
s
,
addr
))
return
;
csr_read
(
s0
,
addr
);
rtl_sr
(
s
,
id_dest
->
reg
,
s0
,
8
);
if
(
id_src1
->
reg
!=
0
)
{
...
...
src/isa/riscv64/intr.c
浏览文件 @
3fd461b0
...
...
@@ -3,7 +3,6 @@
#include "local-include/csr.h"
#include "local-include/rtl.h"
#include "local-include/intr.h"
#include <setjmp.h>
#define INTR_BIT (1ULL << 63)
enum
{
...
...
@@ -81,8 +80,3 @@ void query_intr(DecodeExecState *s) {
}
}
}
jmp_buf
intr_buf
;
void
longjmp_raise_intr
(
uint32_t
NO
)
{
longjmp
(
intr_buf
,
NO
+
1
);
}
src/isa/riscv64/local-include/intr.h
浏览文件 @
3fd461b0
...
...
@@ -22,7 +22,12 @@ enum {
EX_SPF
,
// store/amo page fault
};
// now NEMU does not support EX_IAM,
// so it may ok to use EX_IAM to indicate a successful memory access
#define MEM_OK 0
void
raise_intr
(
DecodeExecState
*
s
,
word_t
NO
,
vaddr_t
epc
);
void
longjmp_raise_intr
(
uint32_t
);
#define check_mem_ex() do { if (cpu.mem_exception != MEM_OK) return; } while (0)
#endif
src/isa/riscv64/mmu.c
浏览文件 @
3fd461b0
...
...
@@ -35,7 +35,7 @@ static inline uintptr_t VPNi(vaddr_t va, int i) {
return
(
va
>>
VPNiSHFT
(
i
))
&
VPNMASK
;
}
static
inline
void
check_permission
(
PTE
*
pte
,
bool
ok
,
vaddr_t
vaddr
,
bool
is_write
)
{
static
inline
bool
check_permission
(
PTE
*
pte
,
bool
ok
,
vaddr_t
vaddr
,
bool
is_write
)
{
uint32_t
mode
=
(
mstatus
->
mprv
&&
!
cpu
.
fetching
?
mstatus
->
mpp
:
cpu
.
mode
);
ok
=
ok
&&
pte
->
v
;
ok
=
ok
&&
!
(
mode
==
MODE_U
&&
!
pte
->
u
);
...
...
@@ -44,31 +44,31 @@ static inline void check_permission(PTE *pte, bool ok, vaddr_t vaddr, bool is_wr
if
(
!
(
ok
&&
pte
->
x
))
{
assert
(
!
cpu
.
amo
);
stval
->
val
=
vaddr
;
longjmp_raise_intr
(
EX_IPF
);
cpu
.
mem_exception
=
EX_IPF
;
return
false
;
}
}
else
if
(
!
is_write
)
{
bool
can_load
=
pte
->
r
||
(
mstatus
->
mxr
&&
pte
->
x
);
if
(
!
(
ok
&&
can_load
))
{
if
(
cpu
.
mode
==
MODE_M
)
mtval
->
val
=
vaddr
;
else
stval
->
val
=
vaddr
;
if
(
cpu
.
amo
)
{
cpu
.
amo
=
false
;
Log
(
"redirect to AMO page fault exception at pc = "
FMT_WORD
,
cpu
.
pc
);
longjmp_raise_intr
(
EX_SPF
);
}
longjmp_raise_intr
(
EX_LPF
);
if
(
cpu
.
amo
)
Log
(
"redirect to AMO page fault exception at pc = "
FMT_WORD
,
cpu
.
pc
);
cpu
.
mem_exception
=
(
cpu
.
amo
?
EX_SPF
:
EX_LPF
);
return
false
;
}
}
else
{
if
(
!
(
ok
&&
pte
->
w
))
{
if
(
cpu
.
amo
)
cpu
.
amo
=
false
;
if
(
cpu
.
mode
==
MODE_M
)
mtval
->
val
=
vaddr
;
else
stval
->
val
=
vaddr
;
longjmp_raise_intr
(
EX_SPF
);
cpu
.
mem_exception
=
EX_SPF
;
return
false
;
}
}
return
true
;
}
static
word_t
page_walk
(
vaddr_t
v
addr
,
bool
is_write
)
{
static
bool
page_walk
(
vaddr_t
vaddr
,
paddr_t
*
p
addr
,
bool
is_write
)
{
word_t
pg_base
=
PGBASE
(
satp
->
ppn
);
word_t
p_pte
;
// pte pointer
PTE
pte
;
...
...
@@ -86,18 +86,18 @@ static word_t page_walk(vaddr_t vaddr, bool is_write) {
if
(
pte
.
r
||
pte
.
x
)
{
break
;
}
else
{
level
--
;
if
(
level
<
0
)
{
check_permission
(
&
pte
,
false
,
vaddr
,
is_write
)
;
}
if
(
level
<
0
)
{
if
(
!
check_permission
(
&
pte
,
false
,
vaddr
,
is_write
))
return
false
;
}
}
}
check_permission
(
&
pte
,
true
,
vaddr
,
is_write
)
;
if
(
!
check_permission
(
&
pte
,
true
,
vaddr
,
is_write
))
return
false
;
if
(
level
>
0
)
{
// superpage
word_t
pg_mask
=
((
1ull
<<
VPNiSHFT
(
level
))
-
1
);
if
((
pg_base
&
pg_mask
)
!=
0
)
{
// missaligned superpage
check_permission
(
&
pte
,
false
,
vaddr
,
is_write
)
;
if
(
!
check_permission
(
&
pte
,
false
,
vaddr
,
is_write
))
return
false
;
}
pg_base
=
(
pg_base
&
~
pg_mask
)
|
(
vaddr
&
pg_mask
&
~
PGMASK
);
}
...
...
@@ -108,18 +108,22 @@ static word_t page_walk(vaddr_t vaddr, bool is_write) {
paddr_write
(
p_pte
,
pte
.
val
,
PTE_SIZE
);
}
return
pg_base
;
*
paddr
=
pg_base
;
return
true
;
}
static
inline
paddr_t
page_translate
(
vaddr_t
addr
,
bool
is_write
)
{
static
inline
bool
page_translate
(
vaddr_t
vaddr
,
paddr_t
*
p
addr
,
bool
is_write
)
{
uint32_t
mode
=
(
mstatus
->
mprv
&&
!
cpu
.
fetching
?
mstatus
->
mpp
:
cpu
.
mode
);
if
(
mode
<
MODE_M
)
{
assert
(
satp
->
mode
==
0
||
satp
->
mode
==
8
);
if
(
satp
->
mode
==
8
)
{
return
page_walk
(
addr
,
is_write
)
|
(
addr
&
PAGE_MASK
);
if
(
!
page_walk
(
vaddr
,
paddr
,
is_write
))
return
false
;
*
paddr
|=
(
vaddr
&
PAGE_MASK
);
return
true
;
}
}
return
addr
;
*
paddr
=
vaddr
;
return
true
;
}
/*
...
...
@@ -173,23 +177,22 @@ uint_type(bits) concat(isa_vaddr_read, bits) (vaddr_t addr) { \
if (!cpu.fetching) { \
if ((addr & (bits / 8 - 1)) != 0) { \
mtval->val = addr; \
if (cpu.amo) { \
cpu.amo = false; \
longjmp_raise_intr(EX_SAM); \
} \
longjmp_raise_intr(EX_LAM); \
cpu.mem_exception = (cpu.amo ? EX_SAM : EX_LAM); \
return 0; \
} \
} \
paddr_t paddr = page_translate(addr, false); \
paddr_t paddr; \
if (!page_translate(addr, &paddr, false)) return 0; \
return concat(paddr_read, bits)(paddr); \
} \
void concat(isa_vaddr_write, bits) (vaddr_t addr, uint_type(bits) data) { \
if ((addr & (bits / 8 - 1)) != 0) { \
if (cpu.amo) cpu.amo = false; \
mtval->val = addr; \
longjmp_raise_intr(EX_SAM); \
cpu.mem_exception = EX_SAM; \
return; \
} \
paddr_t paddr = page_translate(addr, true); \
paddr_t paddr; \
if (!page_translate(addr, &paddr, true)) return; \
concat(paddr_write, bits)(paddr, data); \
}
...
...
src/isa/riscv64/reg.c
浏览文件 @
3fd461b0
...
...
@@ -51,13 +51,6 @@ static bool csr_exist[4096] = {
static
inline
word_t
*
csr_decode
(
uint32_t
addr
)
{
assert
(
addr
<
4096
);
switch
(
addr
)
{
case
0xc01
:
// time
case
0x001
:
// fflags
case
0x002
:
// frm
case
0x003
:
// fcsr
longjmp_raise_intr
(
EX_II
);
}
Assert
(
csr_exist
[
addr
],
"unimplemented CSR 0x%x at pc = "
FMT_WORD
,
addr
,
cpu
.
pc
);
return
&
csr_array
[
addr
];
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录