Skip to content

Commit 4a24b77

Browse files
committed
refactor(priv): totally abandon rtl_sys_slow_path
In previous commit e6b9212, amo and system instructions were changed to use slow path handler, in order to reduce the number of instruction entries in the execute() function, which improved the performance of NEMU. As the number of RISC-V instructions develops, RVV, RVB, RVK introducing a large number of new instruction. In this context, using slow path handler no longer brings significant performance gains, and the complex decoding and execution logic reduces code readability and maintainability. Testing shows that: * When PERF_OPT enabled, the execution time of linux-hello and xvisor-hello increases by 0.68%; * When PERF_OPT disabled, the execution time of linux-hello decreases by 0.8%
1 parent 9e3af6e commit 4a24b77

File tree

10 files changed

+447
-461
lines changed

10 files changed

+447
-461
lines changed

src/cpu/cpu-exec.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ uint64_t get_abs_instr_count() {
123123
uint64_t get_abs_instr_count_csr() {
124124
#if defined(CONFIG_INSTR_CNT_BY_BB)
125125
return get_abs_instr_count() + prev_s->idx_in_bb - 1;
126-
// s of this instruction is saved into prev_s, before csrrw() in rtl_sys_slow_path().
126+
// s of this instruction is saved into prev_s, in EHelper of csrrw/csrrs/csrrc.
127127
#elif defined(CONFIG_INSTR_CNT_BY_INSTR)
128128
// INSTR-level
129129
return g_nr_guest_instr;
@@ -478,7 +478,7 @@ static void execute(int n) {
478478
end_of_loop:
479479
// Here is per loop action and some priv instruction action.
480480
// If end_of_bb and n_remain <= 0, it will goto here.
481-
// Most of priv instruction (using rtl_sys_slow_path()) will goto here.
481+
// Most of priv instruction (using rtl_priv_jr() or rtl_priv_next()) will goto here.
482482

483483
// Settle instruction counting for the last instruction:
484484
// - If it is end_of_bb and n_remain < 0, it will goto here without "per inst action".

src/isa/riscv64/include/isa-all-instr.h

Lines changed: 77 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -40,64 +40,83 @@
4040
#define AMO_INSTR_TERNARY(f) f(atomic)
4141
#endif
4242

43-
#ifdef CONFIG_RVH
44-
#ifdef CONFIG_RV_SVINVAL
45-
#define RVH_INST_BINARY(f) f(hfence_vvma) f(hfence_gvma) f(hinval_vvma) f(hinval_gvma) \
46-
f(hlv_b) f(hlv_bu) f(hlv_h) f(hlv_hu) f(hlvx_hu) f(hlv_w) f(hlvx_wu) f(hlv_wu) f(hlv_d) \
47-
f(hsv_b) f(hsv_h) f(hsv_w) f(hsv_d)
48-
#else
49-
#define RVH_INST_BINARY(f) f(hfence_vvma) f(hfence_gvma) \
50-
f(hlv_b) f(hlv_bu) f(hlv_h) f(hlv_hu) f(hlvx_hu) f(hlv_w) f(hlvx_wu) f(hlv_wu) f(hlv_d) \
51-
f(hsv_b) f(hsv_h) f(hsv_w) f(hsv_d)
52-
#endif // CONFIG_RV_SVINVAL
53-
#else
54-
#define RVH_INST_BINARY(f)
55-
#endif // CONFIG_RVH
43+
#ifdef CONFIG_RV_ZAWRS
44+
#define ZAWRS_INSTR_NULLARY(f) \
45+
f(wrs_nto) f(wrs_sto)
46+
#else // CONFIG_RV_ZAWRS
47+
#define ZAWRS_INSTR_NULLARY(f)
48+
#endif // CONFIG_RV_ZAWRS
49+
50+
/********************** SYS INSTR NULLARY **********************/
5651

57-
#if defined(CONFIG_DEBUG) || defined(CONFIG_SHARE)
5852
#ifdef CONFIG_RV_SMRNMI
59-
#define SYS_NMI_NULLARY(f) \
60-
f(mnret)
61-
#else
62-
#define SYS_NMI_NULLARY(f)
63-
#endif
64-
#ifdef CONFIG_RV_ZAWRS
65-
#define SYS_ZAWRS_NULLARY(f) \
66-
f(wrs_nto) f(wrs_sto)
67-
#else
68-
#define SYS_ZAWRS_NULLARY(f)
69-
#endif
53+
#define SYS_SMRNMI_INSTR_NULLARY(f) \
54+
f(mnret)
55+
#else // CONFIG_RV_SMRNMI
56+
#define SYS_SMRNMI_INSTR_NULLARY(f)
57+
#endif // CONFIG_RV_SMRNMI
58+
7059
#ifdef CONFIG_RV_SVINVAL
60+
#define SYS_SVINVAL_INSTR_NULLARY(f) \
61+
f(sfence_w_inval) f(sfence_inval_ir)
62+
#else // CONFIG_RV_SVINVAL
63+
#define SYS_SVINVAL_INSTR_NULLARY(f)
64+
#endif // CONFIG_RV_SVINVAL
65+
7166
#define SYS_INSTR_NULLARY(f) \
7267
f(ecall) f(ebreak) f(c_ebreak) f(mret) f(sret) f(wfi) \
73-
SYS_ZAWRS_NULLARY(f) \
74-
f(sfence_w_inval) f(sfence_inval_ir)
75-
#define SYS_INSTR_BINARY(f) \
76-
f(sfence_vma) f(sinval_vma) RVH_INST_BINARY(f)
77-
#else
78-
#define SYS_INSTR_NULLARY(f) \
79-
f(ecall) f(ebreak) f(c_ebreak) f(mret) f(sret) f(wfi) \
80-
SYS_ZAWRS_NULLARY(f)
68+
SYS_SMRNMI_INSTR_NULLARY(f) \
69+
SYS_SVINVAL_INSTR_NULLARY(f)
70+
71+
/********************** SYS INSTR BINARY (2 op) **********************/
72+
73+
#ifdef CONFIG_RVH
74+
#define SYS_RVH_INSTR_BINARY(f) \
75+
f(hlv_b) f(hlv_bu) f(hlv_h) f(hlv_hu) f(hlv_w) f(hlv_wu) f(hlv_d) \
76+
f(hlvx_hu) f(hlvx_wu) \
77+
f(hsv_b) f(hsv_h) f(hsv_w) f(hsv_d)
78+
#else // CONFIG_RVH
79+
#define SYS_RVH_INSTR_BINARY(f)
80+
#endif // CONFIG_RVH
81+
8182
#define SYS_INSTR_BINARY(f) \
82-
f(sfence_vma) RVH_INST_BINARY(f)
83-
#endif
83+
SYS_RVH_INSTR_BINARY(f)
84+
85+
/********************** SYS INSTR TERNARY (3 op) **********************/
86+
87+
// Instructions sfence.vma / hfence.vvma / hfence.gvma have 2 operands (rs1, rs2),
88+
// But NEMU's print_asm_template2 is for (rd, rs1). We have to treat them as 3 operands.
89+
90+
#ifdef CONFIG_RV_SVINVAL
91+
#define SYS_SVINVAL_INSTR_TERNARY(f) \
92+
f(sinval_vma)
93+
#define SYS_SVINVAL_RVH_INSTR_TERNARY(f) \
94+
f(hinval_vvma) f(hinval_gvma)
95+
#else // CONFIG_RV_SVINVAL
96+
#define SYS_SVINVAL_INSTR_TERNARY(f)
97+
#define SYS_SVINVAL_RVH_INSTR_TERNARY(f)
98+
#endif // CONFIG_RV_SVINVAL
8499

85-
#define SYS_INSTR_TERNARY(f) \
86-
f(csrrw) f(csrrs) f(csrrc) f(csrrwi) f(csrrsi) f(csrrci)
87-
#else
88100
#ifdef CONFIG_RVH
89-
#define SYS_NMI_NULLARY(f)
90-
#define SYS_INSTR_NULLARY(f) f(c_ebreak)
91-
#define SYS_INSTR_BINARY(f)
92-
#define SYS_INSTR_TERNARY(f) f(priv) f(hload) f(hstore)
93-
#else
94-
#define SYS_NMI_NULLARY(f)
95-
#define SYS_INSTR_NULLARY(f) f(c_ebreak)
96-
#define SYS_INSTR_BINARY(f)
97-
#define SYS_INSTR_TERNARY(f) f(system)
101+
#define SYS_RVH_INSTR_TERNARY(f) \
102+
f(hfence_vvma) f(hfence_gvma) \
103+
SYS_SVINVAL_RVH_INSTR_TERNARY(f)
104+
#else // CONFIG_RVH
105+
#define SYS_RVH_INSTR_TERNARY(f)
98106
#endif // CONFIG_RVH
99-
#endif
100-
// TODO: sfence.vma and sinval.vma need two reg operand, only one(addr) now
107+
108+
#define SYS_INSTR_TERNARY(f) \
109+
f(sfence_vma) \
110+
SYS_SVINVAL_INSTR_TERNARY(f) \
111+
SYS_RVH_INSTR_TERNARY(f)
112+
113+
114+
/********************** SYS INSTR TERNARY CSR (csr) **********************/
115+
116+
#define SYS_INSTR_TERNARY_CSR(f) \
117+
f(csrrw) f(csrrs) f(csrrc) \
118+
f(csrrwi) f(csrrsi) f(csrrci)
119+
101120

102121
#ifdef CONFIG_RVV
103122
#define VECTOR_INSTR_TERNARY(f) \
@@ -280,15 +299,13 @@
280299
#endif // CONFIG_FPU_NONE
281300

282301
#ifdef CONFIG_RV_ZIMOP
283-
#define ZIMOP_INSTR_BINARY(f) \
284-
f(mop_r_n)
285-
286-
#define ZIMOP_INSTR_TERNARY(f) \
287-
f(mop_rr_n)
288-
302+
#define ZIMOP_INSTR_BINARY(f) \
303+
f(mop_r_n)
304+
#define ZIMOP_INSTR_TERNARY(f) \
305+
f(mop_rr_n)
289306
#else
290-
#define ZIMOP_INSTR_BINARY(f)
291-
#define ZIMOP_INSTR_TERNARY(f)
307+
#define ZIMOP_INSTR_BINARY(f)
308+
#define ZIMOP_INSTR_TERNARY(f)
292309
#endif // CONFIG_RV_ZIMOP
293310

294311
#ifdef CONFIG_RV_ZCMOP
@@ -320,8 +337,8 @@
320337
ZIHINTPAUSE_INSTR_NULLARY(f) \
321338
f(fence_i) f(fence) \
322339
SYS_INSTR_NULLARY(f) \
323-
SYS_NMI_NULLARY(f) \
324340
f(p_ret) \
341+
ZAWRS_INSTR_NULLARY(f) \
325342
ZCMOP_INSTR_NULLARY(f)
326343

327344
#define INSTR_UNARY(f) \
@@ -360,6 +377,7 @@
360377
f(p_inc) f(p_dec) \
361378
AMO_INSTR_TERNARY(f) \
362379
AMO_CAS_INSTR(f) \
380+
SYS_INSTR_TERNARY(f) \
363381
FLOAT_INSTR_TERNARY(f) \
364382
BITMANIP_INSTR_TERNARY(f) \
365383
CRYPTO_INSTR_TERNARY(f) \
@@ -373,7 +391,7 @@
373391
ZCB_INSTR_TERNARY(f)
374392

375393
#define INSTR_TERNARY_CSR(f) \
376-
SYS_INSTR_TERNARY(f)
394+
SYS_INSTR_TERNARY_CSR(f)
377395

378396
def_all_EXEC_ID();
379397

src/isa/riscv64/instr/decode.c

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -141,30 +141,9 @@ int isa_fetch_decode(Decode *s) {
141141

142142
case EXEC_ID_p_ret: case EXEC_ID_c_jr: case EXEC_ID_c_jalr: case EXEC_ID_jalr:
143143
case EXEC_ID_c_ebreak:
144-
#if defined(CONFIG_DEBUG) || defined(CONFIG_SHARE)
145144
case EXEC_ID_mret: case EXEC_ID_sret: case EXEC_ID_ecall: case EXEC_ID_ebreak:
146145
IFDEF(CONFIG_RV_SMRNMI, case EXEC_ID_mnret:)
147-
#endif
148146
s->type = INSTR_TYPE_I; break;
149-
150-
#if !defined(CONFIG_DEBUG) && !defined(CONFIG_SHARE)
151-
#ifdef CONFIG_RVH
152-
case EXEC_ID_priv:
153-
#else // CONFIG_RVH
154-
case EXEC_ID_system:
155-
#endif // CONFIG_RVH
156-
if (s->isa.instr.i.funct3 == 0) {
157-
switch (s->isa.instr.csr.csr) {
158-
case 0x0: // ecall
159-
case 0x1: // ebreak
160-
case 0x102: // sret
161-
case 0x302: // mret
162-
IFDEF(CONFIG_RV_SMRNMI, case 0x702: )// mnret
163-
s->type = INSTR_TYPE_I;
164-
}
165-
}
166-
break;
167-
#endif // CONFIG_DEBUG
168147
}
169148

170149
return idx;

0 commit comments

Comments
 (0)