countertest: support tests for all *counteren

This commit is contained in:
Xu, Zefan 2024-05-28 22:05:42 +08:00
parent 8e2aa1de33
commit 6f4db8e1f7
7 changed files with 193 additions and 27 deletions

View File

@ -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__

View File

@ -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__

View File

@ -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__
void setup_expected_exception();
void clear_last_exception();
#endif // __PRIV_H__

View File

@ -6,34 +6,24 @@
#include <klib-macros.h>
#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;
}
return error;
}

View File

@ -0,0 +1,18 @@
#include <am.h>
#include <csr.h>
#include <xsextra.h>
#include <klib.h>
#include <klib-macros.h>
#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)
};

View File

@ -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;
}

View File

@ -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