From 6f4db8e1f745d656b2886fc9ae12a3ee795bda92 Mon Sep 17 00:00:00 2001 From: "Xu, Zefan" Date: Tue, 28 May 2024 22:05:42 +0800 Subject: [PATCH] countertest: support tests for all *counteren --- tests/countertest/include/countertest.h | 38 +++++++++ tests/countertest/include/enable.h | 102 ++++++++++++++++++++++++ tests/countertest/include/priv.h | 8 +- tests/countertest/src/countertest.c | 34 +++----- tests/countertest/src/enable.c | 18 +++++ tests/countertest/src/priv.c | 17 +++- tests/countertest/src/trap.S | 3 +- 7 files changed, 193 insertions(+), 27 deletions(-) create mode 100644 tests/countertest/include/countertest.h create mode 100644 tests/countertest/include/enable.h create mode 100644 tests/countertest/src/enable.c diff --git a/tests/countertest/include/countertest.h b/tests/countertest/include/countertest.h new file mode 100644 index 00000000..26e6a7e7 --- /dev/null +++ b/tests/countertest/include/countertest.h @@ -0,0 +1,38 @@ +#ifndef __COUNTERTEST_H__ +#define __COUNTERTEST_H__ + +#define MSG_ERROR "\33[1;31mERROR\033[0m" + +#define MAP(c, f) c(f) + +#define MACHINE_COUNTER_BASE 0xB00 +#define UNPRIV_COUNTER_BASE 0xC00 +#define COUNTER_NUM 32 + +#define CSRS_UNPRIV_CNTR(f) \ + f(cycle , 0xC00) \ + f(time , 0xC01) \ + f(instret , 0xC02) + +#define CSRS_UNPRIV_HPM(f) \ + f(hpmcounter3 , 0xC03) \ + f(hpmcounter4 , 0xC04) f(hpmcounter5 , 0xC05) f(hpmcounter6 , 0xC06) f(hpmcounter7 , 0xC07) \ + f(hpmcounter8 , 0xC08) f(hpmcounter9 , 0xC09) f(hpmcounter10 , 0xC0A) f(hpmcounter11 , 0xC0B) \ + f(hpmcounter12 , 0xC0C) f(hpmcounter13 , 0xC0D) f(hpmcounter14 , 0xC0E) f(hpmcounter15 , 0xC0F) \ + f(hpmcounter16 , 0xC10) f(hpmcounter17 , 0xC11) f(hpmcounter18 , 0xC12) f(hpmcounter19 , 0xC13) \ + f(hpmcounter20 , 0xC14) f(hpmcounter21 , 0xC15) f(hpmcounter22 , 0xC16) f(hpmcounter23 , 0xC17) \ + f(hpmcounter24 , 0xC18) f(hpmcounter25 , 0xC19) f(hpmcounter26 , 0xC1A) f(hpmcounter27 , 0xC1B) \ + f(hpmcounter28 , 0xC1C) f(hpmcounter29 , 0xC1D) f(hpmcounter30 , 0xC1E) f(hpmcounter31 , 0xC1F) + +#define CSR_ALL_UNPRIV_COUNTER(f) \ + CSRS_UNPRIV_CNTR(f) \ + CSRS_UNPRIV_HPM(f) + +#define ACCESSIBLE 0 +#define EX_II 2 +#define EX_VI 22 + +extern int error; + + +#endif // __COUNTERTEST_H__ diff --git a/tests/countertest/include/enable.h b/tests/countertest/include/enable.h new file mode 100644 index 00000000..56662bf9 --- /dev/null +++ b/tests/countertest/include/enable.h @@ -0,0 +1,102 @@ +#ifndef __ENABLE_H__ +#define __ENABLE_H__ + +typedef void (*func_void_t)(); +extern func_void_t check_enable_func_arr[32]; + +#define check_enable_detail(csr, addr, m, h, s, mode, res) \ + do { \ + goto_priv_mode(MODE_M); \ + this_mcounteren = m << (addr - UNPRIV_COUNTER_BASE); \ + this_hcounteren = h << (addr - UNPRIV_COUNTER_BASE); \ + this_scounteren = s << (addr - UNPRIV_COUNTER_BASE); \ + csr_write(mcounteren, this_mcounteren); \ + csr_write(hcounteren, this_hcounteren); \ + csr_write(scounteren, this_scounteren); \ + goto_priv_mode(mode); \ + setup_expected_exception(); \ + csr_read_res = csr_read(csr); \ + csr_read_res &= csr_read_res; \ + if (res) { /* should trap */ \ + if (!last_exception.actual_trap) { \ + printf(MSG_ERROR ": checking " #csr ", "); \ + printf("m/h/scounteren: %d/%d/%d, mode: " #mode "\n", m, h, s); \ + printf("reading " #csr " shoule trap into " #res ", but not.\n"); \ + error += 1; \ + } else if (last_exception.cause != res) { \ + printf(MSG_ERROR ": checking " #csr ", "); \ + printf("m/h/scounteren: %d/%d/%d, mode: " #mode "\n", m, h, s); \ + printf("reading " #csr " shoule trap into " #res ", but trapped into %d.\n", last_exception.cause); \ + error += 1; \ + } \ + } else { /* should be accessible */\ + if (last_exception.actual_trap) { \ + printf(MSG_ERROR ": checking " #csr ", "); \ + printf("m/h/scounteren: %d/%d/%d, mode: " #mode "\n", m, h, s); \ + printf(#csr " shoule be accessible, but not.\n"); \ + error += 1; \ + } \ + } \ + clear_last_exception(); \ + } while (0) + +#define def_func_check_enable(csr, addr) \ + void check_enable_##csr() { \ + int this_mcounteren; \ + int this_hcounteren; \ + int this_scounteren; \ + uint64_t csr_read_res; \ + /* m/h/scounteren: 0/0/0 */ \ + check_enable_detail(csr, addr, 0, 0, 0, MODE_M, ACCESSIBLE); \ + check_enable_detail(csr, addr, 0, 0, 0, MODE_S, EX_II); \ + check_enable_detail(csr, addr, 0, 0, 0, MODE_U, EX_II); \ + check_enable_detail(csr, addr, 0, 0, 0, MODE_VS, EX_II); \ + check_enable_detail(csr, addr, 0, 0, 0, MODE_VU, EX_II); \ + /* m/h/scounteren: 0/0/1 */ \ + check_enable_detail(csr, addr, 0, 0, 1, MODE_M, ACCESSIBLE); \ + check_enable_detail(csr, addr, 0, 0, 1, MODE_S, EX_II); \ + check_enable_detail(csr, addr, 0, 0, 1, MODE_U, EX_II); \ + check_enable_detail(csr, addr, 0, 0, 1, MODE_VS, EX_II); \ + check_enable_detail(csr, addr, 0, 0, 1, MODE_VU, EX_II); \ + /* m/h/scounteren: 0/1/0 */ \ + check_enable_detail(csr, addr, 0, 1, 0, MODE_M, ACCESSIBLE); \ + check_enable_detail(csr, addr, 0, 1, 0, MODE_S, EX_II); \ + check_enable_detail(csr, addr, 0, 1, 0, MODE_U, EX_II); \ + check_enable_detail(csr, addr, 0, 1, 0, MODE_VS, EX_II); \ + check_enable_detail(csr, addr, 0, 1, 0, MODE_VU, EX_II); \ + /* m/h/scounteren: 0/1/1 */ \ + check_enable_detail(csr, addr, 0, 1, 1, MODE_M, ACCESSIBLE); \ + check_enable_detail(csr, addr, 0, 1, 1, MODE_S, EX_II); \ + check_enable_detail(csr, addr, 0, 1, 1, MODE_U, EX_II); \ + check_enable_detail(csr, addr, 0, 1, 1, MODE_VS, EX_II); \ + check_enable_detail(csr, addr, 0, 1, 1, MODE_VU, EX_II); \ + /* m/h/scounteren: 1/0/0 */ \ + check_enable_detail(csr, addr, 1, 0, 0, MODE_M, ACCESSIBLE); \ + check_enable_detail(csr, addr, 1, 0, 0, MODE_S, ACCESSIBLE); \ + check_enable_detail(csr, addr, 1, 0, 0, MODE_U, EX_II); \ + check_enable_detail(csr, addr, 1, 0, 0, MODE_VS, EX_VI); \ + check_enable_detail(csr, addr, 1, 0, 0, MODE_VU, EX_VI); \ + /* m/h/scounteren: 1/0/1 */ \ + check_enable_detail(csr, addr, 1, 0, 1, MODE_M, ACCESSIBLE); \ + check_enable_detail(csr, addr, 1, 0, 1, MODE_S, ACCESSIBLE); \ + check_enable_detail(csr, addr, 1, 0, 1, MODE_U, ACCESSIBLE); \ + check_enable_detail(csr, addr, 1, 0, 1, MODE_VS, EX_VI); \ + check_enable_detail(csr, addr, 1, 0, 1, MODE_VU, EX_VI); \ + /* m/h/scounteren: 1/1/0 */ \ + check_enable_detail(csr, addr, 1, 1, 0, MODE_M, ACCESSIBLE); \ + check_enable_detail(csr, addr, 1, 1, 0, MODE_S, ACCESSIBLE); \ + check_enable_detail(csr, addr, 1, 1, 0, MODE_U, EX_II); \ + check_enable_detail(csr, addr, 1, 1, 0, MODE_VS, ACCESSIBLE); \ + check_enable_detail(csr, addr, 1, 1, 0, MODE_VU, EX_VI); \ + /* m/h/scounteren: 1/1/1 */ \ + check_enable_detail(csr, addr, 1, 1, 1, MODE_M, ACCESSIBLE); \ + check_enable_detail(csr, addr, 1, 1, 1, MODE_S, ACCESSIBLE); \ + check_enable_detail(csr, addr, 1, 1, 1, MODE_U, ACCESSIBLE); \ + check_enable_detail(csr, addr, 1, 1, 1, MODE_VS, ACCESSIBLE); \ + check_enable_detail(csr, addr, 1, 1, 1, MODE_VU, ACCESSIBLE); \ + } + +#define list_func_check_enable(csr, addr) \ + check_enable_##csr, + +#endif // __ENABLE_H__ diff --git a/tests/countertest/include/priv.h b/tests/countertest/include/priv.h index b2524067..9c0cd27c 100644 --- a/tests/countertest/include/priv.h +++ b/tests/countertest/include/priv.h @@ -18,7 +18,8 @@ enum { typedef struct { - uint64_t expected; + uint64_t expected_trap; + uint64_t actual_trap; uint64_t cause; uint64_t epc; } exception_t; @@ -75,4 +76,7 @@ void do_ecall( uint64_t arg4, uint64_t arg5, uint64_t arg6, uint64_t ecall_num ); -#endif // __PRIV_H__ \ No newline at end of file +void setup_expected_exception(); +void clear_last_exception(); + +#endif // __PRIV_H__ diff --git a/tests/countertest/src/countertest.c b/tests/countertest/src/countertest.c index 7649f623..c41afd7d 100644 --- a/tests/countertest/src/countertest.c +++ b/tests/countertest/src/countertest.c @@ -6,34 +6,24 @@ #include #include "priv.h" +#include "countertest.h" +#include "enable.h" extern void m_trap_entry(); +int error = 0; + int main() { - // setup + // setup trap vector csr_write(mtvec, m_trap_entry); - goto_priv_mode(MODE_M); - csr_write(mcounteren, 0); - csr_write(scounteren, 0); - csr_write(hcounteren, 0); + check_enable_func_arr[1] = 0; - goto_priv_mode(MODE_VU); - - last_exception.expected = 1; - last_exception.cause = 0; - last_exception.epc = 0; - - int this_cycle = csr_read(cycle); - printf("cycle: %d\n", this_cycle); - - if (last_exception.cause == 2) { - printf("good exception!\n"); - _halt(0); - } else { - printf("bad no exception!\n"); - _halt(1); + for (int i = 0; i < COUNTER_NUM; i++) { + if (check_enable_func_arr[i]) { + check_enable_func_arr[i](); + } } - return 0; -} \ No newline at end of file + return error; +} diff --git a/tests/countertest/src/enable.c b/tests/countertest/src/enable.c new file mode 100644 index 00000000..8eb7e7a7 --- /dev/null +++ b/tests/countertest/src/enable.c @@ -0,0 +1,18 @@ + +#include +#include +#include +#include +#include + +#include "priv.h" +#include "countertest.h" +#include "enable.h" + +// define all check_enable_* function +MAP(CSR_ALL_UNPRIV_COUNTER, def_func_check_enable) + +// link all check_enable_* function to array of function pointers +func_void_t check_enable_func_arr[32] = { + MAP(CSR_ALL_UNPRIV_COUNTER, list_func_check_enable) +}; diff --git a/tests/countertest/src/priv.c b/tests/countertest/src/priv.c index 71f2e8f5..af3a5e91 100644 --- a/tests/countertest/src/priv.c +++ b/tests/countertest/src/priv.c @@ -32,8 +32,8 @@ volatile int m_exception_handler( } // other exceptions should be expected by main program - assert(last_exception.expected); - last_exception.expected = 0; + assert(last_exception.expected_trap); + last_exception.actual_trap = 1; // epc to next uint64_t this_mepc = csr_read(mepc); @@ -98,3 +98,16 @@ void do_ecall( "+r" (a4), "+r" (a5), "+r" (a6), "+r" (a7)); } +void setup_expected_exception() { + last_exception.expected_trap = 1; + last_exception.actual_trap = 0; + last_exception.cause = 0; + last_exception.epc = 0; +} + +void clear_last_exception() { + last_exception.expected_trap = 0; + last_exception.actual_trap = 0; + last_exception.cause = 0; + last_exception.epc = 0; +} diff --git a/tests/countertest/src/trap.S b/tests/countertest/src/trap.S index 0b2e4a24..65aa6ec0 100644 --- a/tests/countertest/src/trap.S +++ b/tests/countertest/src/trap.S @@ -81,7 +81,8 @@ .endm # entry to trap into M-mode -.balign 0x4 +.text +.align 4 .global m_trap_entry m_trap_entry: SAVE_CONTEXT