Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(mhpmevent): add struct, rtl guidance and legal check for mhpmevent csr #574

Merged
merged 3 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/isa.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,5 +87,6 @@ void *isa_difftest_query_br_log(void);
void isa_difftest_set_mhartid(int n);
#endif
void isa_update_mip(unsigned lcofip);
void isa_update_mhpmcounter_overflow(uint64_t mhpmeventOverflowVec);

#endif
6 changes: 6 additions & 0 deletions src/cpu/difftest/ref.c
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,12 @@ void difftest_virtual_interrupt_is_hvictl_inject(bool virtualInterruptIsHvictlIn
#endif
}

void difftest_raise_mhpmevent_overflow(uint64_t mhpmeventOverflowVec) {
#ifdef CONFIG_RV_SSCOFPMF
isa_update_mhpmcounter_overflow(mhpmeventOverflowVec);
#endif
}

void difftest_non_reg_interrupt_pending(void *nonRegInterruptPending) {
memcpy(&cpu.non_reg_interrupt_pending, nonRegInterruptPending, sizeof(struct NonRegInterruptPending));
isa_update_mip(cpu.non_reg_interrupt_pending.lcofi_req);
Expand Down
11 changes: 10 additions & 1 deletion src/isa/riscv64/difftest/ref.c
Original file line number Diff line number Diff line change
Expand Up @@ -419,4 +419,13 @@ void isa_difftest_set_mhartid(int n) {

void isa_update_mip(unsigned lcofip) {
mip->lcofip = lcofip;
}
}

void isa_update_mhpmcounter_overflow(uint64_t mhpmeventOverflowVec) {
#ifdef CONFIG_RV_SSCOFPMF
for (int i = 0; i < 29; i++) {
mhpmevent3_t* current_hpm = (mhpmevent3_t*)&csr_array[CSR_MHPMEVENT_BASE + i];
current_hpm->of = (mhpmeventOverflowVec >> i) & 0x1;
}
#endif
}
5 changes: 4 additions & 1 deletion src/isa/riscv64/include/isa-def.h
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,10 @@ typedef struct {
} instr;
} riscv64_ISADecodeInfo;

enum { MODE_U = 0, MODE_S, MODE_HS, MODE_M };
// MODE_RS:reservation mode for mpp
enum { MODE_U = 0, MODE_S, MODE_RS, MODE_M };

enum { OP_OR = 0, OP_AND, OP_XOR, OP_ADD = 4 };

int get_data_mmu_state();
#ifdef CONFIG_RVH
Expand Down
26 changes: 24 additions & 2 deletions src/isa/riscv64/local-include/csr.h
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@
f(mhpmevent16 , 0x330) f(mhpmevent17 , 0x331) f(mhpmevent18 , 0x332) f(mhpmevent19 , 0x333) \
f(mhpmevent20 , 0x334) f(mhpmevent21 , 0x335) f(mhpmevent22 , 0x336) f(mhpmevent23 , 0x337) \
f(mhpmevent24 , 0x338) f(mhpmevent25 , 0x339) f(mhpmevent26 , 0x33A) f(mhpmevent27 , 0x33B) \
f(mhpmevent28 , 0x33C) f(mhpmevent29 , 0x33D) f(mhpmevent30 , 0x33E) f(mhpmeven31 , 0x33F)
f(mhpmevent28 , 0x33C) f(mhpmevent29 , 0x33D) f(mhpmevent30 , 0x33E) f(mhpmevent31 , 0x33F)

#ifdef CONFIG_RV_CSR_MCOUNTINHIBIT
#define CSRS_M_MCOUNTINHIBIT(f) \
Expand Down Expand Up @@ -623,7 +623,29 @@ CSR_STRUCT_START(minstret)
CSR_STRUCT_END(minstret)

CSR_STRUCT_DUMMY_LIST(CSRS_M_HPMCOUNTER)
CSR_STRUCT_DUMMY_LIST(CSRS_M_HPMEVENT)

#define CSRS_M_HPMEVENTS_STRUCT(name, addr) \
typedef union { \
struct { \
uint64_t event0 : 10; \
uint64_t event1 : 10; \
uint64_t event2 : 10; \
uint64_t event3 : 10; \
uint64_t optype0 : 5; \
uint64_t optype1 : 5; \
uint64_t optype2 : 5; \
uint64_t pad0 : 3; \
uint64_t vuinh : 1; \
uint64_t vsinh : 1; \
uint64_t uinh : 1; \
uint64_t sinh : 1; \
uint64_t minh : 1; \
uint64_t of : 1; \
}; \
word_t val; \
} concat(name, _t);

MAP(CSRS_M_HPMEVENT, CSRS_M_HPMEVENTS_STRUCT)

CSR_STRUCT_START(mcounteren)
CSR_STRUCT_END(mcounteren)
Expand Down
76 changes: 72 additions & 4 deletions src/isa/riscv64/system/priv.c
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,36 @@ static inline word_t* csr_decode(uint32_t addr) {
#define HSTATEEN0_WMASK 0xdc00000000000001ULL
#define SSTATEEN0_WMASK 0x0000000000000001ULL // 32 bits

#define MHPMEVENT_WMASK_OF (0x1UL << 63)
#define MHPMEVENT_WMASK_MINH (0x1UL << 62)
#define MHPMEVENT_WMASK_SINH (0x1UL << 61)
#define MHPMEVENT_WMASK_UINH (0x1UL << 60)
#define MHPMEVENT_WMASK_VSINH (0x1UL << 59)
#define MHPMEVENT_WMASK_VUINH (0x1UL << 58)
#define MHPMEVENT_WMASK_OPTYPE2 (0X1FUL << 50)
#define MHPMEVENT_WMASK_OPTYPE1 (0X1FUL << 45)
#define MHPMEVENT_WMASK_OPTYPE0 (0X1FUL << 40)
#define MHPMEVENT_WMASK_EVENT3 (0X3FFUL << 30)
#define MHPMEVENT_WMASK_EVENT2 (0X3FFUL << 20)
#define MHPMEVENT_WMASK_EVENT1 (0X3FFUL << 10)
#define MHPMEVENT_WMASK_EVENT0 (0X3FFUL << 0)

#define MHPMEVENT_WMASK ( \
MHPMEVENT_WMASK_OF | \
MHPMEVENT_WMASK_MINH | \
MHPMEVENT_WMASK_SINH | \
MHPMEVENT_WMASK_UINH | \
MHPMEVENT_WMASK_VSINH | \
MHPMEVENT_WMASK_VUINH | \
MHPMEVENT_WMASK_OPTYPE2 | \
MHPMEVENT_WMASK_OPTYPE1 | \
MHPMEVENT_WMASK_OPTYPE0 | \
MHPMEVENT_WMASK_EVENT3 | \
MHPMEVENT_WMASK_EVENT2 | \
MHPMEVENT_WMASK_EVENT1 | \
MHPMEVENT_WMASK_EVENT0 \
)

#define is_read(csr) (src == (void *)(csr))
#define is_write(csr) (dest == (void *)(csr))
#define is_access(csr) (dest_access == (void *)(csr))
Expand Down Expand Up @@ -578,6 +608,15 @@ static inline word_t gen_mask(word_t begin, word_t end) {
return tmp_mask;
}

static inline bool hpmevent_op_islegal(unsigned new_val) {
switch (new_val) {
case OP_OR: case OP_AND: case OP_XOR: case OP_ADD:
return true;
default:
return false;
}
}

#ifdef CONFIG_RV_AIA
static inline word_t vmode_get_ie(word_t old_value, word_t begin, word_t end) {
word_t mask = gen_mask(begin, end);
Expand Down Expand Up @@ -1305,6 +1344,7 @@ static inline void csr_write(word_t *dest, word_t src) {
update_vsatp(new_val);
}else if (is_write(mstatus)) {
uint64_t mstatus_wmask = MSTATUS_WMASK;
unsigned prev_mpp = mstatus->mpp;
// only when reg.MDT is zero or wdata.MDT is zero , MIE can be explicitly written by 1
#ifdef CONFIG_RV_SMDBLTRP
if (src & MSTATUS_MIE) {
Expand All @@ -1327,7 +1367,11 @@ static inline void csr_write(word_t *dest, word_t src) {
}
#endif //CONFIG_RV_SSDBLTRP
mstatus->val = mask_bitset(mstatus->val, mstatus_wmask, src);
update_mmu_state(); // maybe this write update mprv, mpp or mpv
if (mstatus->mpp == MODE_RS) {
// MODE_RS is reserved. write will not take effect.
mstatus->mpp = prev_mpp;
}
update_mmu_state(); // maybe write update mprv, mpp or mpv
#ifdef CONFIG_RV_SMDBLTRP
// when MDT is explicitly written by 1, clear MIE
if (src & MSTATUS_WMASK_MDT) { mstatus->mie = 0; }
Expand Down Expand Up @@ -1355,8 +1399,8 @@ static inline void csr_write(word_t *dest, word_t src) {
// by writing that mode to MPP then reading it back. If the machine
// provides only U and M modes, then only a single hardware storage bit
// is required to represent either 00 or 11 in MPP.
if (mstatus->mpp == MODE_HS) {
// MODE_H is not implemented. The write will not take effect.
if (mstatus->mpp == MODE_RS) {
// MODE_RS is reserved. The write will not take effect.
mstatus->mpp = prev_mpp;
}
#endif // CONFIG_RVH
Expand Down Expand Up @@ -1386,10 +1430,14 @@ static inline void csr_write(word_t *dest, word_t src) {
else if (is_write(mnscratch)) { *dest = src; }
else if (is_write(mnstatus)) {
word_t mnstatus_mask = MNSTATUS_MASK;
unsigned pre_mnpp = mnstatus->mnpp;
// if ((src & MNSTATUS_NMIE) == 0) {
// mnstatus_mask &= ~MNSTATUS_NMIE;
// }
mnstatus->val = mask_bitset(mnstatus->val, mnstatus_mask, src);
if (mnstatus->mnpp == MODE_RS) {
mnstatus->mnpp = pre_mnpp;
}
}
#endif //CONFIG_RV_SMRNMI
#ifdef CONFIG_RVH
Expand Down Expand Up @@ -1627,7 +1675,27 @@ static inline void csr_write(word_t *dest, word_t src) {
// When MODE=Bare, software should set the remaining fields in hgatp to zeros, not hardware.
}
#endif// CONFIG_RVH
else if (is_mhpmcounter(dest) || is_mhpmevent(dest)) {
else if (is_mhpmevent(dest)) {
mhpmevent3_t *mhpmevent = (mhpmevent3_t *)dest;
unsigned pre_op0 = mhpmevent->optype0;
unsigned pre_op1 = mhpmevent->optype1;
unsigned pre_op2 = mhpmevent->optype2;
mhpmevent3_t new_val;
new_val.val = src;

*dest = src & MHPMEVENT_WMASK;

if (!hpmevent_op_islegal(new_val.optype0)) {
mhpmevent->optype0 = pre_op0;
}
if (!hpmevent_op_islegal(new_val.optype1)) {
mhpmevent->optype1 = pre_op1;
}
if (!hpmevent_op_islegal(new_val.optype2)) {
mhpmevent->optype2 = pre_op2;
}
}
else if (is_mhpmcounter(dest)) {
// read-only zero in NEMU
return;
}
Expand Down